Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
diff --git a/CREDITS b/CREDITS
index 8e577ce..6957ef4 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3101,7 +3101,7 @@
 S: Australia
 
 N: Stephen Smalley
-E: sds@epoch.ncsc.mil
+E: sds@tycho.nsa.gov
 D: portions of the Linux Security Module (LSM) framework and security modules
 
 N: Chris Smith
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
index fcbcbc3..6221464 100644
--- a/Documentation/RCU/RTFP.txt
+++ b/Documentation/RCU/RTFP.txt
@@ -90,16 +90,20 @@
 following year [McKenney02a], and use of RCU in dcache was first
 described that same year [Linder02a].
 
-Also in 2002, Michael [Michael02b,Michael02a] presented techniques
-that defer the destruction of data structures to simplify non-blocking
-synchronization (wait-free synchronization, lock-free synchronization,
-and obstruction-free synchronization are all examples of non-blocking
-synchronization).  In particular, this technique eliminates locking,
-reduces contention, reduces memory latency for readers, and parallelizes
-pipeline stalls and memory latency for writers.  However, these
-techniques still impose significant read-side overhead in the form of
-memory barriers.  Researchers at Sun worked along similar lines in the
-same timeframe [HerlihyLM02,HerlihyLMS03].
+Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer"
+techniques that defer the destruction of data structures to simplify
+non-blocking synchronization (wait-free synchronization, lock-free
+synchronization, and obstruction-free synchronization are all examples of
+non-blocking synchronization).  In particular, this technique eliminates
+locking, reduces contention, reduces memory latency for readers, and
+parallelizes pipeline stalls and memory latency for writers.  However,
+these techniques still impose significant read-side overhead in the
+form of memory barriers.  Researchers at Sun worked along similar lines
+in the same timeframe [HerlihyLM02,HerlihyLMS03].  These techniques
+can be thought of as inside-out reference counts, where the count is
+represented by the number of hazard pointers referencing a given data
+structure (rather than the more conventional counter field within the
+data structure itself).
 
 In 2003, the K42 group described how RCU could be used to create
 hot-pluggable implementations of operating-system functions.  Later that
@@ -113,7 +117,6 @@
 describing how to make RCU safe for soft-realtime applications [Sarma04c],
 and a paper describing SELinux performance with RCU [JamesMorris04b].
 
-
 2005 has seen further adaptation of RCU to realtime use, permitting
 preemption of RCU realtime critical sections [PaulMcKenney05a,
 PaulMcKenney05b].
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index e118a7c..49e27cc 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -177,3 +177,9 @@
 
 	If you want to wait for some of these other things, you might
 	instead need to use synchronize_irq() or synchronize_sched().
+
+12.	Any lock acquired by an RCU callback must be acquired elsewhere
+	with irq disabled, e.g., via spin_lock_irqsave().  Failing to
+	disable irq on a given acquisition of that lock will result in
+	deadlock as soon as the RCU callback happens to interrupt that
+	acquisition's critical section.
diff --git a/Documentation/RCU/listRCU.txt b/Documentation/RCU/listRCU.txt
index f8a54fa..1fd1753 100644
--- a/Documentation/RCU/listRCU.txt
+++ b/Documentation/RCU/listRCU.txt
@@ -232,7 +232,7 @@
 return holding the per-entry spinlock, as ipc_lock() does in fact do.
 
 Quick Quiz:  Why does the search function need to return holding the
-per-entry lock for this deleted-flag technique to be helpful?
+	per-entry lock for this deleted-flag technique to be helpful?
 
 If the system-call audit module were to ever need to reject stale data,
 one way to accomplish this would be to add a "deleted" flag and a "lock"
@@ -275,8 +275,8 @@
 	{
 		struct audit_entry  *e;
 
-		/* Do not use the _rcu iterator here, since this is the only
-		 * deletion routine. */
+		/* Do not need to use the _rcu iterator here, since this
+		 * is the only deletion routine. */
 		list_for_each_entry(e, list, list) {
 			if (!audit_compare_rule(rule, &e->rule)) {
 				spin_lock(&e->lock);
@@ -304,9 +304,12 @@
 
 
 Answer to Quick Quiz
+	Why does the search function need to return holding the per-entry
+	lock for this deleted-flag technique to be helpful?
 
-If the search function drops the per-entry lock before returning, then
-the caller will be processing stale data in any case.  If it is really
-OK to be processing stale data, then you don't need a "deleted" flag.
-If processing stale data really is a problem, then you need to hold the
-per-entry lock across all of the code that uses the value looked up.
+	If the search function drops the per-entry lock before returning,
+	then the caller will be processing stale data in any case.  If it
+	is really OK to be processing stale data, then you don't need a
+	"deleted" flag.  If processing stale data really is a problem,
+	then you need to hold the per-entry lock across all of the code
+	that uses the value that was returned.
diff --git a/Documentation/RCU/rcu.txt b/Documentation/RCU/rcu.txt
index 6fa0922..02e27bf 100644
--- a/Documentation/RCU/rcu.txt
+++ b/Documentation/RCU/rcu.txt
@@ -111,6 +111,11 @@
 
 		You are reading it!
 
+	rcuref.txt
+
+		Describes how to combine use of reference counts
+		with RCU.
+
 	whatisRCU.txt
 
 		Overview of how the RCU implementation works.  Along
diff --git a/Documentation/RCU/rcuref.txt b/Documentation/RCU/rcuref.txt
index 3f60db41..451de2a 100644
--- a/Documentation/RCU/rcuref.txt
+++ b/Documentation/RCU/rcuref.txt
@@ -1,7 +1,7 @@
-Refcounter design for elements of lists/arrays protected by RCU.
+Reference-count design for elements of lists/arrays protected by RCU.
 
-Refcounting on elements of  lists which are protected by traditional
-reader/writer spinlocks or semaphores are straight forward as in:
+Reference counting on elements of lists which are protected by traditional
+reader/writer spinlocks or semaphores are straightforward:
 
 1.				2.
 add()				search_and_reference()
@@ -28,12 +28,12 @@
 					    ...
 					}
 
-If this list/array is made lock free using rcu as in changing the
-write_lock in add() and delete() to spin_lock and changing read_lock
+If this list/array is made lock free using RCU as in changing the
+write_lock() in add() and delete() to spin_lock and changing read_lock
 in search_and_reference to rcu_read_lock(), the atomic_get in
 search_and_reference could potentially hold reference to an element which
-has already been deleted from the list/array.  atomic_inc_not_zero takes
-care of this scenario. search_and_reference should look as;
+has already been deleted from the list/array.  Use atomic_inc_not_zero()
+in this scenario as follows:
 
 1.					2.
 add()					search_and_reference()
@@ -51,17 +51,16 @@
 release_referenced()			delete()
 {					{
     ...					    write_lock(&list_lock);
-    atomic_dec(&el->rc, relfunc)	    ...
-    ...					    delete_element
-}					    write_unlock(&list_lock);
- 					    ...
+    if (atomic_dec_and_test(&el->rc))       ...
+        call_rcu(&el->head, el_free);       delete_element
+    ...                                     write_unlock(&list_lock);
+} 					    ...
 					    if (atomic_dec_and_test(&el->rc))
 					        call_rcu(&el->head, el_free);
 					    ...
 					}
 
-Sometimes, reference to the element need to be obtained in the
-update (write) stream.  In such cases, atomic_inc_not_zero might be an
-overkill since the spinlock serialising list updates are held. atomic_inc
-is to be used in such cases.
-
+Sometimes, a reference to the element needs to be obtained in the
+update (write) stream.  In such cases, atomic_inc_not_zero() might be
+overkill, since we hold the update-side spinlock.  One might instead
+use atomic_inc() in such cases.
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 15da168..5ed85af 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -200,10 +200,11 @@
 	the new value, and also executes any memory-barrier instructions
 	required for a given CPU architecture.
 
-	Perhaps more important, it serves to document which pointers
-	are protected by RCU.  That said, rcu_assign_pointer() is most
-	frequently used indirectly, via the _rcu list-manipulation
-	primitives such as list_add_rcu().
+	Perhaps just as important, it serves to document (1) which
+	pointers are protected by RCU and (2) the point at which a
+	given structure becomes accessible to other CPUs.  That said,
+	rcu_assign_pointer() is most frequently used indirectly, via
+	the _rcu list-manipulation primitives such as list_add_rcu().
 
 rcu_dereference()
 
@@ -258,9 +259,11 @@
 	locking.
 
 	As with rcu_assign_pointer(), an important function of
-	rcu_dereference() is to document which pointers are protected
-	by RCU.  And, again like rcu_assign_pointer(), rcu_dereference()
-	is typically used indirectly, via the _rcu list-manipulation
+	rcu_dereference() is to document which pointers are protected by
+	RCU, in particular, flagging a pointer that is subject to changing
+	at any time, including immediately after the rcu_dereference().
+	And, again like rcu_assign_pointer(), rcu_dereference() is
+	typically used indirectly, via the _rcu list-manipulation
 	primitives, such as list_for_each_entry_rcu().
 
 The following diagram shows how each API communicates among the
@@ -327,7 +330,7 @@
 3.  WHAT ARE SOME EXAMPLE USES OF CORE RCU API?
 
 This section shows a simple use of the core RCU API to protect a
-global pointer to a dynamically allocated structure.  More typical
+global pointer to a dynamically allocated structure.  More-typical
 uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt.
 
 	struct foo {
@@ -410,6 +413,8 @@
 	data item.
 
 See checklist.txt for additional rules to follow when using RCU.
+And again, more-typical uses of RCU may be found in listRCU.txt,
+arrayRCU.txt, and NMI-RCU.txt.
 
 
 4.  WHAT IF MY UPDATING THREAD CANNOT BLOCK?
@@ -513,7 +518,7 @@
 
 for papers describing the Linux kernel RCU implementation.  The OLS'01
 and OLS'02 papers are a good introduction, and the dissertation provides
-more details on the current implementation.
+more details on the current implementation as of early 2004.
 
 
 5A.  "TOY" IMPLEMENTATION #1: LOCKING
@@ -768,7 +773,6 @@
 	rcu_dereference
 	list_for_each_rcu		(to be deprecated in favor of
 					 list_for_each_entry_rcu)
-	list_for_each_safe_rcu		(deprecated, not used)
 	list_for_each_entry_rcu
 	list_for_each_continue_rcu	(to be deprecated in favor of new
 					 list_for_each_entry_continue_rcu)
@@ -807,7 +811,8 @@
 Answer:		Consider the following sequence of events:
 
 		1.	CPU 0 acquires some unrelated lock, call it
-			"problematic_lock".
+			"problematic_lock", disabling irq via
+			spin_lock_irqsave().
 
 		2.	CPU 1 enters synchronize_rcu(), write-acquiring
 			rcu_gp_mutex.
@@ -894,7 +899,7 @@
 ACKNOWLEDGEMENTS
 
 My thanks to the people who helped make this human-readable, including
-Jon Walpole, Josh Triplett, Serge Hallyn, and Suzanne Wood.
+Jon Walpole, Josh Triplett, Serge Hallyn, Suzanne Wood, and Alan Stern.
 
 
 For more information, see http://www.rdrop.com/users/paulmck/RCU.
diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt
new file mode 100644
index 0000000..ff280e2
--- /dev/null
+++ b/Documentation/cputopology.txt
@@ -0,0 +1,41 @@
+
+Export cpu topology info by sysfs. Items (attributes) are similar
+to /proc/cpuinfo.
+
+1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
+represent the physical package id of  cpu X;
+2) /sys/devices/system/cpu/cpuX/topology/core_id:
+represent the cpu core id to cpu X;
+3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
+represent the thread siblings to cpu X in the same core;
+4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
+represent the thread siblings to cpu X in the same physical package;
+
+To implement it in an architecture-neutral way, a new source file,
+driver/base/topology.c, is to export the 5 attributes.
+
+If one architecture wants to support this feature, it just needs to
+implement 4 defines, typically in file include/asm-XXX/topology.h.
+The 4 defines are:
+#define topology_physical_package_id(cpu)
+#define topology_core_id(cpu)
+#define topology_thread_siblings(cpu)
+#define topology_core_siblings(cpu)
+
+The type of **_id is int.
+The type of siblings is cpumask_t.
+
+To be consistent on all architectures, the 4 attributes should have
+deafult values if their values are unavailable. Below is the rule.
+1) physical_package_id: If cpu has no physical package id, -1 is the
+default value.
+2) core_id: If cpu doesn't support multi-core, its core id is 0.
+3) thread_siblings: Just include itself, if the cpu doesn't support
+HT/multi-thread.
+4) core_siblings: Just include itself, if the cpu doesn't support
+multi-core and HT/Multi-thread.
+
+So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
+
+If an attribute isn't defined on an architecture, it won't be exported.
+
diff --git a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt
index 4466273..ac4a7a7 100644
--- a/Documentation/driver-model/overview.txt
+++ b/Documentation/driver-model/overview.txt
@@ -1,50 +1,43 @@
 The Linux Kernel Device Model
 
-Patrick Mochel	<mochel@osdl.org>
+Patrick Mochel	<mochel@digitalimplant.org>
 
-26 August 2002
+Drafted 26 August 2002
+Updated 31 January 2006
 
 
 Overview
 ~~~~~~~~
 
-This driver model is a unification of all the current, disparate driver models
-that are currently in the kernel. It is intended to augment the
+The Linux Kernel Driver Model is a unification of all the disparate driver
+models that were previously used in the kernel. It is intended to augment the
 bus-specific drivers for bridges and devices by consolidating a set of data
 and operations into globally accessible data structures.
 
-Current driver models implement some sort of tree-like structure (sometimes
-just a list) for the devices they control. But, there is no linkage between
-the different bus types.
+Traditional driver models implemented some sort of tree-like structure
+(sometimes just a list) for the devices they control. There wasn't any
+uniformity across the different bus types.
 
-A common data structure can provide this linkage with little overhead: when a
-bus driver discovers a particular device, it can insert it into the global
-tree as well as its local tree. In fact, the local tree becomes just a subset
-of the global tree.
+The current driver model provides a comon, uniform data model for describing
+a bus and the devices that can appear under the bus. The unified bus
+model includes a set of common attributes which all busses carry, and a set
+of common callbacks, such as device discovery during bus probing, bus
+shutdown, bus power management, etc.
 
-Common data fields can also be moved out of the local bus models into the
-global model. Some of the manipulations of these fields can also be
-consolidated. Most likely, manipulation functions will become a set
-of helper functions, which the bus drivers wrap around to include any
-bus-specific items.
-
-The common device and bridge interface currently reflects the goals of the
-modern PC: namely the ability to do seamless Plug and Play, power management,
-and hot plug. (The model dictated by Intel and Microsoft (read: ACPI) ensures
-us that any device in the system may fit any of these criteria.)
-
-In reality, not every bus will be able to support such operations. But, most
-buses will support a majority of those operations, and all future buses will.
-In other words, a bus that doesn't support an operation is the exception,
-instead of the other way around.
-
+The common device and bridge interface reflects the goals of the modern
+computer: namely the ability to do seamless device "plug and play", power
+management, and hot plug. In particular, the model dictated by Intel and
+Microsoft (namely ACPI) ensures that almost every device on almost any bus
+on an x86-compatible system can work within this paradigm.  Of course,
+not every bus is able to support all such operations, although most
+buses support a most of those operations.
 
 
 Downstream Access
 ~~~~~~~~~~~~~~~~~
 
 Common data fields have been moved out of individual bus layers into a common
-data structure. But, these fields must still be accessed by the bus layers,
+data structure. These fields must still be accessed by the bus layers,
 and sometimes by the device-specific drivers.
 
 Other bus layers are encouraged to do what has been done for the PCI layer.
@@ -53,7 +46,7 @@
 struct pci_dev {
 	...
 
-	struct device device;
+	struct device dev;
 };
 
 Note first that it is statically allocated. This means only one allocation on
@@ -64,9 +57,9 @@
 
 The PCI bus layer freely accesses the fields of struct device. It knows about
 the structure of struct pci_dev, and it should know the structure of struct
-device. PCI devices that have been converted generally do not touch the fields
-of struct device. More precisely, device-specific drivers should not touch
-fields of struct device unless there is a strong compelling reason to do so.
+device. Individual PCI device drivers that have been converted the the current
+driver model generally do not and should not touch the fields of struct device,
+unless there is a strong compelling reason to do so.
 
 This abstraction is prevention of unnecessary pain during transitional phases.
 If the name of the field changes or is removed, then every downstream driver
diff --git a/Documentation/drivers/edac/edac.txt b/Documentation/drivers/edac/edac.txt
new file mode 100644
index 0000000..d37191f
--- /dev/null
+++ b/Documentation/drivers/edac/edac.txt
@@ -0,0 +1,673 @@
+
+
+EDAC - Error Detection And Correction
+
+Written by Doug Thompson <norsk5@xmission.com>
+7 Dec 2005
+
+
+EDAC was written by:
+	Thayne Harbaugh,
+	modified by Dave Peterson, Doug Thompson, et al,
+	from the bluesmoke.sourceforge.net project.
+
+
+============================================================================
+EDAC PURPOSE
+
+The 'edac' kernel module goal is to detect and report errors that occur
+within the computer system. In the initial release, memory Correctable Errors
+(CE) and Uncorrectable Errors (UE) are the primary errors being harvested.
+
+Detecting CE events, then harvesting those events and reporting them,
+CAN be a predictor of future UE events.  With CE events, the system can
+continue to operate, but with less safety. Preventive maintainence and
+proactive part replacement of memory DIMMs exhibiting CEs can reduce
+the likelihood of the dreaded UE events and system 'panics'.
+
+
+In addition, PCI Bus Parity and SERR Errors are scanned for on PCI devices
+in order to determine if errors are occurring on data transfers.
+The presence of PCI Parity errors must be examined with a grain of salt.
+There are several addin adapters that do NOT follow the PCI specification
+with regards to Parity generation and reporting. The specification says
+the vendor should tie the parity status bits to 0 if they do not intend
+to generate parity.  Some vendors do not do this, and thus the parity bit
+can "float" giving false positives.
+
+The PCI Parity EDAC device has the ability to "skip" known flakey
+cards during the parity scan. These are set by the parity "blacklist"
+interface in the sysfs for PCI Parity. (See the PCI section in the sysfs
+section below.) There is also a parity "whitelist" which is used as
+an explicit list of devices to scan, while the blacklist is a list
+of devices to skip.
+
+EDAC will have future error detectors that will be added or integrated
+into EDAC in the following list:
+
+	MCE	Machine Check Exception
+	MCA	Machine Check Architecture
+	NMI	NMI notification of ECC errors
+	MSRs 	Machine Specific Register error cases
+	and other mechanisms.
+
+These errors are usually bus errors, ECC errors, thermal throttling
+and the like.
+
+
+============================================================================
+EDAC VERSIONING
+
+EDAC is composed of a "core" module (edac_mc.ko) and several Memory
+Controller (MC) driver modules. On a given system, the CORE
+is loaded and one MC driver will be loaded. Both the CORE and
+the MC driver have individual versions that reflect current release
+level of their respective modules.  Thus, to "report" on what version
+a system is running, one must report both the CORE's and the
+MC driver's versions.
+
+
+LOADING
+
+If 'edac' was statically linked with the kernel then no loading is
+necessary.  If 'edac' was built as modules then simply modprobe the
+'edac' pieces that you need.  You should be able to modprobe
+hardware-specific modules and have the dependencies load the necessary core
+modules.
+
+Example:
+
+$> modprobe amd76x_edac
+
+loads both the amd76x_edac.ko memory controller module and the edac_mc.ko
+core module.
+
+
+============================================================================
+EDAC sysfs INTERFACE
+
+EDAC presents a 'sysfs' interface for control, reporting and attribute
+reporting purposes.
+
+EDAC lives in the /sys/devices/system/edac directory. Within this directory
+there currently reside 2 'edac' components:
+
+	mc	memory controller(s) system
+	pci	PCI status system
+
+
+============================================================================
+Memory Controller (mc) Model
+
+First a background on the memory controller's model abstracted in EDAC.
+Each mc device controls a set of DIMM memory modules. These modules are
+layed out in a Chip-Select Row (csrowX) and Channel table (chX). There can
+be multiple csrows and two channels.
+
+Memory controllers allow for several csrows, with 8 csrows being a typical value.
+Yet, the actual number of csrows depends on the electrical "loading"
+of a given motherboard, memory controller and DIMM characteristics.
+
+Dual channels allows for 128 bit data transfers to the CPU from memory.
+
+
+		Channel 0	Channel 1
+	===================================
+	csrow0	| DIMM_A0	| DIMM_B0 |
+	csrow1	| DIMM_A0	| DIMM_B0 |
+	===================================
+
+	===================================
+	csrow2	| DIMM_A1	| DIMM_B1 |
+	csrow3	| DIMM_A1	| DIMM_B1 |
+	===================================
+
+In the above example table there are 4 physical slots on the motherboard
+for memory DIMMs:
+
+	DIMM_A0
+	DIMM_B0
+	DIMM_A1
+	DIMM_B1
+
+Labels for these slots are usually silk screened on the motherboard. Slots
+labeled 'A' are channel 0 in this example. Slots labled 'B'
+are channel 1. Notice that there are two csrows possible on a
+physical DIMM. These csrows are allocated their csrow assignment
+based on the slot into which the memory DIMM is placed. Thus, when 1 DIMM
+is placed in each Channel, the csrows cross both DIMMs.
+
+Memory DIMMs come single or dual "ranked". A rank is a populated csrow.
+Thus, 2 single ranked DIMMs, placed in slots DIMM_A0 and DIMM_B0 above
+will have 1 csrow, csrow0. csrow1 will be empty. On the other hand,
+when 2 dual ranked DIMMs are similiaryly placed, then both csrow0 and
+csrow1 will be populated. The pattern repeats itself for csrow2 and
+csrow3.
+
+The representation of the above is reflected in the directory tree
+in EDAC's sysfs interface. Starting in directory
+/sys/devices/system/edac/mc each memory controller will be represented
+by its own 'mcX' directory, where 'X" is the index of the MC.
+
+
+	..../edac/mc/
+		   |
+		   |->mc0
+		   |->mc1
+		   |->mc2
+		   ....
+
+Under each 'mcX' directory each 'csrowX' is again represented by a
+'csrowX', where 'X" is the csrow index:
+
+
+	.../mc/mc0/
+		|
+		|->csrow0
+		|->csrow2
+		|->csrow3
+		....
+
+Notice that there is no csrow1, which indicates that csrow0 is
+composed of a single ranked DIMMs. This should also apply in both
+Channels, in order to have dual-channel mode be operational. Since
+both csrow2 and csrow3 are populated, this indicates a dual ranked
+set of DIMMs for channels 0 and 1.
+
+
+Within each of the 'mc','mcX' and 'csrowX' directories are several
+EDAC control and attribute files.
+
+
+============================================================================
+DIRECTORY 'mc'
+
+In directory 'mc' are EDAC system overall control and attribute files:
+
+
+Panic on UE control file:
+
+	'panic_on_ue'
+
+	An uncorrectable error will cause a machine panic.  This is usually
+	desirable.  It is a bad idea to continue when an uncorrectable error
+	occurs - it is indeterminate what was uncorrected and the operating
+	system context might be so mangled that continuing will lead to further
+	corruption. If the kernel has MCE configured, then EDAC will never
+	notice the UE.
+
+	LOAD TIME: module/kernel parameter: panic_on_ue=[0|1]
+
+	RUN TIME:  echo "1" >/sys/devices/system/edac/mc/panic_on_ue
+
+
+Log UE control file:
+
+	'log_ue'
+
+	Generate kernel messages describing uncorrectable errors.  These errors
+	are reported through the system message log system.  UE statistics
+	will be accumulated even when UE logging is disabled.
+
+	LOAD TIME: module/kernel parameter: log_ue=[0|1]
+
+	RUN TIME: echo "1" >/sys/devices/system/edac/mc/log_ue
+
+
+Log CE control file:
+
+	'log_ce'
+
+	Generate kernel messages describing correctable errors.  These
+	errors are reported through the system message log system.
+	CE statistics will be accumulated even when CE logging is disabled.
+
+	LOAD TIME: module/kernel parameter: log_ce=[0|1]
+
+	RUN TIME: echo "1" >/sys/devices/system/edac/mc/log_ce
+
+
+Polling period control file:
+
+	'poll_msec'
+
+	The time period, in milliseconds, for polling for error information.
+	Too small a value wastes resources.  Too large a value might delay
+	necessary handling of errors and might loose valuable information for
+	locating the error.  1000 milliseconds (once each second) is about
+	right for most uses.
+
+	LOAD TIME: module/kernel parameter: poll_msec=[0|1]
+
+	RUN TIME: echo "1000" >/sys/devices/system/edac/mc/poll_msec
+
+
+Module Version read-only attribute file:
+
+	'mc_version'
+
+	The EDAC CORE modules's version and compile date are shown here to
+	indicate what EDAC is running.
+
+
+
+============================================================================
+'mcX' DIRECTORIES
+
+
+In 'mcX' directories are EDAC control and attribute files for
+this 'X" instance of the memory controllers:
+
+
+Counter reset control file:
+
+	'reset_counters'
+
+	This write-only control file will zero all the statistical counters
+	for UE and CE errors.  Zeroing the counters will also reset the timer
+	indicating how long since the last counter zero.  This is useful
+	for computing errors/time.  Since the counters are always reset at
+	driver initialization time, no module/kernel parameter is available.
+
+	RUN TIME: echo "anything" >/sys/devices/system/edac/mc/mc0/counter_reset
+
+		This resets the counters on memory controller 0
+
+
+Seconds since last counter reset control file:
+
+	'seconds_since_reset'
+
+	This attribute file displays how many seconds have elapsed since the
+	last counter reset. This can be used with the error counters to
+	measure error rates.
+
+
+
+DIMM capability attribute file:
+
+	'edac_capability'
+
+	The EDAC (Error Detection and Correction) capabilities/modes of
+	the memory controller hardware.
+
+
+DIMM Current Capability attribute file:
+
+	'edac_current_capability'
+
+	The EDAC capabilities available with the hardware
+	configuration.  This may not be the same as "EDAC capability"
+	if the correct memory is not used.  If a memory controller is
+	capable of EDAC, but DIMMs without check bits are in use, then
+	Parity, SECDED, S4ECD4ED capabilities will not be available
+	even though the memory controller might be capable of those
+	modes with the proper memory loaded.
+
+
+Memory Type supported on this controller attribute file:
+
+	'supported_mem_type'
+
+	This attribute file displays the memory type, usually
+	buffered and unbuffered DIMMs.
+
+
+Memory Controller name attribute file:
+
+	'mc_name'
+
+	This attribute file displays the type of memory controller
+	that is being utilized.
+
+
+Memory Controller Module name attribute file:
+
+	'module_name'
+
+	This attribute file displays the memory controller module name,
+	version and date built.  The name of the memory controller
+	hardware - some drivers work with multiple controllers and
+	this field shows which hardware is present.
+
+
+Total memory managed by this memory controller attribute file:
+
+	'size_mb'
+
+	This attribute file displays, in count of megabytes, of memory
+	that this instance of memory controller manages.
+
+
+Total Uncorrectable Errors count attribute file:
+
+	'ue_count'
+
+	This attribute file displays the total count of uncorrectable
+	errors that have occurred on this memory controller. If panic_on_ue
+	is set this counter will not have a chance to increment,
+	since EDAC will panic the system.
+
+
+Total UE count that had no information attribute fileY:
+
+	'ue_noinfo_count'
+
+	This attribute file displays the number of UEs that
+	have occurred have occurred with  no informations as to which DIMM
+	slot is having errors.
+
+
+Total Correctable Errors count attribute file:
+
+	'ce_count'
+
+	This attribute file displays the total count of correctable
+	errors that have occurred on this memory controller. This
+	count is very important to examine. CEs provide early
+	indications that a DIMM is beginning to fail. This count
+	field should be monitored for non-zero values and report
+	such information to the system administrator.
+
+
+Total Correctable Errors count attribute file:
+
+	'ce_noinfo_count'
+
+	This attribute file displays the number of CEs that
+	have occurred wherewith no informations as to which DIMM slot
+	is having errors. Memory is handicapped, but operational,
+	yet no information is available to indicate which slot
+	the failing memory is in. This count field should be also
+	be monitored for non-zero values.
+
+Device Symlink:
+
+	'device'
+
+	Symlink to the memory controller device
+
+
+
+============================================================================
+'csrowX' DIRECTORIES
+
+In the 'csrowX' directories are EDAC control and attribute files for
+this 'X" instance of csrow:
+
+
+Total Uncorrectable Errors count attribute file:
+
+	'ue_count'
+
+	This attribute file displays the total count of uncorrectable
+	errors that have occurred on this csrow. If panic_on_ue is set
+	this counter will not have a chance to increment, since EDAC
+	will panic the system.
+
+
+Total Correctable Errors count attribute file:
+
+	'ce_count'
+
+	This attribute file displays the total count of correctable
+	errors that have occurred on this csrow. This
+	count is very important to examine. CEs provide early
+	indications that a DIMM is beginning to fail. This count
+	field should be monitored for non-zero values and report
+	such information to the system administrator.
+
+
+Total memory managed by this csrow attribute file:
+
+	'size_mb'
+
+	This attribute file displays, in count of megabytes, of memory
+	that this csrow contatins.
+
+
+Memory Type attribute file:
+
+	'mem_type'
+
+	This attribute file will display what type of memory is currently
+	on this csrow. Normally, either buffered or unbuffered memory.
+
+
+EDAC Mode of operation attribute file:
+
+	'edac_mode'
+
+	This attribute file will display what type of Error detection
+	and correction is being utilized.
+
+
+Device type attribute file:
+
+	'dev_type'
+
+	This attribute file will display what type of DIMM device is
+	being utilized. Example:  x4
+
+
+Channel 0 CE Count attribute file:
+
+	'ch0_ce_count'
+
+	This attribute file will display the count of CEs on this
+	DIMM located in channel 0.
+
+
+Channel 0 UE Count attribute file:
+
+	'ch0_ue_count'
+
+	This attribute file will display the count of UEs on this
+	DIMM located in channel 0.
+
+
+Channel 0 DIMM Label control file:
+
+	'ch0_dimm_label'
+
+	This control file allows this DIMM to have a label assigned
+	to it. With this label in the module, when errors occur
+	the output can provide the DIMM label in the system log.
+	This becomes vital for panic events to isolate the
+	cause of the UE event.
+
+	DIMM Labels must be assigned after booting, with information
+	that correctly identifies the physical slot with its
+	silk screen label. This information is currently very
+	motherboard specific and determination of this information
+	must occur in userland at this time.
+
+
+Channel 1 CE Count attribute file:
+
+	'ch1_ce_count'
+
+	This attribute file will display the count of CEs on this
+	DIMM located in channel 1.
+
+
+Channel 1 UE Count attribute file:
+
+	'ch1_ue_count'
+
+	This attribute file will display the count of UEs on this
+	DIMM located in channel 0.
+
+
+Channel 1 DIMM Label control file:
+
+	'ch1_dimm_label'
+
+	This control file allows this DIMM to have a label assigned
+	to it. With this label in the module, when errors occur
+	the output can provide the DIMM label in the system log.
+	This becomes vital for panic events to isolate the
+	cause of the UE event.
+
+	DIMM Labels must be assigned after booting, with information
+	that correctly identifies the physical slot with its
+	silk screen label. This information is currently very
+	motherboard specific and determination of this information
+	must occur in userland at this time.
+
+
+============================================================================
+SYSTEM LOGGING
+
+If logging for UEs and CEs are enabled then system logs will have
+error notices indicating errors that have been detected:
+
+MC0: CE page 0x283, offset 0xce0, grain 8, syndrome 0x6ec3, row 0,
+channel 1 "DIMM_B1": amd76x_edac
+
+MC0: CE page 0x1e5, offset 0xfb0, grain 8, syndrome 0xb741, row 0,
+channel 1 "DIMM_B1": amd76x_edac
+
+
+The structure of the message is:
+	the memory controller			(MC0)
+	Error type				(CE)
+	memory page				(0x283)
+	offset in the page			(0xce0)
+	the byte granularity 			(grain 8)
+		or resolution of the error
+	the error syndrome			(0xb741)
+	memory row				(row 0)
+	memory channel				(channel 1)
+	DIMM label, if set prior		(DIMM B1
+	and then an optional, driver-specific message that may
+		have additional information.
+
+Both UEs and CEs with no info will lack all but memory controller,
+error type, a notice of "no info" and then an optional,
+driver-specific error message.
+
+
+
+============================================================================
+PCI Bus Parity Detection
+
+
+On Header Type 00 devices the primary status is looked at
+for any parity error regardless of whether Parity is enabled on the
+device.  (The spec indicates parity is generated in some cases).
+On Header Type 01 bridges, the secondary status register is also
+looked at to see if parity ocurred on the bus on the other side of
+the bridge.
+
+
+SYSFS CONFIGURATION
+
+Under /sys/devices/system/edac/pci are control and attribute files as follows:
+
+
+Enable/Disable PCI Parity checking control file:
+
+	'check_pci_parity'
+
+
+	This control file enables or disables the PCI Bus Parity scanning
+	operation. Writing a 1 to this file enables the scanning. Writing
+	a 0 to this file disables the scanning.
+
+	Enable:
+	echo "1" >/sys/devices/system/edac/pci/check_pci_parity
+
+	Disable:
+	echo "0" >/sys/devices/system/edac/pci/check_pci_parity
+
+
+
+Panic on PCI PARITY Error:
+
+	'panic_on_pci_parity'
+
+
+	This control files enables or disables panic'ing when a parity
+	error has been detected.
+
+
+	module/kernel parameter: panic_on_pci_parity=[0|1]
+
+	Enable:
+	echo "1" >/sys/devices/system/edac/pci/panic_on_pci_parity
+
+	Disable:
+	echo "0" >/sys/devices/system/edac/pci/panic_on_pci_parity
+
+
+Parity Count:
+
+	'pci_parity_count'
+
+	This attribute file will display the number of parity errors that
+	have been detected.
+
+
+
+PCI Device Whitelist:
+
+	'pci_parity_whitelist'
+
+	This control file allows for an explicit list of PCI devices to be
+	scanned for parity errors. Only devices found on this list will
+	be examined.  The list is a line of hexadecimel VENDOR and DEVICE
+	ID tuples:
+
+	1022:7450,1434:16a6
+
+	One or more can be inserted, seperated by a comma.
+
+	To write the above list doing the following as one command line:
+
+	echo "1022:7450,1434:16a6"
+		> /sys/devices/system/edac/pci/pci_parity_whitelist
+
+
+
+	To display what the whitelist is, simply 'cat' the same file.
+
+
+PCI Device Blacklist:
+
+	'pci_parity_blacklist'
+
+	This control file allows for a list of PCI devices to be
+	skipped for scanning.
+	The list is a line of hexadecimel VENDOR and DEVICE ID tuples:
+
+	1022:7450,1434:16a6
+
+	One or more can be inserted, seperated by a comma.
+
+	To write the above list doing the following as one command line:
+
+	echo "1022:7450,1434:16a6"
+		> /sys/devices/system/edac/pci/pci_parity_blacklist
+
+
+	To display what the whitelist current contatins,
+	simply 'cat' the same file.
+
+=======================================================================
+
+PCI Vendor and Devices IDs can be obtained with the lspci command. Using
+the -n option lspci will display the vendor and device IDs. The system
+adminstrator will have to determine which devices should be scanned or
+skipped.
+
+
+
+The two lists (white and black) are prioritized. blacklist is the lower
+priority and will NOT be utilized when a whitelist has been set.
+Turn OFF a whitelist by an empty echo command:
+
+	echo > /sys/devices/system/edac/pci/pci_parity_whitelist
+
+and any previous blacklist will be utililzed.
+
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index b4a1ea7..b730d76 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -148,3 +148,26 @@
 	brother on Alchemy SOCs.  The loss of features is not considered an
 	issue.
 Who:	Ralf Baechle <ralf@linux-mips.org>
+
+---------------------------
+
+What:	Legacy /proc/pci interface (PCI_LEGACY_PROC)
+When:	March 2006
+Why:	deprecated since 2.5.53 in favor of lspci(8)
+Who:	Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
+What:	pci_module_init(driver)
+When:	January 2007
+Why:	Is replaced by pci_register_driver(pci_driver).
+Who:	Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@suse.de>
+
+---------------------------
+
+What:	I2C interface of the it87 driver
+When:	January 2007
+Why:	The ISA interface is faster and should be always available. The I2C
+	probing is also known to cause trouble in at least one case (see
+	bug #5889.)
+Who:	Jean Delvare <khali@linux-fr.org>
diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example.c
index f3c6e49..3d4713a 100644
--- a/Documentation/filesystems/configfs/configfs_example.c
+++ b/Documentation/filesystems/configfs/configfs_example.c
@@ -320,6 +320,7 @@
 	.ct_item_ops	= &simple_children_item_ops,
 	.ct_group_ops	= &simple_children_group_ops,
 	.ct_attrs	= simple_children_attrs,
+	.ct_owner	= THIS_MODULE,
 };
 
 static struct configfs_subsystem simple_children_subsys = {
@@ -403,6 +404,7 @@
 	.ct_item_ops	= &group_children_item_ops,
 	.ct_group_ops	= &group_children_group_ops,
 	.ct_attrs	= group_children_attrs,
+	.ct_owner	= THIS_MODULE,
 };
 
 static struct configfs_subsystem group_children_subsys = {
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index f2595ca..4389c68 100644
--- a/Documentation/filesystems/ocfs2.txt
+++ b/Documentation/filesystems/ocfs2.txt
@@ -35,6 +35,7 @@
 	  be cluster coherent.
 	- quotas
 	- cluster aware flock
+	- cluster aware lockf
 	- Directory change notification (F_NOTIFY)
 	- Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
 	- POSIX ACLs
diff --git a/Documentation/hwmon/f71805f b/Documentation/hwmon/f71805f
new file mode 100644
index 0000000..28c5b7d
--- /dev/null
+++ b/Documentation/hwmon/f71805f
@@ -0,0 +1,105 @@
+Kernel driver f71805f
+=====================
+
+Supported chips:
+  * Fintek F71805F/FG
+    Prefix: 'f71805f'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Provided by Fintek on request
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Thanks to Denis Kieft from Barracuda Networks for the donation of a
+test system (custom Jetway K8M8MS motherboard, with CPU and RAM) and
+for providing initial documentation.
+
+Thanks to Kris Chen from Fintek for answering technical questions and
+providing additional documentation.
+
+Thanks to Chris Lin from Jetway for providing wiring schematics and
+anwsering technical questions.
+
+
+Description
+-----------
+
+The Fintek F71805F/FG Super I/O chip includes complete hardware monitoring
+capabilities. It can monitor up to 9 voltages (counting its own power
+source), 3 fans and 3 temperature sensors.
+
+This chip also has fan controlling features, using either DC or PWM, in
+three different modes (one manual, two automatic). The driver doesn't
+support these features yet.
+
+The driver assumes that no more than one chip is present, which seems
+reasonable.
+
+
+Voltage Monitoring
+------------------
+
+Voltages are sampled by an 8-bit ADC with a LSB of 8 mV. The supported
+range is thus from 0 to 2.040 V. Voltage values outside of this range
+need external resistors. An exception is in0, which is used to monitor
+the chip's own power source (+3.3V), and is divided internally by a
+factor 2.
+
+The two LSB of the voltage limit registers are not used (always 0), so
+you can only set the limits in steps of 32 mV (before scaling).
+
+The wirings and resistor values suggested by Fintek are as follow:
+
+        pin                                           expected
+        name    use           R1      R2     divider  raw val.
+
+in0     VCC     VCC3.3V     int.    int.        2.00    1.65 V
+in1     VIN1    VTT1.2V      10K       -        1.00    1.20 V
+in2     VIN2    VRAM        100K    100K        2.00   ~1.25 V (1)
+in3     VIN3    VCHIPSET     47K    100K        1.47    2.24 V (2)
+in4     VIN4    VCC5V       200K     47K        5.25    0.95 V
+in5     VIN5    +12V        200K     20K       11.00    1.05 V
+in6     VIN6    VCC1.5V      10K       -        1.00    1.50 V
+in7     VIN7    VCORE        10K       -        1.00   ~1.40 V (1)
+in8     VIN8    VSB5V       200K     47K        1.00    0.95 V
+
+(1) Depends on your hardware setup.
+(2) Obviously not correct, swapping R1 and R2 would make more sense.
+
+These values can be used as hints at best, as motherboard manufacturers
+are free to use a completely different setup. As a matter of fact, the
+Jetway K8M8MS uses a significantly different setup. You will have to
+find out documentation about your own motherboard, and edit sensors.conf
+accordingly.
+
+Each voltage measured has associated low and high limits, each of which
+triggers an alarm when crossed.
+
+
+Fan Monitoring
+--------------
+
+Fan rotation speeds are reported as 12-bit values from a gated clock
+signal. Speeds down to 366 RPM can be measured. There is no theoretical
+high limit, but values over 6000 RPM seem to cause problem. The effective
+resolution is much lower than you would expect, the step between different
+register values being 10 rather than 1.
+
+The chip assumes 2 pulse-per-revolution fans.
+
+An alarm is triggered if the rotation speed drops below a programmable
+limit or is too low to be measured.
+
+
+Temperature Monitoring
+----------------------
+
+Temperatures are reported in degrees Celsius. Each temperature measured
+has a high limit, those crossing triggers an alarm. There is an associated
+hysteresis value, below which the temperature has to drop before the
+alarm is cleared.
+
+All temperature channels are external, there is no embedded temperature
+sensor. Each channel can be used for connecting either a thermal diode
+or a thermistor. The driver reports the currently selected mode, but
+doesn't allow changing it. In theory, the BIOS should have configured
+everything properly.
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 7f42e44..9555be1 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -9,7 +9,7 @@
                http://www.ite.com.tw/
   * IT8712F
     Prefix: 'it8712'
-    Addresses scanned: I2C 0x28 - 0x2f
+    Addresses scanned: I2C 0x2d
                        from Super I/O config space (8 I/O ports)
     Datasheet: Publicly available at the ITE website
                http://www.ite.com.tw/
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index 764cdc5..a0d0ab2 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -179,11 +179,12 @@
 ****************
 
 temp[1-3]_type	Sensor type selection.
-		Integers 1, 2, 3 or thermistor Beta value (3435)
+		Integers 1 to 4 or thermistor Beta value (typically 3435)
 		Read/Write.
 		1: PII/Celeron Diode
 		2: 3904 transistor
 		3: thermal diode
+		4: thermistor (default/unknown Beta)
 		Not all types are supported by all chips
 
 temp[1-4]_max	Temperature max value.
@@ -261,6 +262,21 @@
 		of individual bits.
 		Bits are defined in kernel/include/sensors.h.
 
+alarms_in	Alarm bitmask relative to in (voltage) channels
+		Read only
+		A '1' bit means an alarm, LSB corresponds to in0 and so on
+		Prefered to 'alarms' for newer chips
+
+alarms_fan	Alarm bitmask relative to fan channels
+		Read only
+		A '1' bit means an alarm, LSB corresponds to fan1 and so on
+		Prefered to 'alarms' for newer chips
+
+alarms_temp	Alarm bitmask relative to temp (temperature) channels
+		Read only
+		A '1' bit means an alarm, LSB corresponds to temp1 and so on
+		Prefered to 'alarms' for newer chips
+
 beep_enable	Beep/interrupt enable
 		0 to disable.
 		1 to enable.
diff --git a/Documentation/i2c/busses/i2c-sis69x b/Documentation/i2c/busses/i2c-sis96x
similarity index 98%
rename from Documentation/i2c/busses/i2c-sis69x
rename to Documentation/i2c/busses/i2c-sis96x
index b88953d..00a009b 100644
--- a/Documentation/i2c/busses/i2c-sis69x
+++ b/Documentation/i2c/busses/i2c-sis96x
@@ -7,7 +7,7 @@
     Any combination of these host bridges:
 	645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746
     and these south bridges:
-    	961, 962, 963(L) 
+    	961, 962, 963(L)
 
 Author: Mark M. Hoffman <mhoffman@lightlink.com>
 
@@ -29,7 +29,7 @@
 
 or perhaps this...
 
-00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 
+00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
 00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961
 00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
 
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
index c406ce6..c65233d 100644
--- a/Documentation/kernel-doc-nano-HOWTO.txt
+++ b/Documentation/kernel-doc-nano-HOWTO.txt
@@ -45,10 +45,10 @@
 
 If you just want to read the ready-made books on the various
 subsystems (see Documentation/DocBook/*.tmpl), just type 'make
-psdocs', or 'make pdfdocs', or 'make htmldocs', depending on your 
-preference.  If you would rather read a different format, you can type 
-'make sgmldocs' and then use DocBook tools to convert 
-Documentation/DocBook/*.sgml to a format of your choice (for example, 
+psdocs', or 'make pdfdocs', or 'make htmldocs', depending on your
+preference.  If you would rather read a different format, you can type
+'make sgmldocs' and then use DocBook tools to convert
+Documentation/DocBook/*.sgml to a format of your choice (for example,
 'db2html ...' if 'make htmldocs' was not defined).
 
 If you want to see man pages instead, you can do this:
@@ -124,6 +124,36 @@
 Take a look around the source tree for examples.
 
 
+kernel-doc for structs, unions, enums, and typedefs
+---------------------------------------------------
+
+Beside functions you can also write documentation for structs, unions,
+enums and typedefs. Instead of the function name you must write the name
+of the declaration;  the struct/union/enum/typedef must always precede
+the name. Nesting of declarations is not supported.
+Use the argument mechanism to document members or constants.
+
+Inside a struct description, you can use the "private:" and "public:"
+comment tags.  Structure fields that are inside a "private:" area
+are not listed in the generated output documentation.
+
+Example:
+
+/**
+ * struct my_struct - short description
+ * @a: first member
+ * @b: second member
+ *
+ * Longer description
+ */
+struct my_struct {
+    int a;
+    int b;
+/* private: */
+    int c;
+};
+
+
 How to make new SGML template files
 -----------------------------------
 
@@ -147,4 +177,3 @@
 
 Tim.
 */ <twaugh@redhat.com>
-
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 1cbcf65..8437036 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -452,6 +452,11 @@
 
 	eata=		[HW,SCSI]
 
+	ec_intr=	[HW,ACPI] ACPI Embedded Controller interrupt mode
+			Format: <int>
+			0: polling mode
+			non-0: interrupt mode (default)
+
 	eda=		[HW,PS2]
 
 	edb=		[HW,PS2]
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 2b7cf19..26364d0 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -427,6 +427,23 @@
 	will avoid log file clutter.
 	Default: FALSE
 
+icmp_errors_use_inbound_ifaddr - BOOLEAN
+
+	If zero, icmp error messages are sent with the primary address of
+	the exiting interface.
+ 
+	If non-zero, the message will be sent with the primary address of
+	the interface that received the packet that caused the icmp error.
+	This is the behaviour network many administrators will expect from
+	a router. And it can make debugging complicated network layouts
+	much easier. 
+
+	Note that if no primary address exists for the interface selected,
+	then the primary address of the first non-loopback interface that
+	has one will be used regarldess of this setting.
+
+	Default: 0
+
 igmp_max_memberships - INTEGER
 	Change the maximum number of multicast groups we can subscribe to.
 	Default: 20
diff --git a/Documentation/parport-lowlevel.txt b/Documentation/parport-lowlevel.txt
index 1d40008..8f23024 100644
--- a/Documentation/parport-lowlevel.txt
+++ b/Documentation/parport-lowlevel.txt
@@ -1068,7 +1068,7 @@
 
 struct parport_operations {
 	...
-	void (*write_status) (struct parport *port, unsigned char s);
+	void (*write_control) (struct parport *port, unsigned char s);
 	...
 };
 
@@ -1097,9 +1097,9 @@
 
 struct parport_operations {
 	...
-	void (*frob_control) (struct parport *port,
-	                      unsigned char mask,
-			      unsigned char val);
+	unsigned char (*frob_control) (struct parport *port,
+				       unsigned char mask,
+				       unsigned char val);
 	...
 };
 
diff --git a/Documentation/pci-error-recovery.txt b/Documentation/pci-error-recovery.txt
index d089967..634d3e5 100644
--- a/Documentation/pci-error-recovery.txt
+++ b/Documentation/pci-error-recovery.txt
@@ -1,246 +1,396 @@
 
                        PCI Error Recovery
                        ------------------
-                         May 31, 2005
+                        February 2, 2006
 
-               Current document maintainer:
-           Linas Vepstas <linas@austin.ibm.com>
+                 Current document maintainer:
+             Linas Vepstas <linas@austin.ibm.com>
 
 
-Some PCI bus controllers are able to detect certain "hard" PCI errors
-on the bus, such as parity errors on the data and address busses, as
-well as SERR and PERR errors.  These chipsets are then able to disable
-I/O to/from the affected device, so that, for example, a bad DMA
-address doesn't end up corrupting system memory.  These same chipsets
-are also able to reset the affected PCI device, and return it to
-working condition.  This document describes a generic API form
-performing error recovery.
+Many PCI bus controllers are able to detect a variety of hardware
+PCI errors on the bus, such as parity errors on the data and address
+busses, as well as SERR and PERR errors.  Some of the more advanced
+chipsets are able to deal with these errors; these include PCI-E chipsets,
+and the PCI-host bridges found on IBM Power4 and Power5-based pSeries
+boxes. A typical action taken is to disconnect the affected device,
+halting all I/O to it.  The goal of a disconnection is to avoid system
+corruption; for example, to halt system memory corruption due to DMA's
+to "wild" addresses. Typically, a reconnection mechanism is also
+offered, so that the affected PCI device(s) are reset and put back
+into working condition. The reset phase requires coordination
+between the affected device drivers and the PCI controller chip.
+This document describes a generic API for notifying device drivers
+of a bus disconnection, and then performing error recovery.
+This API is currently implemented in the 2.6.16 and later kernels.
 
-The core idea is that after a PCI error has been detected, there must
-be a way for the kernel to coordinate with all affected device drivers
-so that the pci card can be made operational again, possibly after
-performing a full electrical #RST of the PCI card.  The API below
-provides a generic API for device drivers to be notified of PCI
-errors, and to be notified of, and respond to, a reset sequence.
+Reporting and recovery is performed in several steps. First, when
+a PCI hardware error has resulted in a bus disconnect, that event
+is reported as soon as possible to all affected device drivers,
+including multiple instances of a device driver on multi-function
+cards. This allows device drivers to avoid deadlocking in spinloops,
+waiting for some i/o-space register to change, when it never will.
+It also gives the drivers a chance to defer incoming I/O as
+needed.
 
-Preliminary sketch of API, cut-n-pasted-n-modified email from
-Ben Herrenschmidt, circa 5 april 2005
+Next, recovery is performed in several stages. Most of the complexity
+is forced by the need to handle multi-function devices, that is,
+devices that have multiple device drivers associated with them.
+In the first stage, each driver is allowed to indicate what type
+of reset it desires, the choices being a simple re-enabling of I/O
+or requesting a hard reset (a full electrical #RST of the PCI card).
+If any driver requests a full reset, that is what will be done.
+
+After a full reset and/or a re-enabling of I/O, all drivers are
+again notified, so that they may then perform any device setup/config
+that may be required.  After these have all completed, a final
+"resume normal operations" event is sent out.
+
+The biggest reason for choosing a kernel-based implementation rather
+than a user-space implementation was the need to deal with bus
+disconnects of PCI devices attached to storage media, and, in particular,
+disconnects from devices holding the root file system.  If the root
+file system is disconnected, a user-space mechanism would have to go
+through a large number of contortions to complete recovery. Almost all
+of the current Linux file systems are not tolerant of disconnection
+from/reconnection to their underlying block device. By contrast,
+bus errors are easy to manage in the device driver. Indeed, most
+device drivers already handle very similar recovery procedures;
+for example, the SCSI-generic layer already provides significant
+mechanisms for dealing with SCSI bus errors and SCSI bus resets.
+
+
+Detailed Design
+---------------
+Design and implementation details below, based on a chain of
+public email discussions with Ben Herrenschmidt, circa 5 April 2005.
 
 The error recovery API support is exposed to the driver in the form of
 a structure of function pointers pointed to by a new field in struct
-pci_driver. The absence of this pointer in pci_driver denotes an
-"non-aware" driver, behaviour on these is platform dependant.
-Platforms like ppc64 can try to simulate pci hotplug remove/add.
-
-The definition of "pci_error_token" is not covered here. It is based on
-Seto's work on the synchronous error detection. We still need to define
-functions for extracting infos out of an opaque error token. This is
-separate from this API.
+pci_driver. A driver that fails to provide the structure is "non-aware",
+and the actual recovery steps taken are platform dependent.  The
+arch/powerpc implementation will simulate a PCI hotplug remove/add.
 
 This structure has the form:
-
 struct pci_error_handlers
 {
-	int (*error_detected)(struct pci_dev *dev, pci_error_token error);
+	int (*error_detected)(struct pci_dev *dev, enum pci_channel_state);
 	int (*mmio_enabled)(struct pci_dev *dev);
-	int (*resume)(struct pci_dev *dev);
 	int (*link_reset)(struct pci_dev *dev);
 	int (*slot_reset)(struct pci_dev *dev);
+	void (*resume)(struct pci_dev *dev);
 };
 
-A driver doesn't have to implement all of these callbacks. The
-only mandatory one is error_detected(). If a callback is not
-implemented, the corresponding feature is considered unsupported.
-For example, if mmio_enabled() and resume() aren't there, then the
-driver is assumed as not doing any direct recovery and requires
+The possible channel states are:
+enum pci_channel_state {
+	pci_channel_io_normal,  /* I/O channel is in normal state */
+	pci_channel_io_frozen,  /* I/O to channel is blocked */
+	pci_channel_io_perm_failure, /* PCI card is dead */
+};
+
+Possible return values are:
+enum pci_ers_result {
+	PCI_ERS_RESULT_NONE,        /* no result/none/not supported in device driver */
+	PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */
+	PCI_ERS_RESULT_NEED_RESET,  /* Device driver wants slot to be reset. */
+	PCI_ERS_RESULT_DISCONNECT,  /* Device has completely failed, is unrecoverable */
+	PCI_ERS_RESULT_RECOVERED,   /* Device driver is fully recovered and operational */
+};
+
+A driver does not have to implement all of these callbacks; however,
+if it implements any, it must implement error_detected(). If a callback
+is not implemented, the corresponding feature is considered unsupported.
+For example, if mmio_enabled() and resume() aren't there, then it
+is assumed that the driver is not doing any direct recovery and requires
 a reset. If link_reset() is not implemented, the card is assumed as
-not caring about link resets, in which case, if recover is supported,
-the core can try recover (but not slot_reset() unless it really did
-reset the slot). If slot_reset() is not supported, link_reset() can
-be called instead on a slot reset.
+not care about link resets. Typically a driver will want to know about
+a slot_reset().
 
-At first, the call will always be :
+The actual steps taken by a platform to recover from a PCI error
+event will be platform-dependent, but will follow the general
+sequence described below.
 
-	1) error_detected()
+STEP 0: Error Event
+-------------------
+PCI bus error is detect by the PCI hardware.  On powerpc, the slot
+is isolated, in that all I/O is blocked: all reads return 0xffffffff,
+all writes are ignored.
 
-	Error detected. This is sent once after an error has been detected. At
-this point, the device might not be accessible anymore depending on the
-platform (the slot will be isolated on ppc64). The driver may already
-have "noticed" the error because of a failing IO, but this is the proper
-"synchronisation point", that is, it gives a chance to the driver to
-cleanup, waiting for pending stuff (timers, whatever, etc...) to
-complete; it can take semaphores, schedule, etc... everything but touch
-the device. Within this function and after it returns, the driver
+
+STEP 1: Notification
+--------------------
+Platform calls the error_detected() callback on every instance of
+every driver affected by the error.
+
+At this point, the device might not be accessible anymore, depending on
+the platform (the slot will be isolated on powerpc). The driver may
+already have "noticed" the error because of a failing I/O, but this
+is the proper "synchronization point", that is, it gives the driver
+a chance to cleanup, waiting for pending stuff (timers, whatever, etc...)
+to complete; it can take semaphores, schedule, etc... everything but
+touch the device. Within this function and after it returns, the driver
 shouldn't do any new IOs. Called in task context. This is sort of a
 "quiesce" point. See note about interrupts at the end of this doc.
 
-	Result codes:
-		- PCIERR_RESULT_CAN_RECOVER:
-		  Driever returns this if it thinks it might be able to recover
+All drivers participating in this system must implement this call.
+The driver must return one of the following result codes:
+		- PCI_ERS_RESULT_CAN_RECOVER:
+		  Driver returns this if it thinks it might be able to recover
 		  the HW by just banging IOs or if it wants to be given
-		  a chance to extract some diagnostic informations (see
-		  below).
-		- PCIERR_RESULT_NEED_RESET:
-		  Driver returns this if it thinks it can't recover unless the
-		  slot is reset.
-		- PCIERR_RESULT_DISCONNECT:
-		  Return this if driver thinks it won't recover at all,
-		  (this will detach the driver ? or just leave it
-		  dangling ? to be decided)
+		  a chance to extract some diagnostic information (see
+		  mmio_enable, below).
+		- PCI_ERS_RESULT_NEED_RESET:
+		  Driver returns this if it can't recover without a hard
+		  slot reset.
+		- PCI_ERS_RESULT_DISCONNECT:
+		  Driver returns this if it doesn't want to recover at all.
 
-So at this point, we have called error_detected() for all drivers
-on the segment that had the error. On ppc64, the slot is isolated. What
-happens now typically depends on the result from the drivers. If all
-drivers on the segment/slot return PCIERR_RESULT_CAN_RECOVER, we would
-re-enable IOs on the slot (or do nothing special if the platform doesn't
-isolate slots) and call 2). If not and we can reset slots, we go to 4),
-if neither, we have a dead slot. If it's an hotplug slot, we might
-"simulate" reset by triggering HW unplug/replug though.
+The next step taken will depend on the result codes returned by the
+drivers.
 
->>> Current ppc64 implementation assumes that a device driver will
->>> *not* schedule or semaphore in this routine; the current ppc64
+If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER,
+then the platform should re-enable IOs on the slot (or do nothing in
+particular, if the platform doesn't isolate slots), and recovery
+proceeds to STEP 2 (MMIO Enable).
+
+If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET),
+then recovery proceeds to STEP 4 (Slot Reset).
+
+If the platform is unable to recover the slot, the next step
+is STEP 6 (Permanent Failure).
+
+>>> The current powerpc implementation assumes that a device driver will
+>>> *not* schedule or semaphore in this routine; the current powerpc
 >>> implementation uses one kernel thread to notify all devices;
->>> thus, of one device sleeps/schedules, all devices are affected.
+>>> thus, if one device sleeps/schedules, all devices are affected.
 >>> Doing better requires complex multi-threaded logic in the error
 >>> recovery implementation (e.g. waiting for all notification threads
 >>> to "join" before proceeding with recovery.)  This seems excessively
 >>> complex and not worth implementing.
 
->>> The current ppc64 implementation doesn't much care if the device
->>> attempts i/o at this point, or not.  I/O's will fail, returning
+>>> The current powerpc implementation doesn't much care if the device
+>>> attempts I/O at this point, or not.  I/O's will fail, returning
 >>> a value of 0xff on read, and writes will be dropped. If the device
 >>> driver attempts more than 10K I/O's to a frozen adapter, it will
 >>> assume that the device driver has gone into an infinite loop, and
->>> it will panic the the kernel.
+>>> it will panic the the kernel. There doesn't seem to be any other
+>>> way of stopping a device driver that insists on spinning on I/O.
 
-	2) mmio_enabled()
+STEP 2: MMIO Enabled
+-------------------
+The platform re-enables MMIO to the device (but typically not the
+DMA), and then calls the mmio_enabled() callback on all affected
+device drivers.
 
-	This is the "early recovery" call. IOs are allowed again, but DMA is
+This is the "early recovery" call. IOs are allowed again, but DMA is
 not (hrm... to be discussed, I prefer not), with some restrictions. This
 is NOT a callback for the driver to start operations again, only to
 peek/poke at the device, extract diagnostic information, if any, and
 eventually do things like trigger a device local reset or some such,
-but not restart operations. This is sent if all drivers on a segment
-agree that they can try to recover and no automatic link reset was
-performed by the HW. If the platform can't just re-enable IOs without
-a slot reset or a link reset, it doesn't call this callback and goes
-directly to 3) or 4). All IOs should be done _synchronously_ from
-within this callback, errors triggered by them will be returned via
-the normal pci_check_whatever() api, no new error_detected() callback
-will be issued due to an error happening here. However, such an error
-might cause IOs to be re-blocked for the whole segment, and thus
-invalidate the recovery that other devices on the same segment might
-have done, forcing the whole segment into one of the next states,
-that is link reset or slot reset.
+but not restart operations. This is callback is made if all drivers on
+a segment agree that they can try to recover and if no automatic link reset
+was performed by the HW. If the platform can't just re-enable IOs without
+a slot reset or a link reset, it wont call this callback, and instead
+will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
 
-	Result codes:
-		- PCIERR_RESULT_RECOVERED
+>>> The following is proposed; no platform implements this yet:
+>>> Proposal: All I/O's should be done _synchronously_ from within
+>>> this callback, errors triggered by them will be returned via
+>>> the normal pci_check_whatever() API, no new error_detected()
+>>> callback will be issued due to an error happening here. However,
+>>> such an error might cause IOs to be re-blocked for the whole
+>>> segment, and thus invalidate the recovery that other devices
+>>> on the same segment might have done, forcing the whole segment
+>>> into one of the next states, that is, link reset or slot reset.
+
+The driver should return one of the following result codes:
+		- PCI_ERS_RESULT_RECOVERED
 		  Driver returns this if it thinks the device is fully
-		  functionnal and thinks it is ready to start
+		  functional and thinks it is ready to start
 		  normal driver operations again. There is no
 		  guarantee that the driver will actually be
 		  allowed to proceed, as another driver on the
 		  same segment might have failed and thus triggered a
 		  slot reset on platforms that support it.
 
-		- PCIERR_RESULT_NEED_RESET
+		- PCI_ERS_RESULT_NEED_RESET
 		  Driver returns this if it thinks the device is not
 		  recoverable in it's current state and it needs a slot
 		  reset to proceed.
 
-		- PCIERR_RESULT_DISCONNECT
+		- PCI_ERS_RESULT_DISCONNECT
 		  Same as above. Total failure, no recovery even after
 		  reset driver dead. (To be defined more precisely)
 
->>> The current ppc64 implementation does not implement this callback.
+The next step taken depends on the results returned by the drivers.
+If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform
+proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
 
-	3) link_reset()
+If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
+proceeds to STEP 4 (Slot Reset)
 
-	This is called after the link has been reset. This is typically
-a PCI Express specific state at this point and is done whenever a
-non-fatal error has been detected that can be "solved" by resetting
-the link. This call informs the driver of the reset and the driver
-should check if the device appears to be in working condition.
-This function acts a bit like 2) mmio_enabled(), in that the driver
-is not supposed to restart normal driver I/O operations right away.
-Instead, it should just "probe" the device to check it's recoverability
-status. If all is right, then the core will call resume() once all
-drivers have ack'd link_reset().
+>>> The current powerpc implementation does not implement this callback.
+
+
+STEP 3: Link Reset
+------------------
+The platform resets the link, and then calls the link_reset() callback
+on all affected device drivers.  This is a PCI-Express specific state
+and is done whenever a non-fatal error has been detected that can be
+"solved" by resetting the link. This call informs the driver of the
+reset and the driver should check to see if the device appears to be
+in working condition.
+
+The driver is not supposed to restart normal driver I/O operations
+at this point.  It should limit itself to "probing" the device to
+check it's recoverability status. If all is right, then the platform
+will call resume() once all drivers have ack'd link_reset().
 
 	Result codes:
-		(identical to mmio_enabled)
+		(identical to STEP 3 (MMIO Enabled)
 
->>> The current ppc64 implementation does not implement this callback.
+The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5
+(Resume Operations).
 
-	4) slot_reset()
+>>> The current powerpc implementation does not implement this callback.
 
-	This is called after the slot has been soft or hard reset by the
-platform.  A soft reset consists of asserting the adapter #RST line
-and then restoring the PCI BARs and PCI configuration header. If the
-platform supports PCI hotplug, then it might instead perform a hard
-reset by toggling power on the slot off/on. This call gives drivers
-the chance to re-initialize the hardware (re-download firmware, etc.),
-but drivers shouldn't restart normal I/O processing operations at
-this point.  (See note about interrupts; interrupts aren't guaranteed
-to be delivered until the resume() callback has been called). If all
-device drivers report success on this callback, the patform will call
-resume() to complete the error handling and let the driver restart
-normal I/O processing.
+
+STEP 4: Slot Reset
+------------------
+The platform performs a soft or hard reset of the device, and then
+calls the slot_reset() callback.
+
+A soft reset consists of asserting the adapter #RST line and then
+restoring the PCI BAR's and PCI configuration header to a state
+that is equivalent to what it would be after a fresh system
+power-on followed by power-on BIOS/system firmware initialization.
+If the platform supports PCI hotplug, then the reset might be
+performed by toggling the slot electrical power off/on.
+
+It is important for the platform to restore the PCI config space
+to the "fresh poweron" state, rather than the "last state". After
+a slot reset, the device driver will almost always use its standard
+device initialization routines, and an unusual config space setup
+may result in hung devices, kernel panics, or silent data corruption.
+
+This call gives drivers the chance to re-initialize the hardware
+(re-download firmware, etc.).  At this point, the driver may assume
+that he card is in a fresh state and is fully functional. In
+particular, interrupt generation should work normally.
+
+Drivers should not yet restart normal I/O processing operations
+at this point.  If all device drivers report success on this
+callback, the platform will call resume() to complete the sequence,
+and let the driver restart normal I/O processing.
 
 A driver can still return a critical failure for this function if
 it can't get the device operational after reset.  If the platform
-previously tried a soft reset, it migh now try a hard reset (power
+previously tried a soft reset, it might now try a hard reset (power
 cycle) and then call slot_reset() again.  It the device still can't
 be recovered, there is nothing more that can be done;  the platform
 will typically report a "permanent failure" in such a case.  The
 device will be considered "dead" in this case.
 
+Drivers for multi-function cards will need to coordinate among
+themselves as to which driver instance will perform any "one-shot"
+or global device initialization. For example, the Symbios sym53cxx2
+driver performs device init only from PCI function 0:
+
++       if (PCI_FUNC(pdev->devfn) == 0)
++               sym_reset_scsi_bus(np, 0);
+
 	Result codes:
-		- PCIERR_RESULT_DISCONNECT
+		- PCI_ERS_RESULT_DISCONNECT
 		Same as above.
 
->>> The current ppc64 implementation does not try a power-cycle reset
->>> if the driver returned PCIERR_RESULT_DISCONNECT. However, it should.
+Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
+Failure).
 
-	5) resume()
+>>> The current powerpc implementation does not currently try a
+>>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
+>>> However, it probably should.
 
-	This is called if all drivers on the segment have returned
-PCIERR_RESULT_RECOVERED from one of the 3 prevous callbacks.
-That basically tells the driver to restart activity, tht everything
-is back and running. No result code is taken into account here. If
-a new error happens, it will restart a new error handling process.
 
-That's it. I think this covers all the possibilities. The way those
-callbacks are called is platform policy. A platform with no slot reset
-capability for example may want to just "ignore" drivers that can't
+STEP 5: Resume Operations
+-------------------------
+The platform will call the resume() callback on all affected device
+drivers if all drivers on the segment have returned
+PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks.
+The goal of this callback is to tell the driver to restart activity,
+that everything is back and running. This callback does not return
+a result code.
+
+At this point, if a new error happens, the platform will restart
+a new error recovery sequence.
+
+STEP 6: Permanent Failure
+-------------------------
+A "permanent failure" has occurred, and the platform cannot recover
+the device.  The platform will call error_detected() with a
+pci_channel_state value of pci_channel_io_perm_failure.
+
+The device driver should, at this point, assume the worst. It should
+cancel all pending I/O, refuse all new I/O, returning -EIO to
+higher layers. The device driver should then clean up all of its
+memory and remove itself from kernel operations, much as it would
+during system shutdown.
+
+The platform will typically notify the system operator of the
+permanent failure in some way.  If the device is hotplug-capable,
+the operator will probably want to remove and replace the device.
+Note, however, not all failures are truly "permanent". Some are
+caused by over-heating, some by a poorly seated card. Many
+PCI error events are caused by software bugs, e.g. DMA's to
+wild addresses or bogus split transactions due to programming
+errors. See the discussion in powerpc/eeh-pci-error-recovery.txt
+for additional detail on real-life experience of the causes of
+software errors.
+
+
+Conclusion; General Remarks
+---------------------------
+The way those callbacks are called is platform policy. A platform with
+no slot reset capability may want to just "ignore" drivers that can't
 recover (disconnect them) and try to let other cards on the same segment
 recover. Keep in mind that in most real life cases, though, there will
 be only one driver per segment.
 
-Now, there is a note about interrupts. If you get an interrupt and your
+Now, a note about interrupts. If you get an interrupt and your
 device is dead or has been isolated, there is a problem :)
-
-After much thinking, I decided to leave that to the platform. That is,
-the recovery API only precies that:
+The current policy is to turn this into a platform policy.
+That is, the recovery API only requires that:
 
  - There is no guarantee that interrupt delivery can proceed from any
 device on the segment starting from the error detection and until the
-restart callback is sent, at which point interrupts are expected to be
+resume callback is sent, at which point interrupts are expected to be
 fully operational.
 
- - There is no guarantee that interrupt delivery is stopped, that is, ad
-river that gets an interrupts after detecting an error, or that detects
-and error within the interrupt handler such that it prevents proper
+ - There is no guarantee that interrupt delivery is stopped, that is,
+a driver that gets an interrupt after detecting an error, or that detects
+an error within the interrupt handler such that it prevents proper
 ack'ing of the interrupt (and thus removal of the source) should just
-return IRQ_NOTHANDLED. It's up to the platform to deal with taht
-condition, typically by masking the irq source during the duration of
+return IRQ_NOTHANDLED. It's up to the platform to deal with that
+condition, typically by masking the IRQ source during the duration of
 the error handling. It is expected that the platform "knows" which
 interrupts are routed to error-management capable slots and can deal
-with temporarily disabling that irq number during error processing (this
+with temporarily disabling that IRQ number during error processing (this
 isn't terribly complex). That means some IRQ latency for other devices
 sharing the interrupt, but there is simply no other way. High end
 platforms aren't supposed to share interrupts between many devices
 anyway :)
 
+>>> Implementation details for the powerpc platform are discussed in
+>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
 
-Revised: 31 May 2005 Linas Vepstas <linas@austin.ibm.com>
+>>> As of this writing, there are six device drivers with patches
+>>> implementing error recovery. Not all of these patches are in
+>>> mainline yet. These may be used as "examples":
+>>>
+>>> drivers/scsi/ipr.c
+>>> drivers/scsi/sym53cxx_2
+>>> drivers/next/e100.c
+>>> drivers/net/e1000
+>>> drivers/net/ixgb
+>>> drivers/net/s2io.c
+
+The End
+-------
diff --git a/Documentation/power/interface.txt b/Documentation/power/interface.txt
index bd4ffb5..4117802 100644
--- a/Documentation/power/interface.txt
+++ b/Documentation/power/interface.txt
@@ -44,7 +44,7 @@
 /sys/power/image_size controls the size of the image created by
 the suspend-to-disk mechanism.  It can be written a string
 representing a non-negative integer that will be used as an upper
-limit of the image size, in megabytes.  The suspend-to-disk mechanism will
+limit of the image size, in bytes.  The suspend-to-disk mechanism will
 do its best to ensure the image size will not exceed that number.  However,
 if this turns out to be impossible, it will try to suspend anyway using the
 smallest image possible.  In particular, if "0" is written to this file, the
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 08c79d4..b28b7f0 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -27,7 +27,7 @@
 
 echo platform > /sys/power/disk; echo disk > /sys/power/state
 
-If you want to limit the suspend image size to N megabytes, do
+If you want to limit the suspend image size to N bytes, do
 
 echo N > /sys/power/image_size
 
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
new file mode 100644
index 0000000..d02c649
--- /dev/null
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -0,0 +1,1486 @@
+           Booting the Linux/ppc kernel without Open Firmware
+           --------------------------------------------------
+
+
+(c) 2005 Benjamin Herrenschmidt <benh at kernel.crashing.org>,
+    IBM Corp.
+(c) 2005 Becky Bruce <becky.bruce at freescale.com>,
+    Freescale Semiconductor, FSL SOC and 32-bit additions
+
+   May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.
+
+   May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or
+                           clarifies the fact that a lot of things are
+                           optional, the kernel only requires a very
+                           small device tree, though it is encouraged
+                           to provide an as complete one as possible.
+
+   May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM
+			 - Misc fixes
+			 - Define version 3 and new format version 16
+			   for the DT block (version 16 needs kernel
+			   patches, will be fwd separately).
+			   String block now has a size, and full path
+			   is replaced by unit name for more
+			   compactness.
+			   linux,phandle is made optional, only nodes
+			   that are referenced by other nodes need it.
+			   "name" property is now automatically
+			   deduced from the unit name
+
+   June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and
+                           OF_DT_END_NODE in structure definition.
+                         - Change version 16 format to always align
+                           property data to 4 bytes. Since tokens are
+                           already aligned, that means no specific
+                           required alignement between property size
+                           and property data. The old style variable
+                           alignment would make it impossible to do
+                           "simple" insertion of properties using
+                           memove (thanks Milton for
+                           noticing). Updated kernel patch as well
+			 - Correct a few more alignement constraints
+			 - Add a chapter about the device-tree
+                           compiler and the textural representation of
+                           the tree that can be "compiled" by dtc.
+
+   November 21, 2005: Rev 0.5
+			 - Additions/generalizations for 32-bit
+			 - Changed to reflect the new arch/powerpc
+			   structure
+			 - Added chapter VI
+
+
+ ToDo:
+	- Add some definitions of interrupt tree (simple/complex)
+	- Add some definitions for pci host bridges
+	- Add some common address format examples
+	- Add definitions for standard properties and "compatible"
+	  names for cells that are not already defined by the existing
+	  OF spec.
+	- Compare FSL SOC use of PCI to standard and make sure no new
+	  node definition required.
+	- Add more information about node definitions for SOC devices
+  	  that currently have no standard, like the FSL CPM.
+
+
+I - Introduction
+================
+
+During the recent development of the Linux/ppc64 kernel, and more
+specifically, the addition of new platform types outside of the old
+IBM pSeries/iSeries pair, it was decided to enforce some strict rules
+regarding the kernel entry and bootloader <-> kernel interfaces, in
+order to avoid the degeneration that had become the ppc32 kernel entry
+point and the way a new platform should be added to the kernel. The
+legacy iSeries platform breaks those rules as it predates this scheme,
+but no new board support will be accepted in the main tree that
+doesn't follows them properly.  In addition, since the advent of the
+arch/powerpc merged architecture for ppc32 and ppc64, new 32-bit
+platforms and 32-bit platforms which move into arch/powerpc will be
+required to use these rules as well.
+
+The main requirement that will be defined in more detail below is
+the presence of a device-tree whose format is defined after Open
+Firmware specification. However, in order to make life easier
+to embedded board vendors, the kernel doesn't require the device-tree
+to represent every device in the system and only requires some nodes
+and properties to be present. This will be described in detail in
+section III, but, for example, the kernel does not require you to
+create a node for every PCI device in the system. It is a requirement
+to have a node for PCI host bridges in order to provide interrupt
+routing informations and memory/IO ranges, among others. It is also
+recommended to define nodes for on chip devices and other busses that
+don't specifically fit in an existing OF specification. This creates a
+great flexibility in the way the kernel can then probe those and match
+drivers to device, without having to hard code all sorts of tables. It
+also makes it more flexible for board vendors to do minor hardware
+upgrades without significantly impacting the kernel code or cluttering
+it with special cases.
+
+
+1) Entry point for arch/powerpc
+-------------------------------
+
+   There is one and one single entry point to the kernel, at the start
+   of the kernel image. That entry point supports two calling
+   conventions:
+
+        a) Boot from Open Firmware. If your firmware is compatible
+        with Open Firmware (IEEE 1275) or provides an OF compatible
+        client interface API (support for "interpret" callback of
+        forth words isn't required), you can enter the kernel with:
+
+              r5 : OF callback pointer as defined by IEEE 1275
+              bindings to powerpc. Only the 32 bit client interface
+              is currently supported
+
+              r3, r4 : address & length of an initrd if any or 0
+
+              The MMU is either on or off; the kernel will run the
+              trampoline located in arch/powerpc/kernel/prom_init.c to
+              extract the device-tree and other information from open
+              firmware and build a flattened device-tree as described
+              in b). prom_init() will then re-enter the kernel using
+              the second method. This trampoline code runs in the
+              context of the firmware, which is supposed to handle all
+              exceptions during that time.
+
+        b) Direct entry with a flattened device-tree block. This entry
+        point is called by a) after the OF trampoline and can also be
+        called directly by a bootloader that does not support the Open
+        Firmware client interface. It is also used by "kexec" to
+        implement "hot" booting of a new kernel from a previous
+        running one. This method is what I will describe in more
+        details in this document, as method a) is simply standard Open
+        Firmware, and thus should be implemented according to the
+        various standard documents defining it and its binding to the
+        PowerPC platform. The entry point definition then becomes:
+
+                r3 : physical pointer to the device-tree block
+                (defined in chapter II) in RAM
+
+                r4 : physical pointer to the kernel itself. This is
+                used by the assembly code to properly disable the MMU
+                in case you are entering the kernel with MMU enabled
+                and a non-1:1 mapping.
+
+                r5 : NULL (as to differenciate with method a)
+
+        Note about SMP entry: Either your firmware puts your other
+        CPUs in some sleep loop or spin loop in ROM where you can get
+        them out via a soft reset or some other means, in which case
+        you don't need to care, or you'll have to enter the kernel
+        with all CPUs. The way to do that with method b) will be
+        described in a later revision of this document.
+
+
+2) Board support
+----------------
+
+64-bit kernels:
+
+   Board supports (platforms) are not exclusive config options. An
+   arbitrary set of board supports can be built in a single kernel
+   image. The kernel will "know" what set of functions to use for a
+   given platform based on the content of the device-tree. Thus, you
+   should:
+
+        a) add your platform support as a _boolean_ option in
+        arch/powerpc/Kconfig, following the example of PPC_PSERIES,
+        PPC_PMAC and PPC_MAPLE. The later is probably a good
+        example of a board support to start from.
+
+        b) create your main platform file as
+        "arch/powerpc/platforms/myplatform/myboard_setup.c" and add it
+        to the Makefile under the condition of your CONFIG_
+        option. This file will define a structure of type "ppc_md"
+        containing the various callbacks that the generic code will
+        use to get to your platform specific code
+
+        c) Add a reference to your "ppc_md" structure in the
+        "machines" table in arch/powerpc/kernel/setup_64.c if you are
+        a 64-bit platform.
+
+        d) request and get assigned a platform number (see PLATFORM_*
+        constants in include/asm-powerpc/processor.h
+
+32-bit embedded kernels:
+
+  Currently, board support is essentially an exclusive config option.
+  The kernel is configured for a single platform.  Part of the reason
+  for this is to keep kernels on embedded systems small and efficient;
+  part of this is due to the fact the code is already that way. In the
+  future, a kernel may support multiple platforms, but only if the
+  platforms feature the same core architectire.  A single kernel build
+  cannot support both configurations with Book E and configurations
+  with classic Powerpc architectures.
+
+  32-bit embedded platforms that are moved into arch/powerpc using a
+  flattened device tree should adopt the merged tree practice of
+  setting ppc_md up dynamically, even though the kernel is currently
+  built with support for only a single platform at a time.  This allows
+  unification of the setup code, and will make it easier to go to a
+  multiple-platform-support model in the future.
+
+NOTE: I believe the above will be true once Ben's done with the merge
+of the boot sequences.... someone speak up if this is wrong!
+
+  To add a 32-bit embedded platform support, follow the instructions
+  for 64-bit platforms above, with the exception that the Kconfig
+  option should be set up such that the kernel builds exclusively for
+  the platform selected.  The processor type for the platform should
+  enable another config option to select the specific board
+  supported.
+
+NOTE: If ben doesn't merge the setup files, may need to change this to
+point to setup_32.c
+
+
+   I will describe later the boot process and various callbacks that
+   your platform should implement.
+
+
+II - The DT block format
+========================
+
+
+This chapter defines the actual format of the flattened device-tree
+passed to the kernel. The actual content of it and kernel requirements
+are described later. You can find example of code manipulating that
+format in various places, including arch/powerpc/kernel/prom_init.c
+which will generate a flattened device-tree from the Open Firmware
+representation, or the fs2dt utility which is part of the kexec tools
+which will generate one from a filesystem representation. It is
+expected that a bootloader like uboot provides a bit more support,
+that will be discussed later as well.
+
+Note: The block has to be in main memory. It has to be accessible in
+both real mode and virtual mode with no mapping other than main
+memory. If you are writing a simple flash bootloader, it should copy
+the block to RAM before passing it to the kernel.
+
+
+1) Header
+---------
+
+   The kernel is entered with r3 pointing to an area of memory that is
+   roughtly described in include/asm-powerpc/prom.h by the structure
+   boot_param_header:
+
+struct boot_param_header {
+        u32     magic;                  /* magic word OF_DT_HEADER */
+        u32     totalsize;              /* total size of DT block */
+        u32     off_dt_struct;          /* offset to structure */
+        u32     off_dt_strings;         /* offset to strings */
+        u32     off_mem_rsvmap;         /* offset to memory reserve map
+*/
+        u32     version;                /* format version */
+        u32     last_comp_version;      /* last compatible version */
+
+        /* version 2 fields below */
+        u32     boot_cpuid_phys;        /* Which physical CPU id we're
+                                           booting on */
+        /* version 3 fields below */
+        u32     size_dt_strings;        /* size of the strings block */
+};
+
+   Along with the constants:
+
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER            0xd00dfeed      /* 4: version,
+						   4: total size */
+#define OF_DT_BEGIN_NODE        0x1             /* Start node: full name
+*/
+#define OF_DT_END_NODE          0x2             /* End node */
+#define OF_DT_PROP              0x3             /* Property: name off,
+                                                   size, content */
+#define OF_DT_END               0x9
+
+   All values in this header are in big endian format, the various
+   fields in this header are defined more precisely below. All
+   "offset" values are in bytes from the start of the header; that is
+   from the value of r3.
+
+   - magic
+
+     This is a magic value that "marks" the beginning of the
+     device-tree block header. It contains the value 0xd00dfeed and is
+     defined by the constant OF_DT_HEADER
+
+   - totalsize
+
+     This is the total size of the DT block including the header. The
+     "DT" block should enclose all data structures defined in this
+     chapter (who are pointed to by offsets in this header). That is,
+     the device-tree structure, strings, and the memory reserve map.
+
+   - off_dt_struct
+
+     This is an offset from the beginning of the header to the start
+     of the "structure" part the device tree. (see 2) device tree)
+
+   - off_dt_strings
+
+     This is an offset from the beginning of the header to the start
+     of the "strings" part of the device-tree
+
+   - off_mem_rsvmap
+
+     This is an offset from the beginning of the header to the start
+     of the reserved memory map. This map is a list of pairs of 64
+     bit integers. Each pair is a physical address and a size. The
+
+     list is terminated by an entry of size 0. This map provides the
+     kernel with a list of physical memory areas that are "reserved"
+     and thus not to be used for memory allocations, especially during
+     early initialization. The kernel needs to allocate memory during
+     boot for things like un-flattening the device-tree, allocating an
+     MMU hash table, etc... Those allocations must be done in such a
+     way to avoid overriding critical things like, on Open Firmware
+     capable machines, the RTAS instance, or on some pSeries, the TCE
+     tables used for the iommu. Typically, the reserve map should
+     contain _at least_ this DT block itself (header,total_size). If
+     you are passing an initrd to the kernel, you should reserve it as
+     well. You do not need to reserve the kernel image itself. The map
+     should be 64 bit aligned.
+
+   - version
+
+     This is the version of this structure. Version 1 stops
+     here. Version 2 adds an additional field boot_cpuid_phys.
+     Version 3 adds the size of the strings block, allowing the kernel
+     to reallocate it easily at boot and free up the unused flattened
+     structure after expansion. Version 16 introduces a new more
+     "compact" format for the tree itself that is however not backward
+     compatible. You should always generate a structure of the highest
+     version defined at the time of your implementation. Currently
+     that is version 16, unless you explicitely aim at being backward
+     compatible.
+
+   - last_comp_version
+
+     Last compatible version. This indicates down to what version of
+     the DT block you are backward compatible. For example, version 2
+     is backward compatible with version 1 (that is, a kernel build
+     for version 1 will be able to boot with a version 2 format). You
+     should put a 1 in this field if you generate a device tree of
+     version 1 to 3, or 0x10 if you generate a tree of version 0x10
+     using the new unit name format.
+
+   - boot_cpuid_phys
+
+     This field only exist on version 2 headers. It indicate which
+     physical CPU ID is calling the kernel entry point. This is used,
+     among others, by kexec. If you are on an SMP system, this value
+     should match the content of the "reg" property of the CPU node in
+     the device-tree corresponding to the CPU calling the kernel entry
+     point (see further chapters for more informations on the required
+     device-tree contents)
+
+
+   So the typical layout of a DT block (though the various parts don't
+   need to be in that order) looks like this (addresses go from top to
+   bottom):
+
+
+             ------------------------------
+       r3 -> |  struct boot_param_header  |
+             ------------------------------
+             |      (alignment gap) (*)   |
+             ------------------------------
+             |      memory reserve map    |
+             ------------------------------
+             |      (alignment gap)       |
+             ------------------------------
+             |                            |
+             |    device-tree structure   |
+             |                            |
+             ------------------------------
+             |      (alignment gap)       |
+             ------------------------------
+             |                            |
+             |     device-tree strings    |
+             |                            |
+      -----> ------------------------------
+      |
+      |
+      --- (r3 + totalsize)
+
+  (*) The alignment gaps are not necessarily present; their presence
+      and size are dependent on the various alignment requirements of
+      the individual data blocks.
+
+
+2) Device tree generalities
+---------------------------
+
+This device-tree itself is separated in two different blocks, a
+structure block and a strings block. Both need to be aligned to a 4
+byte boundary.
+
+First, let's quickly describe the device-tree concept before detailing
+the storage format. This chapter does _not_ describe the detail of the
+required types of nodes & properties for the kernel, this is done
+later in chapter III.
+
+The device-tree layout is strongly inherited from the definition of
+the Open Firmware IEEE 1275 device-tree. It's basically a tree of
+nodes, each node having two or more named properties. A property can
+have a value or not.
+
+It is a tree, so each node has one and only one parent except for the
+root node who has no parent.
+
+A node has 2 names. The actual node name is generally contained in a
+property of type "name" in the node property list whose value is a
+zero terminated string and is mandatory for version 1 to 3 of the
+format definition (as it is in Open Firmware). Version 0x10 makes it
+optional as it can generate it from the unit name defined below.
+
+There is also a "unit name" that is used to differenciate nodes with
+the same name at the same level, it is usually made of the node
+name's, the "@" sign, and a "unit address", which definition is
+specific to the bus type the node sits on.
+
+The unit name doesn't exist as a property per-se but is included in
+the device-tree structure. It is typically used to represent "path" in
+the device-tree. More details about the actual format of these will be
+below.
+
+The kernel powerpc generic code does not make any formal use of the
+unit address (though some board support code may do) so the only real
+requirement here for the unit address is to ensure uniqueness of
+the node unit name at a given level of the tree. Nodes with no notion
+of address and no possible sibling of the same name (like /memory or
+/cpus) may omit the unit address in the context of this specification,
+or use the "@0" default unit address. The unit name is used to define
+a node "full path", which is the concatenation of all parent node
+unit names separated with "/".
+
+The root node doesn't have a defined name, and isn't required to have
+a name property either if you are using version 3 or earlier of the
+format. It also has no unit address (no @ symbol followed by a unit
+address). The root node unit name is thus an empty string. The full
+path to the root node is "/".
+
+Every node which actually represents an actual device (that is, a node
+which isn't only a virtual "container" for more nodes, like "/cpus"
+is) is also required to have a "device_type" property indicating the
+type of node .
+
+Finally, every node that can be referenced from a property in another
+node is required to have a "linux,phandle" property. Real open
+firmware implementations provide a unique "phandle" value for every
+node that the "prom_init()" trampoline code turns into
+"linux,phandle" properties. However, this is made optional if the
+flattened device tree is used directly. An example of a node
+referencing another node via "phandle" is when laying out the
+interrupt tree which will be described in a further version of this
+document.
+
+This "linux, phandle" property is a 32 bit value that uniquely
+identifies a node. You are free to use whatever values or system of
+values, internal pointers, or whatever to generate these, the only
+requirement is that every node for which you provide that property has
+a unique value for it.
+
+Here is an example of a simple device-tree. In this example, an "o"
+designates a node followed by the node unit name. Properties are
+presented with their name followed by their content. "content"
+represents an ASCII string (zero terminated) value, while <content>
+represents a 32 bit hexadecimal value. The various nodes in this
+example will be discussed in a later chapter. At this point, it is
+only meant to give you a idea of what a device-tree looks like. I have
+purposefully kept the "name" and "linux,phandle" properties which
+aren't necessary in order to give you a better idea of what the tree
+looks like in practice.
+
+  / o device-tree
+      |- name = "device-tree"
+      |- model = "MyBoardName"
+      |- compatible = "MyBoardFamilyName"
+      |- #address-cells = <2>
+      |- #size-cells = <2>
+      |- linux,phandle = <0>
+      |
+      o cpus
+      | | - name = "cpus"
+      | | - linux,phandle = <1>
+      | | - #address-cells = <1>
+      | | - #size-cells = <0>
+      | |
+      | o PowerPC,970@0
+      |   |- name = "PowerPC,970"
+      |   |- device_type = "cpu"
+      |   |- reg = <0>
+      |   |- clock-frequency = <5f5e1000>
+      |   |- linux,boot-cpu
+      |   |- linux,phandle = <2>
+      |
+      o memory@0
+      | |- name = "memory"
+      | |- device_type = "memory"
+      | |- reg = <00000000 00000000 00000000 20000000>
+      | |- linux,phandle = <3>
+      |
+      o chosen
+        |- name = "chosen"
+        |- bootargs = "root=/dev/sda2"
+        |- linux,platform = <00000600>
+        |- linux,phandle = <4>
+
+This tree is almost a minimal tree. It pretty much contains the
+minimal set of required nodes and properties to boot a linux kernel;
+that is, some basic model informations at the root, the CPUs, and the
+physical memory layout.  It also includes misc information passed
+through /chosen, like in this example, the platform type (mandatory)
+and the kernel command line arguments (optional).
+
+The /cpus/PowerPC,970@0/linux,boot-cpu property is an example of a
+property without a value. All other properties have a value. The
+significance of the #address-cells and #size-cells properties will be
+explained in chapter IV which defines precisely the required nodes and
+properties and their content.
+
+
+3) Device tree "structure" block
+
+The structure of the device tree is a linearized tree structure. The
+"OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE"
+ends that node definition. Child nodes are simply defined before
+"OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32
+bit value. The tree has to be "finished" with a OF_DT_END token
+
+Here's the basic structure of a single node:
+
+     * token OF_DT_BEGIN_NODE (that is 0x00000001)
+     * for version 1 to 3, this is the node full path as a zero
+       terminated string, starting with "/". For version 16 and later,
+       this is the node unit name only (or an empty string for the
+       root node)
+     * [align gap to next 4 bytes boundary]
+     * for each property:
+        * token OF_DT_PROP (that is 0x00000003)
+        * 32 bit value of property value size in bytes (or 0 of no
+     * value)
+        * 32 bit value of offset in string block of property name
+        * property value data if any
+        * [align gap to next 4 bytes boundary]
+     * [child nodes if any]
+     * token OF_DT_END_NODE (that is 0x00000002)
+
+So the node content can be summmarised as a start token, a full path,
+a list of properties, a list of child node and an end token. Every
+child node is a full node structure itself as defined above.
+
+4) Device tree 'strings" block
+
+In order to save space, property names, which are generally redundant,
+are stored separately in the "strings" block. This block is simply the
+whole bunch of zero terminated strings for all property names
+concatenated together. The device-tree property definitions in the
+structure block will contain offset values from the beginning of the
+strings block.
+
+
+III - Required content of the device tree
+=========================================
+
+WARNING: All "linux,*" properties defined in this document apply only
+to a flattened device-tree. If your platform uses a real
+implementation of Open Firmware or an implementation compatible with
+the Open Firmware client interface, those properties will be created
+by the trampoline code in the kernel's prom_init() file. For example,
+that's where you'll have to add code to detect your board model and
+set the platform number. However, when using the flatenned device-tree
+entry point, there is no prom_init() pass, and thus you have to
+provide those properties yourself.
+
+
+1) Note about cells and address representation
+----------------------------------------------
+
+The general rule is documented in the various Open Firmware
+documentations. If you chose to describe a bus with the device-tree
+and there exist an OF bus binding, then you should follow the
+specification. However, the kernel does not require every single
+device or bus to be described by the device tree.
+
+In general, the format of an address for a device is defined by the
+parent bus type, based on the #address-cells and #size-cells
+property. In the absence of such a property, the parent's parent
+values are used, etc... The kernel requires the root node to have
+those properties defining addresses format for devices directly mapped
+on the processor bus.
+
+Those 2 properties define 'cells' for representing an address and a
+size. A "cell" is a 32 bit number. For example, if both contain 2
+like the example tree given above, then an address and a size are both
+composed of 2 cells, and each is a 64 bit number (cells are
+concatenated and expected to be in big endian format). Another example
+is the way Apple firmware defines them, with 2 cells for an address
+and one cell for a size.  Most 32-bit implementations should define
+#address-cells and #size-cells to 1, which represents a 32-bit value.
+Some 32-bit processors allow for physical addresses greater than 32
+bits; these processors should define #address-cells as 2.
+
+"reg" properties are always a tuple of the type "address size" where
+the number of cells of address and size is specified by the bus
+#address-cells and #size-cells. When a bus supports various address
+spaces and other flags relative to a given address allocation (like
+prefetchable, etc...) those flags are usually added to the top level
+bits of the physical address. For example, a PCI physical address is
+made of 3 cells, the bottom two containing the actual address itself
+while the top cell contains address space indication, flags, and pci
+bus & device numbers.
+
+For busses that support dynamic allocation, it's the accepted practice
+to then not provide the address in "reg" (keep it 0) though while
+providing a flag indicating the address is dynamically allocated, and
+then, to provide a separate "assigned-addresses" property that
+contains the fully allocated addresses. See the PCI OF bindings for
+details.
+
+In general, a simple bus with no address space bits and no dynamic
+allocation is preferred if it reflects your hardware, as the existing
+kernel address parsing functions will work out of the box. If you
+define a bus type with a more complex address format, including things
+like address space bits, you'll have to add a bus translator to the
+prom_parse.c file of the recent kernels for your bus type.
+
+The "reg" property only defines addresses and sizes (if #size-cells
+is
+non-0) within a given bus. In order to translate addresses upward
+(that is into parent bus addresses, and possibly into cpu physical
+addresses), all busses must contain a "ranges" property. If the
+"ranges" property is missing at a given level, it's assumed that
+translation isn't possible. The format of the "ranges" proprety for a
+bus is a list of:
+
+	bus address, parent bus address, size
+
+"bus address" is in the format of the bus this bus node is defining,
+that is, for a PCI bridge, it would be a PCI address. Thus, (bus
+address, size) defines a range of addresses for child devices. "parent
+bus address" is in the format of the parent bus of this bus. For
+example, for a PCI host controller, that would be a CPU address. For a
+PCI<->ISA bridge, that would be a PCI address. It defines the base
+address in the parent bus where the beginning of that range is mapped.
+
+For a new 64 bit powerpc board, I recommend either the 2/2 format or
+Apple's 2/1 format which is slightly more compact since sizes usually
+fit in a single 32 bit word.   New 32 bit powerpc boards should use a
+1/1 format, unless the processor supports physical addresses greater
+than 32-bits, in which case a 2/1 format is recommended.
+
+
+2) Note about "compatible" properties
+-------------------------------------
+
+These properties are optional, but recommended in devices and the root
+node. The format of a "compatible" property is a list of concatenated
+zero terminated strings. They allow a device to express its
+compatibility with a family of similar devices, in some cases,
+allowing a single driver to match against several devices regardless
+of their actual names.
+
+3) Note about "name" properties
+-------------------------------
+
+While earlier users of Open Firmware like OldWorld macintoshes tended
+to use the actual device name for the "name" property, it's nowadays
+considered a good practice to use a name that is closer to the device
+class (often equal to device_type). For example, nowadays, ethernet
+controllers are named "ethernet", an additional "model" property
+defining precisely the chip type/model, and "compatible" property
+defining the family in case a single driver can driver more than one
+of these chips. However, the kernel doesn't generally put any
+restriction on the "name" property; it is simply considered good
+practice to follow the standard and its evolutions as closely as
+possible.
+
+Note also that the new format version 16 makes the "name" property
+optional. If it's absent for a node, then the node's unit name is then
+used to reconstruct the name. That is, the part of the unit name
+before the "@" sign is used (or the entire unit name if no "@" sign
+is present).
+
+4) Note about node and property names and character set
+-------------------------------------------------------
+
+While open firmware provides more flexibe usage of 8859-1, this
+specification enforces more strict rules. Nodes and properties should
+be comprised only of ASCII characters 'a' to 'z', '0' to
+'9', ',', '.', '_', '+', '#', '?', and '-'. Node names additionally
+allow uppercase characters 'A' to 'Z' (property names should be
+lowercase. The fact that vendors like Apple don't respect this rule is
+irrelevant here). Additionally, node and property names should always
+begin with a character in the range 'a' to 'z' (or 'A' to 'Z' for node
+names).
+
+The maximum number of characters for both nodes and property names
+is 31. In the case of node names, this is only the leftmost part of
+a unit name (the pure "name" property), it doesn't include the unit
+address which can extend beyond that limit.
+
+
+5) Required nodes and properties
+--------------------------------
+  These are all that are currently required. However, it is strongly
+  recommended that you expose PCI host bridges as documented in the
+  PCI binding to open firmware, and your interrupt tree as documented
+  in OF interrupt tree specification.
+
+  a) The root node
+
+  The root node requires some properties to be present:
+
+    - model : this is your board name/model
+    - #address-cells : address representation for "root" devices
+    - #size-cells: the size representation for "root" devices
+
+  Additionally, some recommended properties are:
+
+    - compatible : the board "family" generally finds its way here,
+      for example, if you have 2 board models with a similar layout,
+      that typically get driven by the same platform code in the
+      kernel, you would use a different "model" property but put a
+      value in "compatible". The kernel doesn't directly use that
+      value (see /chosen/linux,platform for how the kernel choses a
+      platform type) but it is generally useful.
+
+  The root node is also generally where you add additional properties
+  specific to your board like the serial number if any, that sort of
+  thing. it is recommended that if you add any "custom" property whose
+  name may clash with standard defined ones, you prefix them with your
+  vendor name and a comma.
+
+  b) The /cpus node
+
+  This node is the parent of all individual CPU nodes. It doesn't
+  have any specific requirements, though it's generally good practice
+  to have at least:
+
+               #address-cells = <00000001>
+               #size-cells    = <00000000>
+
+  This defines that the "address" for a CPU is a single cell, and has
+  no meaningful size. This is not necessary but the kernel will assume
+  that format when reading the "reg" properties of a CPU node, see
+  below
+
+  c) The /cpus/* nodes
+
+  So under /cpus, you are supposed to create a node for every CPU on
+  the machine. There is no specific restriction on the name of the
+  CPU, though It's common practice to call it PowerPC,<name>. For
+  example, Apple uses PowerPC,G5 while IBM uses PowerPC,970FX.
+
+  Required properties:
+
+    - device_type : has to be "cpu"
+    - reg : This is the physical cpu number, it's a single 32 bit cell
+      and is also used as-is as the unit number for constructing the
+      unit name in the full path. For example, with 2 CPUs, you would
+      have the full path:
+        /cpus/PowerPC,970FX@0
+        /cpus/PowerPC,970FX@1
+      (unit addresses do not require leading zeroes)
+    - d-cache-line-size : one cell, L1 data cache line size in bytes
+    - i-cache-line-size : one cell, L1 instruction cache line size in
+      bytes
+    - d-cache-size : one cell, size of L1 data cache in bytes
+    - i-cache-size : one cell, size of L1 instruction cache in bytes
+    - linux, boot-cpu : Should be defined if this cpu is the boot cpu.
+
+  Recommended properties:
+
+    - timebase-frequency : a cell indicating the frequency of the
+      timebase in Hz. This is not directly used by the generic code,
+      but you are welcome to copy/paste the pSeries code for setting
+      the kernel timebase/decrementer calibration based on this
+      value.
+    - clock-frequency : a cell indicating the CPU core clock frequency
+      in Hz. A new property will be defined for 64 bit values, but if
+      your frequency is < 4Ghz, one cell is enough. Here as well as
+      for the above, the common code doesn't use that property, but
+      you are welcome to re-use the pSeries or Maple one. A future
+      kernel version might provide a common function for this.
+
+  You are welcome to add any property you find relevant to your board,
+  like some information about the mechanism used to soft-reset the
+  CPUs. For example, Apple puts the GPIO number for CPU soft reset
+  lines in there as a "soft-reset" property since they start secondary
+  CPUs by soft-resetting them.
+
+
+  d) the /memory node(s)
+
+  To define the physical memory layout of your board, you should
+  create one or more memory node(s). You can either create a single
+  node with all memory ranges in its reg property, or you can create
+  several nodes, as you wish. The unit address (@ part) used for the
+  full path is the address of the first range of memory defined by a
+  given node. If you use a single memory node, this will typically be
+  @0.
+
+  Required properties:
+
+    - device_type : has to be "memory"
+    - reg : This property contains all the physical memory ranges of
+      your board. It's a list of addresses/sizes concatenated
+      together, with the number of cells of each defined by the
+      #address-cells and #size-cells of the root node. For example,
+      with both of these properties beeing 2 like in the example given
+      earlier, a 970 based machine with 6Gb of RAM could typically
+      have a "reg" property here that looks like:
+
+      00000000 00000000 00000000 80000000
+      00000001 00000000 00000001 00000000
+
+      That is a range starting at 0 of 0x80000000 bytes and a range
+      starting at 0x100000000 and of 0x100000000 bytes. You can see
+      that there is no memory covering the IO hole between 2Gb and
+      4Gb. Some vendors prefer splitting those ranges into smaller
+      segments, but the kernel doesn't care.
+
+  e) The /chosen node
+
+  This node is a bit "special". Normally, that's where open firmware
+  puts some variable environment information, like the arguments, or
+  phandle pointers to nodes like the main interrupt controller, or the
+  default input/output devices.
+
+  This specification makes a few of these mandatory, but also defines
+  some linux-specific properties that would be normally constructed by
+  the prom_init() trampoline when booting with an OF client interface,
+  but that you have to provide yourself when using the flattened format.
+
+  Required properties:
+
+    - linux,platform : This is your platform number as assigned by the
+      architecture maintainers
+
+  Recommended properties:
+
+    - bootargs : This zero-terminated string is passed as the kernel
+      command line
+    - linux,stdout-path : This is the full path to your standard
+      console device if any. Typically, if you have serial devices on
+      your board, you may want to put the full path to the one set as
+      the default console in the firmware here, for the kernel to pick
+      it up as it's own default console. If you look at the funciton
+      set_preferred_console() in arch/ppc64/kernel/setup.c, you'll see
+      that the kernel tries to find out the default console and has
+      knowledge of various types like 8250 serial ports. You may want
+      to extend this function to add your own.
+    - interrupt-controller : This is one cell containing a phandle
+      value that matches the "linux,phandle" property of your main
+      interrupt controller node. May be used for interrupt routing.
+
+
+  Note that u-boot creates and fills in the chosen node for platforms
+  that use it.
+
+  f) the /soc<SOCname> node
+
+  This node is used to represent a system-on-a-chip (SOC) and must be
+  present if the processor is a SOC. The top-level soc node contains
+  information that is global to all devices on the SOC. The node name
+  should contain a unit address for the SOC, which is the base address
+  of the memory-mapped register set for the SOC. The name of an soc
+  node should start with "soc", and the remainder of the name should
+  represent the part number for the soc.  For example, the MPC8540's
+  soc node would be called "soc8540".
+
+  Required properties:
+
+    - device_type : Should be "soc"
+    - ranges : Should be defined as specified in 1) to describe the
+      translation of SOC addresses for memory mapped SOC registers.
+    - bus-frequency: Contains the bus frequency for the SOC node.
+      Typically, the value of this field is filled in by the boot
+      loader. 
+
+
+  Recommended properties:
+
+    - reg : This property defines the address and size of the
+      memory-mapped registers that are used for the SOC node itself.
+      It does not include the child device registers - these will be
+      defined inside each child node.  The address specified in the
+      "reg" property should match the unit address of the SOC node.
+    - #address-cells : Address representation for "soc" devices.  The
+      format of this field may vary depending on whether or not the
+      device registers are memory mapped.  For memory mapped
+      registers, this field represents the number of cells needed to
+      represent the address of the registers.  For SOCs that do not
+      use MMIO, a special address format should be defined that
+      contains enough cells to represent the required information.
+      See 1) above for more details on defining #address-cells.
+    - #size-cells : Size representation for "soc" devices
+    - #interrupt-cells : Defines the width of cells used to represent
+       interrupts.  Typically this value is <2>, which includes a
+       32-bit number that represents the interrupt number, and a
+       32-bit number that represents the interrupt sense and level.
+       This field is only needed if the SOC contains an interrupt
+       controller.
+
+  The SOC node may contain child nodes for each SOC device that the
+  platform uses.  Nodes should not be created for devices which exist
+  on the SOC but are not used by a particular platform. See chapter VI
+  for more information on how to specify devices that are part of an
+SOC.
+
+  Example SOC node for the MPC8540:
+
+	soc8540@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <00000000 e0000000 00100000>
+		reg = <e0000000 00003000>;
+		bus-frequency = <0>;
+	}
+
+
+
+IV - "dtc", the device tree compiler
+====================================
+
+
+dtc source code can be found at
+<http://ozlabs.org/~dgibson/dtc/dtc.tar.gz>
+
+WARNING: This version is still in early development stage; the
+resulting device-tree "blobs" have not yet been validated with the
+kernel. The current generated bloc lacks a useful reserve map (it will
+be fixed to generate an empty one, it's up to the bootloader to fill
+it up) among others. The error handling needs work, bugs are lurking,
+etc...
+
+dtc basically takes a device-tree in a given format and outputs a
+device-tree in another format. The currently supported formats are:
+
+  Input formats:
+  -------------
+
+     - "dtb": "blob" format, that is a flattened device-tree block
+       with
+        header all in a binary blob.
+     - "dts": "source" format. This is a text file containing a
+       "source" for a device-tree. The format is defined later in this
+        chapter.
+     - "fs" format. This is a representation equivalent to the
+        output of /proc/device-tree, that is nodes are directories and
+	properties are files
+
+ Output formats:
+ ---------------
+
+     - "dtb": "blob" format
+     - "dts": "source" format
+     - "asm": assembly language file. This is a file that can be
+       sourced by gas to generate a device-tree "blob". That file can
+       then simply be added to your Makefile. Additionally, the
+       assembly file exports some symbols that can be use
+
+
+The syntax of the dtc tool is
+
+    dtc [-I <input-format>] [-O <output-format>]
+        [-o output-filename] [-V output_version] input_filename
+
+
+The "output_version" defines what versio of the "blob" format will be
+generated. Supported versions are 1,2,3 and 16. The default is
+currently version 3 but that may change in the future to version 16.
+
+Additionally, dtc performs various sanity checks on the tree, like the
+uniqueness of linux,phandle properties, validity of strings, etc...
+
+The format of the .dts "source" file is "C" like, supports C and C++
+style commments.
+
+/ {
+}
+
+The above is the "device-tree" definition. It's the only statement
+supported currently at the toplevel.
+
+/ {
+  property1 = "string_value";	/* define a property containing a 0
+                                 * terminated string
+				 */
+
+  property2 = <1234abcd>;	/* define a property containing a
+                                 * numerical 32 bits value (hexadecimal)
+				 */
+
+  property3 = <12345678 12345678 deadbeef>;
+                                /* define a property containing 3
+                                 * numerical 32 bits values (cells) in
+                                 * hexadecimal
+				 */
+  property4 = [0a 0b 0c 0d de ea ad be ef];
+                                /* define a property whose content is
+                                 * an arbitrary array of bytes
+                                 */
+
+  childnode@addresss {	/* define a child node named "childnode"
+                                 * whose unit name is "childnode at
+				 * address"
+                                 */
+
+    childprop = "hello\n";      /* define a property "childprop" of
+                                 * childnode (in this case, a string)
+                                 */
+  };
+};
+
+Nodes can contain other nodes etc... thus defining the hierarchical
+structure of the tree.
+
+Strings support common escape sequences from C: "\n", "\t", "\r",
+"\(octal value)", "\x(hex value)".
+
+It is also suggested that you pipe your source file through cpp (gcc
+preprocessor) so you can use #include's, #define for constants, etc...
+
+Finally, various options are planned but not yet implemented, like
+automatic generation of phandles, labels (exported to the asm file so
+you can point to a property content and change it easily from whatever
+you link the device-tree with), label or path instead of numeric value
+in some cells to "point" to a node (replaced by a phandle at compile
+time), export of reserve map address to the asm file, ability to
+specify reserve map content at compile time, etc...
+
+We may provide a .h include file with common definitions of that
+proves useful for some properties (like building PCI properties or
+interrupt maps) though it may be better to add a notion of struct
+definitions to the compiler...
+
+
+V - Recommendations for a bootloader
+====================================
+
+
+Here are some various ideas/recommendations that have been proposed
+while all this has been defined and implemented.
+
+  - The bootloader may want to be able to use the device-tree itself
+    and may want to manipulate it (to add/edit some properties,
+    like physical memory size or kernel arguments). At this point, 2
+    choices can be made. Either the bootloader works directly on the
+    flattened format, or the bootloader has its own internal tree
+    representation with pointers (similar to the kernel one) and
+    re-flattens the tree when booting the kernel. The former is a bit
+    more difficult to edit/modify, the later requires probably a bit
+    more code to handle the tree structure. Note that the structure
+    format has been designed so it's relatively easy to "insert"
+    properties or nodes or delete them by just memmoving things
+    around. It contains no internal offsets or pointers for this
+    purpose.
+
+  - An example of code for iterating nodes & retreiving properties
+    directly from the flattened tree format can be found in the kernel
+    file arch/ppc64/kernel/prom.c, look at scan_flat_dt() function,
+    it's usage in early_init_devtree(), and the corresponding various
+    early_init_dt_scan_*() callbacks. That code can be re-used in a
+    GPL bootloader, and as the author of that code, I would be happy
+    do discuss possible free licencing to any vendor who wishes to
+    integrate all or part of this code into a non-GPL bootloader.
+
+
+
+VI - System-on-a-chip devices and nodes
+=======================================
+
+Many companies are now starting to develop system-on-a-chip
+processors, where the processor core (cpu) and many peripheral devices
+exist on a single piece of silicon.  For these SOCs, an SOC node
+should be used that defines child nodes for the devices that make
+up the SOC. While platforms are not required to use this model in
+order to boot the kernel, it is highly encouraged that all SOC
+implementations define as complete a flat-device-tree as possible to
+describe the devices on the SOC.  This will allow for the
+genericization of much of the kernel code.
+
+
+1) Defining child nodes of an SOC
+---------------------------------
+
+Each device that is part of an SOC may have its own node entry inside
+the SOC node.  For each device that is included in the SOC, the unit
+address property represents the address offset for this device's
+memory-mapped registers in the parent's address space.  The parent's
+address space is defined by the "ranges" property in the top-level soc
+node. The "reg" property for each node that exists directly under the
+SOC node should contain the address mapping from the child address space
+to the parent SOC address space and the size of the device's
+memory-mapped register file.
+
+For many devices that may exist inside an SOC, there are predefined
+specifications for the format of the device tree node.  All SOC child
+nodes should follow these specifications, except where noted in this
+document.
+
+See appendix A for an example partial SOC node definition for the
+MPC8540.
+
+
+2) Specifying interrupt information for SOC devices
+---------------------------------------------------
+
+Each device that is part of an SOC and which generates interrupts
+should have the following properties:
+
+	- interrupt-parent : contains the phandle of the interrupt
+          controller which handles interrupts for this device
+	- interrupts : a list of tuples representing the interrupt
+          number and the interrupt sense and level for each interupt
+          for this device.
+
+This information is used by the kernel to build the interrupt table
+for the interrupt controllers in the system.
+
+Sense and level information should be encoded as follows:
+
+   Devices connected to openPIC-compatible controllers should encode
+   sense and polarity as follows:
+
+	0 = high to low edge sensitive type enabled
+	1 = active low level sensitive type enabled
+	2 = low to high edge sensitive type enabled
+	3 = active high level sensitive type enabled
+
+   ISA PIC interrupt controllers should adhere to the ISA PIC
+   encodings listed below:
+
+	0 =  active low level sensitive type enabled
+	1 =  active high level sensitive type enabled
+	2 =  high to low edge sensitive type enabled
+	3 =  low to high edge sensitive type enabled
+
+
+
+3) Representing devices without a current OF specification
+----------------------------------------------------------
+
+Currently, there are many devices on SOCs that do not have a standard
+representation pre-defined as part of the open firmware
+specifications, mainly because the boards that contain these SOCs are
+not currently booted using open firmware.   This section contains
+descriptions for the SOC devices for which new nodes have been
+defined; this list will expand as more and more SOC-containing
+platforms are moved over to use the flattened-device-tree model.
+
+  a) MDIO IO device
+
+  The MDIO is a bus to which the PHY devices are connected.  For each
+  device that exists on this bus, a child node should be created.  See
+  the definition of the PHY node below for an example of how to define
+  a PHY.
+
+  Required properties:
+    - reg : Offset and length of the register set for the device
+    - device_type : Should be "mdio"
+    - compatible : Should define the compatible device type for the
+      mdio.  Currently, this is most likely to be "gianfar"
+
+  Example:
+
+	mdio@24520 {
+		reg = <24520 20>;
+		device_type = "mdio"; 
+		compatible = "gianfar";
+
+		ethernet-phy@0 {
+			......
+		};
+	};
+
+
+  b) Gianfar-compatible ethernet nodes
+
+  Required properties:
+
+    - device_type : Should be "network"
+    - model : Model of the device.  Can be "TSEC", "eTSEC", or "FEC"
+    - compatible : Should be "gianfar"
+    - reg : Offset and length of the register set for the device
+    - address : List of bytes representing the ethernet address of
+      this controller
+    - interrupts : <a b> where a is the interrupt number and b is a
+      field that represents an encoding of the sense and level
+      information for the interrupt.  This should be encoded based on
+      the information in section 2) depending on the type of interrupt
+      controller you have.
+    - interrupt-parent : the phandle for the interrupt controller that
+      services interrupts for this device.
+    - phy-handle : The phandle for the PHY connected to this ethernet
+      controller.
+
+  Example:
+
+	ethernet@24000 {
+		#size-cells = <0>;
+		device_type = "network";
+		model = "TSEC";
+		compatible = "gianfar";
+		reg = <24000 1000>;
+		address = [ 00 E0 0C 00 73 00 ];
+		interrupts = <d 3 e 3 12 3>;
+		interrupt-parent = <40000>;
+		phy-handle = <2452000>
+	};
+
+
+
+   c) PHY nodes
+
+   Required properties:
+
+    - device_type : Should be "ethernet-phy"
+    - interrupts : <a b> where a is the interrupt number and b is a
+      field that represents an encoding of the sense and level
+      information for the interrupt.  This should be encoded based on
+      the information in section 2) depending on the type of interrupt
+      controller you have.
+    - interrupt-parent : the phandle for the interrupt controller that
+      services interrupts for this device.
+    - reg : The ID number for the phy, usually a small integer
+    - linux,phandle :  phandle for this node; likely referenced by an
+      ethernet controller node.
+
+
+   Example:
+
+	ethernet-phy@0 {
+		linux,phandle = <2452000>
+		interrupt-parent = <40000>;
+		interrupts = <35 1>;
+		reg = <0>;
+		device_type = "ethernet-phy";
+	};
+
+
+   d) Interrupt controllers
+
+   Some SOC devices contain interrupt controllers that are different
+   from the standard Open PIC specification.  The SOC device nodes for
+   these types of controllers should be specified just like a standard
+   OpenPIC controller.  Sense and level information should be encoded
+   as specified in section 2) of this chapter for each device that
+   specifies an interrupt.
+
+   Example :
+
+	pic@40000 {
+		linux,phandle = <40000>;
+		clock-frequency = <0>;
+		interrupt-controller;
+		#address-cells = <0>;
+		reg = <40000 40000>;
+		built-in;
+		compatible = "chrp,open-pic";
+		device_type = "open-pic";
+		big-endian;
+	};
+
+
+   e) I2C
+
+   Required properties :
+
+    - device_type : Should be "i2c"
+    - reg : Offset and length of the register set for the device
+
+   Recommended properties :
+
+    - compatible : Should be "fsl-i2c" for parts compatible with
+      Freescale I2C specifications.
+    - interrupts : <a b> where a is the interrupt number and b is a
+      field that represents an encoding of the sense and level
+      information for the interrupt.  This should be encoded based on
+      the information in section 2) depending on the type of interrupt
+      controller you have.
+    - interrupt-parent : the phandle for the interrupt controller that
+      services interrupts for this device.
+    - dfsrr : boolean; if defined, indicates that this I2C device has
+      a digital filter sampling rate register
+    - fsl5200-clocking : boolean; if defined, indicated that this device
+      uses the FSL 5200 clocking mechanism.
+
+   Example :
+
+	i2c@3000 {
+		interrupt-parent = <40000>;
+		interrupts = <1b 3>;
+		reg = <3000 18>;
+		device_type = "i2c";
+		compatible  = "fsl-i2c";
+		dfsrr;
+	};
+
+
+   f) Freescale SOC USB controllers
+
+   The device node for a USB controller that is part of a Freescale
+   SOC is as described in the document "Open Firmware Recommended
+   Practice : Universal Serial Bus" with the following modifications
+   and additions :  
+
+   Required properties :
+    - compatible : Should be "fsl-usb2-mph" for multi port host usb
+      controllers, or "fsl-usb2-dr" for dual role usb controllers
+    - phy_type : For multi port host usb controllers, should be one of
+      "ulpi", or "serial". For dual role usb controllers, should be
+      one of "ulpi", "utmi", "utmi_wide", or "serial".
+    - reg : Offset and length of the register set for the device
+    - port0 : boolean; if defined, indicates port0 is connected for
+      fsl-usb2-mph compatible controllers.  Either this property or
+      "port1" (or both) must be defined for "fsl-usb2-mph" compatible 
+      controllers.
+    - port1 : boolean; if defined, indicates port1 is connected for
+      fsl-usb2-mph compatible controllers.  Either this property or
+      "port0" (or both) must be defined for "fsl-usb2-mph" compatible 
+      controllers.
+
+   Recommended properties :
+    - interrupts : <a b> where a is the interrupt number and b is a
+      field that represents an encoding of the sense and level
+      information for the interrupt.  This should be encoded based on
+      the information in section 2) depending on the type of interrupt
+      controller you have.
+    - interrupt-parent : the phandle for the interrupt controller that
+      services interrupts for this device.
+
+   Example multi port host usb controller device node : 
+	usb@22000 {
+	        device_type = "usb";
+		compatible = "fsl-usb2-mph";
+		reg = <22000 1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-parent = <700>;
+		interrupts = <27 1>;
+		phy_type = "ulpi";
+		port0;
+		port1;
+	};
+
+   Example dual role usb controller device node : 
+	usb@23000 {
+		device_type = "usb";
+		compatible = "fsl-usb2-dr";
+		reg = <23000 1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-parent = <700>;
+		interrupts = <26 1>;
+		phy = "ulpi";
+	};
+
+
+   More devices will be defined as this spec matures.
+
+
+Appendix A - Sample SOC node for MPC8540
+========================================
+
+Note that the #address-cells and #size-cells for the SoC node
+in this example have been explicitly listed; these are likely
+not necessary as they are usually the same as the root node.
+
+	soc8540@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <00000000 e0000000 00100000>
+		reg = <e0000000 00003000>;
+		bus-frequency = <0>;
+
+		mdio@24520 {
+			reg = <24520 20>;
+			device_type = "mdio";
+			compatible = "gianfar";
+
+			ethernet-phy@0 {
+				linux,phandle = <2452000>
+				interrupt-parent = <40000>;
+				interrupts = <35 1>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+
+			ethernet-phy@1 {
+				linux,phandle = <2452001>
+				interrupt-parent = <40000>;
+				interrupts = <35 1>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+
+			ethernet-phy@3 {
+				linux,phandle = <2452002>
+				interrupt-parent = <40000>;
+				interrupts = <35 1>;
+				reg = <3>;
+				device_type = "ethernet-phy";
+			};
+
+		};
+
+		ethernet@24000 {
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			address = [ 00 E0 0C 00 73 00 ];
+			interrupts = <d 3 e 3 12 3>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452000>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			address = [ 00 E0 0C 00 73 01 ];
+			interrupts = <13 3 14 3 18 3>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452001>;
+		};
+
+		ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "FEC";
+			compatible = "gianfar";
+			reg = <26000 1000>;
+			address = [ 00 E0 0C 00 73 02 ];
+			interrupts = <19 3>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452002>;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;
+			interrupts = <1a 3>;
+			interrupt-parent = <40000>;
+		};
+
+		pic@40000 {
+			linux,phandle = <40000>;
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			reg = <40000 40000>;
+			built-in;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+                        big-endian;
+		};
+
+		i2c@3000 {
+			interrupt-parent = <40000>;
+			interrupts = <1b 3>;
+			reg = <3000 18>;
+			device_type = "i2c";
+			compatible  = "fsl-i2c";
+			dfsrr;
+		};
+
+	};
diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
new file mode 100644
index 0000000..f8c16cb
--- /dev/null
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -0,0 +1,24 @@
+1 Release Date    : Mon Jan 23 14:09:01 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.02.02
+3 Older Version   : 00.00.02.01 
+
+i.	New template defined to represent each family of controllers (identified by processor used). 
+	The template will have defintions that will be initialised to appropritae values for a specific family of controllers. The template definition has four function pointers. During driver initialisation the function pointers will be set based on the controller family type. This change is done to support new controllers that has different processors and thus different register set.
+
+		-Sumant Patro <Sumant.Patro@lsil.com>
+
+1 Release Date    : Mon Dec 19 14:36:26 PST 2005 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.02.00-rc4 
+3 Older Version   : 00.00.02.01 
+
+i.	Code reorganized to remove code duplication in megasas_build_cmd. 
+
+	"There's a lot of duplicate code megasas_build_cmd.  Move that out of the different codepathes and merge the reminder of megasas_build_cmd into megasas_queue_command"
+
+		- Christoph Hellwig <hch@lst.de>
+
+ii.	Defined MEGASAS_IOC_FIRMWARE32 for code paths that handles 32 bit applications in 64 bit systems.
+
+	"MEGASAS_IOC_FIRMWARE can't be redefined if CONFIG_COMPAT is set, we need to define a MEGASAS_IOC_FIRMWARE32 define so native binaries continue to work"
+
+		- Christoph Hellwig <hch@lst.de>
diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt
index 0aeef74..382b439 100644
--- a/Documentation/scsi/aic79xx.txt
+++ b/Documentation/scsi/aic79xx.txt
@@ -1,5 +1,5 @@
 ====================================================================
-=             Adaptec Ultra320 Family Manager Set v1.3.11          =
+=             Adaptec Ultra320 Family Manager Set                  =
 =                                                                  =
 =                            README for                            =
 =                    The Linux Operating System                    =
@@ -63,6 +63,11 @@
                               68-pin)
 2. Version History
 
+   3.0	  (December 1st, 2005)
+	- Updated driver to use SCSI transport class infrastructure
+	- Upported sequencer and core fixes from adaptec released
+	  version 2.0.15 of the driver.
+
    1.3.11 (July 11, 2003)
         - Fix several deadlock issues.
         - Add 29320ALP and 39320B Id's.
@@ -194,7 +199,7 @@
           supported)
         - Support for the PCI-X standard up to 133MHz
         - Support for the PCI v2.2 standard
-	- Domain Validation
+        - Domain Validation
 
    2.2. Operating System Support:
         - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1
@@ -411,77 +416,53 @@
           http://www.adaptec.com.
 
 
-5. Contacting Adaptec
+5. Adaptec Customer Support
 
    A Technical Support Identification (TSID) Number is required for 
    Adaptec technical support.
     - The 12-digit TSID can be found on the white barcode-type label
-      included inside the box with your product. The TSID helps us 
+      included inside the box with your product.  The TSID helps us 
       provide more efficient service by accurately identifying your 
       product and support status.
+
    Support Options
     - Search the Adaptec Support Knowledgebase (ASK) at
       http://ask.adaptec.com for articles, troubleshooting tips, and
-      frequently asked questions for your product.
+      frequently asked questions about your product.
     - For support via Email, submit your question to Adaptec's 
-      Technical Support Specialists at http://ask.adaptec.com.
+      Technical Support Specialists at http://ask.adaptec.com/.
      
    North America
-    - Visit our Web site at http://www.adaptec.com.
-    - To speak with a Fibre Channel/RAID/External Storage Technical
-      Support Specialist, call 1-321-207-2000,
-      Hours: Monday-Friday, 3:00 A.M. to 5:00 P.M., PST.
-      (Not open on holidays)
-    - For Technical Support in all other technologies including 
-      SCSI, call 1-408-934-7274,
-      Hours: Monday-Friday, 6:00 A.M. to 5:00 P.M., PST.
-      (Not open on holidays)
-    - For after hours support, call 1-800-416-8066 ($99/call, 
-      $149/call on holidays)
-    - To order Adaptec products including software and cables, call
-      1-800-442-7274 or 1-408-957-7274. You can also visit our 
-      online store at http://www.adaptecstore.com
+    - Visit our Web site at http://www.adaptec.com/.
+    - For information about Adaptec's support options, call
+      408-957-2550, 24 hours a day, 7 days a week.
+    - To speak with a Technical Support Specialist,
+      * For hardware products, call 408-934-7274,
+        Monday to Friday, 3:00 am to 5:00 pm, PDT.
+      * For RAID and Fibre Channel products, call 321-207-2000,
+        Monday to Friday, 3:00 am to 5:00 pm, PDT.
+      To expedite your service, have your computer with you.
+    - To order Adaptec products, including accessories and cables,
+      call 408-957-7274.  To order cables online go to
+      http://www.adaptec.com/buy-cables/.
 
    Europe
-    - Visit our Web site at http://www.adaptec-europe.com.
-    - English and French: To speak with a Technical Support 
-      Specialist, call one of the following numbers:
-        - English: +32-2-352-3470
-        - French:  +32-2-352-3460
-      Hours: Monday-Thursday, 10:00 to 12:30, 13:30 to 17:30 CET 
-             Friday, 10:00 to 12:30, 13:30 to 16:30 CET
-    - German: To speak with a Technical Support Specialist,
-      call +49-89-456-40660
-      Hours: Monday-Thursday, 09:30 to 12:30, 13:30 to 16:30 CET
-             Friday, 09:30 to 12:30, 13:30 to 15:00 CET
-    - To order Adaptec products, including accessories and cables:
-        - UK: +0800-96-65-26 or fax +0800-731-02-95
-        - Other European countries: +32-11-300-379
-
-   Australia and New Zealand
-    - Visit our Web site at http://www.adaptec.com.au.
-    - To speak with a Technical Support Specialist, call 
-      +612-9416-0698
-      Hours: Monday-Friday, 10:00 A.M. to 4:30 P.M., EAT
-      (Not open on holidays)
+    - Visit our Web site at http://www.adaptec-europe.com/.
+    - To speak with a Technical Support Specialist, call, or email,
+      * German:  +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET,
+        http://ask-de.adaptec.com/.
+      * French:  +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET,
+	http://ask-fr.adaptec.com/.
+      * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT,
+	http://ask.adaptec.com/.
+    - You can order Adaptec cables online at
+      http://www.adaptec.com/buy-cables/.
 
    Japan
+    - Visit our web site at http://www.adaptec.co.jp/.
     - To speak with a Technical Support Specialist, call 
-      +81-3-5308-6120 
-      Hours: Monday-Friday, 9:00 a.m. to 12:00 p.m., 1:00 p.m. to
-      6:00 p.m. TSC
-
-   Hong Kong and China
-    - To speak with a Technical Support Specialist, call 
-      +852-2869-7200
-      Hours: Monday-Friday, 10:00 to 17:00.
-    - Fax Technical Support at +852-2869-7100.
-
-   Singapore
-    - To speak with a Technical Support Specialist, call 
-      +65-245-7470
-      Hours: Monday-Friday, 10:00 to 17:00.
-    - Fax Technical Support at +852-2869-7100
+      +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m.,
+      1:00 p.m. to 6:00 p.m.
 
 -------------------------------------------------------------------
 /*
diff --git a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt
index 47e74dd..3481fcd 100644
--- a/Documentation/scsi/aic7xxx.txt
+++ b/Documentation/scsi/aic7xxx.txt
@@ -309,81 +309,57 @@
    -----------------------------------------------------------------
 
    Example:
-   'options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1"
+   'options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1'
         enables verbose logging, Disable EISA/VLB probing,
         and set tag depth on Controller 1/Target 2 to 10 tags.
 
-3. Contacting Adaptec
+4. Adaptec Customer Support
 
    A Technical Support Identification (TSID) Number is required for 
    Adaptec technical support.
     - The 12-digit TSID can be found on the white barcode-type label
-      included inside the box with your product. The TSID helps us 
+      included inside the box with your product.  The TSID helps us 
       provide more efficient service by accurately identifying your 
       product and support status.
+
    Support Options
     - Search the Adaptec Support Knowledgebase (ASK) at
       http://ask.adaptec.com for articles, troubleshooting tips, and
-      frequently asked questions for your product.
+      frequently asked questions about your product.
     - For support via Email, submit your question to Adaptec's 
-      Technical Support Specialists at http://ask.adaptec.com.
+      Technical Support Specialists at http://ask.adaptec.com/.
      
    North America
-    - Visit our Web site at http://www.adaptec.com.
-    - To speak with a Fibre Channel/RAID/External Storage Technical
-      Support Specialist, call 1-321-207-2000,
-      Hours: Monday-Friday, 3:00 A.M. to 5:00 P.M., PST.
-      (Not open on holidays)
-    - For Technical Support in all other technologies including 
-      SCSI, call 1-408-934-7274,
-      Hours: Monday-Friday, 6:00 A.M. to 5:00 P.M., PST.
-      (Not open on holidays)
-    - For after hours support, call 1-800-416-8066 ($99/call, 
-      $149/call on holidays)
-    - To order Adaptec products including software and cables, call
-      1-800-442-7274 or 1-408-957-7274. You can also visit our 
-      online store at http://www.adaptecstore.com
+    - Visit our Web site at http://www.adaptec.com/.
+    - For information about Adaptec's support options, call
+      408-957-2550, 24 hours a day, 7 days a week.
+    - To speak with a Technical Support Specialist,
+      * For hardware products, call 408-934-7274,
+        Monday to Friday, 3:00 am to 5:00 pm, PDT.
+      * For RAID and Fibre Channel products, call 321-207-2000,
+        Monday to Friday, 3:00 am to 5:00 pm, PDT.
+      To expedite your service, have your computer with you.
+    - To order Adaptec products, including accessories and cables,
+      call 408-957-7274.  To order cables online go to
+      http://www.adaptec.com/buy-cables/.
 
    Europe
-    - Visit our Web site at http://www.adaptec-europe.com.
-    - English and French: To speak with a Technical Support 
-      Specialist, call one of the following numbers:
-        - English: +32-2-352-3470
-        - French:  +32-2-352-3460
-      Hours: Monday-Thursday, 10:00 to 12:30, 13:30 to 17:30 CET 
-             Friday, 10:00 to 12:30, 13:30 to 16:30 CET
-    - German: To speak with a Technical Support Specialist,
-      call +49-89-456-40660
-      Hours: Monday-Thursday, 09:30 to 12:30, 13:30 to 16:30 CET
-             Friday, 09:30 to 12:30, 13:30 to 15:00 CET
-    - To order Adaptec products, including accessories and cables:
-        - UK: +0800-96-65-26 or fax +0800-731-02-95
-        - Other European countries: +32-11-300-379
-
-   Australia and New Zealand
-    - Visit our Web site at http://www.adaptec.com.au.
-    - To speak with a Technical Support Specialist, call 
-      +612-9416-0698
-      Hours: Monday-Friday, 10:00 A.M. to 4:30 P.M., EAT
-      (Not open on holidays)
+    - Visit our Web site at http://www.adaptec-europe.com/.
+    - To speak with a Technical Support Specialist, call, or email,
+      * German:  +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET,
+        http://ask-de.adaptec.com/.
+      * French:  +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET,
+	http://ask-fr.adaptec.com/.
+      * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT,
+	http://ask.adaptec.com/.
+    - You can order Adaptec cables online at
+      http://www.adaptec.com/buy-cables/.
 
    Japan
+    - Visit our web site at http://www.adaptec.co.jp/.
     - To speak with a Technical Support Specialist, call 
-      +81-3-5308-6120 
-      Hours: Monday-Friday, 9:00 a.m. to 12:00 p.m., 1:00 p.m. to
-      6:00 p.m. TSC
-
-   Hong Kong and China
-    - To speak with a Technical Support Specialist, call 
-      +852-2869-7200
-      Hours: Monday-Friday, 10:00 to 17:00.
-    - Fax Technical Support at +852-2869-7100.
-
-   Singapore
-    - To speak with a Technical Support Specialist, call 
-      +65-245-7470
-      Hours: Monday-Friday, 10:00 to 17:00.
-    - Fax Technical Support at +852-2869-7100
+      +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m.,
+      1:00 p.m. to 6:00 p.m.
 
 -------------------------------------------------------------------
 /*
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index d257801..36b511c 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -837,8 +837,10 @@
 
     Module for AC'97 motherboards from Intel and compatibles.
 			* Intel i810/810E, i815, i820, i830, i84x, MX440
+				ICH5, ICH6, ICH7, ESB2
 			* SiS 7012 (SiS 735)
-			* NVidia NForce, NForce2
+			* NVidia NForce, NForce2, NForce3, MCP04, CK804
+				 CK8, CK8S, MCP501
 			* AMD AMD768, AMD8111
 			* ALi m5455
 
@@ -868,6 +870,12 @@
   --------------------
 
     Module for Intel ICH (i8x0) chipset MC97 modems.
+			* Intel i810/810E, i815, i820, i830, i84x, MX440
+				ICH5, ICH6, ICH7
+			* SiS 7013 (SiS 735)
+			* NVidia NForce, NForce2, NForce2s, NForce3
+			* AMD AMD8111
+			* ALi m5455
 
     ac97_clock	  - AC'97 codec clock base (0 = auto-detect)
 
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index e651ed8..4251085 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -5206,14 +5206,14 @@
         You need to pass the <function>snd_dma_pci_data(pci)</function>,
         where pci is the struct <structname>pci_dev</structname> pointer
         of the chip as well.
-        The <type>snd_sg_buf_t</type> instance is created as
+        The <type>struct snd_sg_buf</type> instance is created as
         substream-&gt;dma_private. You can cast
         the pointer like: 
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  struct snd_sg_buf *sgbuf = (struct snd_sg_buf_t*)substream->dma_private;
+  struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
 ]]>
           </programlisting>
         </informalexample>
diff --git a/Documentation/spi/butterfly b/Documentation/spi/butterfly
index a2e8c8d..9927af7a 100644
--- a/Documentation/spi/butterfly
+++ b/Documentation/spi/butterfly
@@ -12,13 +12,20 @@
 directly to the Butterfly.  Or (if you have the parts and skills) you
 can come up with something fancier, providing ciruit protection to the
 Butterfly and the printer port, or with a better power supply than two
-signal pins from the printer port.
+signal pins from the printer port.  Or for that matter, you can use
+similar cables to talk to many AVR boards, even a breadboard.
+
+This is more powerful than "ISP programming" cables since it lets kernel
+SPI protocol drivers interact with the AVR, and could even let the AVR
+issue interrupts to them.  Later, your protocol driver should work
+easily with a "real SPI controller", instead of this bitbanger.
 
 
 The first cable connections will hook Linux up to one SPI bus, with the
 AVR and a DataFlash chip; and to the AVR reset line.  This is all you
 need to reflash the firmware, and the pins are the standard Atmel "ISP"
-connector pins (used also on non-Butterfly AVR boards).
+connector pins (used also on non-Butterfly AVR boards).  On the parport
+side this is like "sp12" programming cables.
 
 	Signal	  Butterfly	  Parport (DB-25)
 	------	  ---------	  ---------------
@@ -40,10 +47,14 @@
 	SELECT	= J400.PB0/nSS	= pin 17/C3,nSELECT
 	GND	= J400.GND	= pin 24/GND
 
-The "USI" controller, using J405, can be used for a second SPI bus.  That
-would let you talk to the AVR over SPI, running firmware that makes it act
-as an SPI slave, while letting either Linux or the AVR use the DataFlash.
-There are plenty of spare parport pins to wire this one up, such as:
+Or you could flash firmware making the AVR into an SPI slave (keeping the
+DataFlash in reset) and tweak the spi_butterfly driver to make it bind to
+the driver for your custom SPI-based protocol.
+
+The "USI" controller, using J405, can also be used for a second SPI bus.
+That would let you talk to the AVR using custom SPI-with-USI firmware,
+while letting either Linux or the AVR use the DataFlash.  There are plenty
+of spare parport pins to wire this one up, such as:
 
 	Signal	  Butterfly	  Parport (DB-25)
 	------	  ---------	  ---------------
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 6910c01..a46c10f 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -27,6 +27,8 @@
 - laptop_mode
 - block_dump
 - drop-caches
+- zone_reclaim_mode
+- zone_reclaim_interval
 
 ==============================================================
 
@@ -120,3 +122,59 @@
 
 The initial value is zero.  Kernel does not use this value at boot time to set
 the high water marks for each per cpu page list.
+
+===============================================================
+
+zone_reclaim_mode:
+
+Zone_reclaim_mode allows to set more or less agressive approaches to
+reclaim memory when a zone runs out of memory. If it is set to zero then no
+zone reclaim occurs. Allocations will be satisfied from other zones / nodes
+in the system.
+
+This is value ORed together of
+
+1	= Zone reclaim on
+2	= Zone reclaim writes dirty pages out
+4	= Zone reclaim swaps pages
+8	= Also do a global slab reclaim pass
+
+zone_reclaim_mode is set during bootup to 1 if it is determined that pages
+from remote zones will cause a measurable performance reduction. The
+page allocator will then reclaim easily reusable pages (those page
+cache pages that are currently not used) before allocating off node pages.
+
+It may be beneficial to switch off zone reclaim if the system is
+used for a file server and all of memory should be used for caching files
+from disk. In that case the caching effect is more important than
+data locality.
+
+Allowing zone reclaim to write out pages stops processes that are
+writing large amounts of data from dirtying pages on other nodes. Zone
+reclaim will write out dirty pages if a zone fills up and so effectively
+throttle the process. This may decrease the performance of a single process
+since it cannot use all of system memory to buffer the outgoing writes
+anymore but it preserve the memory on other nodes so that the performance
+of other processes running on other nodes will not be affected.
+
+Allowing regular swap effectively restricts allocations to the local
+node unless explicitly overridden by memory policies or cpuset
+configurations.
+
+It may be advisable to allow slab reclaim if the system makes heavy
+use of files and builds up large slab caches. However, the slab
+shrink operation is global, may take a long time and free slabs
+in all nodes of the system.
+
+================================================================
+
+zone_reclaim_interval:
+
+The time allowed for off node allocations after zone reclaim
+has failed to reclaim enough pages to allow a local allocation.
+
+Time is set in seconds and set by default to 30 seconds.
+
+Reduce the interval if undesired off node allocations occur. However, too
+frequent scans will have a negative impact onoff node allocation performance.
+
diff --git a/Documentation/unshare.txt b/Documentation/unshare.txt
new file mode 100644
index 0000000..90a5e9e
--- /dev/null
+++ b/Documentation/unshare.txt
@@ -0,0 +1,295 @@
+
+unshare system call:
+--------------------
+This document describes the new system call, unshare. The document
+provides an overview of the feature, why it is needed, how it can
+be used, its interface specification, design, implementation and
+how it can be tested.
+
+Change Log:
+-----------
+version 0.1  Initial document, Janak Desai (janak@us.ibm.com), Jan 11, 2006
+
+Contents:
+---------
+	1) Overview
+	2) Benefits
+	3) Cost
+	4) Requirements
+	5) Functional Specification
+	6) High Level Design
+	7) Low Level Design
+	8) Test Specification
+	9) Future Work
+
+1) Overview
+-----------
+Most legacy operating system kernels support an abstraction of threads
+as multiple execution contexts within a process. These kernels provide
+special resources and mechanisms to maintain these "threads". The Linux
+kernel, in a clever and simple manner, does not make distinction
+between processes and "threads". The kernel allows processes to share
+resources and thus they can achieve legacy "threads" behavior without
+requiring additional data structures and mechanisms in the kernel. The
+power of implementing threads in this manner comes not only from
+its simplicity but also from allowing application programmers to work
+outside the confinement of all-or-nothing shared resources of legacy
+threads. On Linux, at the time of thread creation using the clone system
+call, applications can selectively choose which resources to share
+between threads.
+
+unshare system call adds a primitive to the Linux thread model that
+allows threads to selectively 'unshare' any resources that were being
+shared at the time of their creation. unshare was conceptualized by
+Al Viro in the August of 2000, on the Linux-Kernel mailing list, as part
+of the discussion on POSIX threads on Linux.  unshare augments the
+usefulness of Linux threads for applications that would like to control
+shared resources without creating a new process. unshare is a natural
+addition to the set of available primitives on Linux that implement
+the concept of process/thread as a virtual machine.
+
+2) Benefits
+-----------
+unshare would be useful to large application frameworks such as PAM
+where creating a new process to control sharing/unsharing of process
+resources is not possible. Since namespaces are shared by default
+when creating a new process using fork or clone, unshare can benefit
+even non-threaded applications if they have a need to disassociate
+from default shared namespace. The following lists two use-cases
+where unshare can be used.
+
+2.1 Per-security context namespaces
+-----------------------------------
+unshare can be used to implement polyinstantiated directories using
+the kernel's per-process namespace mechanism. Polyinstantiated directories,
+such as per-user and/or per-security context instance of /tmp, /var/tmp or
+per-security context instance of a user's home directory, isolate user
+processes when working with these directories. Using unshare, a PAM
+module can easily setup a private namespace for a user at login.
+Polyinstantiated directories are required for Common Criteria certification
+with Labeled System Protection Profile, however, with the availability
+of shared-tree feature in the Linux kernel, even regular Linux systems
+can benefit from setting up private namespaces at login and
+polyinstantiating /tmp, /var/tmp and other directories deemed
+appropriate by system administrators.
+
+2.2 unsharing of virtual memory and/or open files
+-------------------------------------------------
+Consider a client/server application where the server is processing
+client requests by creating processes that share resources such as
+virtual memory and open files. Without unshare, the server has to
+decide what needs to be shared at the time of creating the process
+which services the request. unshare allows the server an ability to
+disassociate parts of the context during the servicing of the
+request. For large and complex middleware application frameworks, this
+ability to unshare after the process was created can be very
+useful.
+
+3) Cost
+-------
+In order to not duplicate code and to handle the fact that unshare
+works on an active task (as opposed to clone/fork working on a newly
+allocated inactive task) unshare had to make minor reorganizational
+changes to copy_* functions utilized by clone/fork system call.
+There is a cost associated with altering existing, well tested and
+stable code to implement a new feature that may not get exercised
+extensively in the beginning. However, with proper design and code
+review of the changes and creation of an unshare test for the LTP
+the benefits of this new feature can exceed its cost.
+
+4) Requirements
+---------------
+unshare reverses sharing that was done using clone(2) system call,
+so unshare should have a similar interface as clone(2). That is,
+since flags in clone(int flags, void *stack) specifies what should
+be shared, similar flags in unshare(int flags) should specify
+what should be unshared. Unfortunately, this may appear to invert
+the meaning of the flags from the way they are used in clone(2).
+However, there was no easy solution that was less confusing and that
+allowed incremental context unsharing in future without an ABI change.
+
+unshare interface should accommodate possible future addition of
+new context flags without requiring a rebuild of old applications.
+If and when new context flags are added, unshare design should allow
+incremental unsharing of those resources on an as needed basis.
+
+5) Functional Specification
+---------------------------
+NAME
+	unshare - disassociate parts of the process execution context
+
+SYNOPSIS
+	#include <sched.h>
+
+	int unshare(int flags);
+
+DESCRIPTION
+	unshare allows a process to disassociate parts of its execution
+	context that are currently being shared with other processes. Part
+	of execution context, such as the namespace, is shared by default
+	when a new process is created using fork(2), while other parts,
+	such as the virtual memory, open file descriptors, etc, may be
+	shared by explicit request to share them when creating a process
+	using clone(2).
+
+	The main use of unshare is to allow a process to control its
+	shared execution context without creating a new process.
+
+	The flags argument specifies one or bitwise-or'ed of several of
+	the following constants.
+
+	CLONE_FS
+		If CLONE_FS is set, file system information of the caller
+		is disassociated from the shared file system information.
+
+	CLONE_FILES
+		If CLONE_FILES is set, the file descriptor table of the
+		caller is disassociated from the shared file descriptor
+		table.
+
+	CLONE_NEWNS
+		If CLONE_NEWNS is set, the namespace of the caller is
+		disassociated from the shared namespace.
+
+	CLONE_VM
+		If CLONE_VM is set, the virtual memory of the caller is
+		disassociated from the shared virtual memory.
+
+RETURN VALUE
+	On success, zero returned. On failure, -1 is returned and errno is
+
+ERRORS
+	EPERM	CLONE_NEWNS was specified by a non-root process (process
+		without CAP_SYS_ADMIN).
+
+	ENOMEM	Cannot allocate sufficient memory to copy parts of caller's
+		context that need to be unshared.
+
+	EINVAL	Invalid flag was specified as an argument.
+
+CONFORMING TO
+	The unshare() call is Linux-specific and  should  not be used
+	in programs intended to be portable.
+
+SEE ALSO
+	clone(2), fork(2)
+
+6) High Level Design
+--------------------
+Depending on the flags argument, the unshare system call allocates
+appropriate process context structures, populates it with values from
+the current shared version, associates newly duplicated structures
+with the current task structure and releases corresponding shared
+versions. Helper functions of clone (copy_*) could not be used
+directly by unshare because of the following two reasons.
+  1) clone operates on a newly allocated not-yet-active task
+     structure, where as unshare operates on the current active
+     task. Therefore unshare has to take appropriate task_lock()
+     before associating newly duplicated context structures
+  2) unshare has to allocate and duplicate all context structures
+     that are being unshared, before associating them with the
+     current task and releasing older shared structures. Failure
+     do so will create race conditions and/or oops when trying
+     to backout due to an error. Consider the case of unsharing
+     both virtual memory and namespace. After successfully unsharing
+     vm, if the system call encounters an error while allocating
+     new namespace structure, the error return code will have to
+     reverse the unsharing of vm. As part of the reversal the
+     system call will have to go back to older, shared, vm
+     structure, which may not exist anymore.
+
+Therefore code from copy_* functions that allocated and duplicated
+current context structure was moved into new dup_* functions. Now,
+copy_* functions call dup_* functions to allocate and duplicate
+appropriate context structures and then associate them with the
+task structure that is being constructed. unshare system call on
+the other hand performs the following:
+  1) Check flags to force missing, but implied, flags
+  2) For each context structure, call the corresponding unshare
+     helper function to allocate and duplicate a new context
+     structure, if the appropriate bit is set in the flags argument.
+  3) If there is no error in allocation and duplication and there
+     are new context structures then lock the current task structure,
+     associate new context structures with the current task structure,
+     and release the lock on the current task structure.
+  4) Appropriately release older, shared, context structures.
+
+7) Low Level Design
+-------------------
+Implementation of unshare can be grouped in the following 4 different
+items:
+  a) Reorganization of existing copy_* functions
+  b) unshare system call service function
+  c) unshare helper functions for each different process context
+  d) Registration of system call number for different architectures
+
+  7.1) Reorganization of copy_* functions
+       Each copy function such as copy_mm, copy_namespace, copy_files,
+       etc, had roughly two components. The first component allocated
+       and duplicated the appropriate structure and the second component
+       linked it to the task structure passed in as an argument to the copy
+       function. The first component was split into its own function.
+       These dup_* functions allocated and duplicated the appropriate
+       context structure. The reorganized copy_* functions invoked
+       their corresponding dup_* functions and then linked the newly
+       duplicated structures to the task structure with which the
+       copy function was called.
+
+  7.2) unshare system call service function
+       * Check flags
+	 Force implied flags. If CLONE_THREAD is set force CLONE_VM.
+	 If CLONE_VM is set, force CLONE_SIGHAND. If CLONE_SIGHAND is
+	 set and signals are also being shared, force CLONE_THREAD. If
+	 CLONE_NEWNS is set, force CLONE_FS.
+       * For each context flag, invoke the corresponding unshare_*
+	 helper routine with flags passed into the system call and a
+	 reference to pointer pointing the new unshared structure
+       * If any new structures are created by unshare_* helper
+	 functions, take the task_lock() on the current task,
+	 modify appropriate context pointers, and release the
+         task lock.
+       * For all newly unshared structures, release the corresponding
+         older, shared, structures.
+
+  7.3) unshare_* helper functions
+       For unshare_* helpers corresponding to CLONE_SYSVSEM, CLONE_SIGHAND,
+       and CLONE_THREAD, return -EINVAL since they are not implemented yet.
+       For others, check the flag value to see if the unsharing is
+       required for that structure. If it is, invoke the corresponding
+       dup_* function to allocate and duplicate the structure and return
+       a pointer to it.
+
+  7.4) Appropriately modify architecture specific code to register the
+       the new system call.
+
+8) Test Specification
+---------------------
+The test for unshare should test the following:
+  1) Valid flags: Test to check that clone flags for signal and
+	signal handlers, for which unsharing is not implemented
+	yet, return -EINVAL.
+  2) Missing/implied flags: Test to make sure that if unsharing
+	namespace without specifying unsharing of filesystem, correctly
+	unshares both namespace and filesystem information.
+  3) For each of the four (namespace, filesystem, files and vm)
+	supported unsharing, verify that the system call correctly
+	unshares the appropriate structure. Verify that unsharing
+	them individually as well as in combination with each
+	other works as expected.
+  4) Concurrent execution: Use shared memory segments and futex on
+	an address in the shm segment to synchronize execution of
+	about 10 threads. Have a couple of threads execute execve,
+	a couple _exit and the rest unshare with different combination
+	of flags. Verify that unsharing is performed as expected and
+	that there are no oops or hangs.
+
+9) Future Work
+--------------
+The current implementation of unshare does not allow unsharing of
+signals and signal handlers. Signals are complex to begin with and
+to unshare signals and/or signal handlers of a currently running
+process is even more complex. If in the future there is a specific
+need to allow unsharing of signals and/or signal handlers, it can
+be incrementally added to unshare without affecting legacy
+applications using unshare.
+
diff --git a/Documentation/usb/et61x251.txt b/Documentation/usb/et61x251.txt
new file mode 100644
index 0000000..b44dda4
--- /dev/null
+++ b/Documentation/usb/et61x251.txt
@@ -0,0 +1,306 @@
+
+                       ET61X[12]51 PC Camera Controllers
+                                Driver for Linux
+                       =================================
+
+                               - Documentation -
+
+
+Index
+=====
+1.  Copyright
+2.  Disclaimer
+3.  License
+4.  Overview and features
+5.  Module dependencies
+6.  Module loading
+7.  Module parameters
+8.  Optional device control through "sysfs"
+9.  Supported devices
+10. Notes for V4L2 application developers
+11. Contact information
+
+
+1. Copyright
+============
+Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>
+
+
+2. Disclaimer
+=============
+Etoms is a trademark of Etoms Electronics Corp.
+This software is not developed or sponsored by Etoms Electronics.
+
+
+3. License
+==========
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU 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.
+
+
+4. Overview and features
+========================
+This driver supports the video interface of the devices mounting the ET61X151
+or ET61X251 PC Camera Controllers.
+
+It's worth to note that Etoms Electronics has never collaborated with the
+author during the development of this project; despite several requests,
+Etoms Electronics also refused to release enough detailed specifications of
+the video compression engine.
+
+The driver relies on the Video4Linux2 and USB core modules. It has been
+designed to run properly on SMP systems as well.
+
+The latest version of the ET61X[12]51 driver can be found at the following URL:
+http://www.linux-projects.org/
+
+Some of the features of the driver are:
+
+- full compliance with the Video4Linux2 API (see also "Notes for V4L2
+  application developers" paragraph);
+- available mmap or read/poll methods for video streaming through isochronous
+  data transfers;
+- automatic detection of image sensor;
+- support for any window resolutions and optional panning within the maximum
+  pixel area of image sensor;
+- image downscaling with arbitrary scaling factors from 1 and 2 in both
+  directions (see "Notes for V4L2 application developers" paragraph);
+- two different video formats for uncompressed or compressed data in low or
+  high compression quality (see also "Notes for V4L2 application developers"
+  paragraph);
+- full support for the capabilities of every possible image sensors that can
+  be connected to the ET61X[12]51 bridges, including, for istance, red, green,
+  blue and global gain adjustments and exposure control (see "Supported
+  devices" paragraph for details);
+- use of default color settings for sunlight conditions;
+- dynamic I/O interface for both ET61X[12]51 and image sensor control (see
+  "Optional device control through 'sysfs'" paragraph);
+- dynamic driver control thanks to various module parameters (see "Module
+  parameters" paragraph);
+- up to 64 cameras can be handled at the same time; they can be connected and
+  disconnected from the host many times without turning off the computer, if
+  the system supports hotplugging;
+- no known bugs.
+
+
+5. Module dependencies
+======================
+For it to work properly, the driver needs kernel support for Video4Linux and
+USB.
+
+The following options of the kernel configuration file must be enabled and
+corresponding modules must be compiled:
+
+	# Multimedia devices
+	#
+	CONFIG_VIDEO_DEV=m
+
+To enable advanced debugging functionality on the device through /sysfs:
+
+	# Multimedia devices
+	#
+	CONFIG_VIDEO_ADV_DEBUG=y
+
+	# USB support
+	#
+	CONFIG_USB=m
+
+In addition, depending on the hardware being used, the modules below are
+necessary:
+
+	# USB Host Controller Drivers
+	#
+	CONFIG_USB_EHCI_HCD=m
+	CONFIG_USB_UHCI_HCD=m
+	CONFIG_USB_OHCI_HCD=m
+
+And finally:
+
+	# USB Multimedia devices
+	#
+	CONFIG_USB_ET61X251=m
+
+
+6. Module loading
+=================
+To use the driver, it is necessary to load the "et61x251" module into memory
+after every other module required: "videodev", "usbcore" and, depending on
+the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd".
+
+Loading can be done as shown below:
+
+	[root@localhost home]# modprobe et61x251
+
+At this point the devices should be recognized. You can invoke "dmesg" to
+analyze kernel messages and verify that the loading process has gone well:
+
+	[user@localhost home]$ dmesg
+
+
+7. Module parameters
+====================
+Module parameters are listed below:
+-------------------------------------------------------------------------------
+Name:           video_nr
+Type:           short array (min = 0, max = 64)
+Syntax:         <-1|n[,...]>
+Description:    Specify V4L2 minor mode number:
+                -1 = use next available
+                 n = use minor number n
+                You can specify up to 64 cameras this way.
+                For example:
+                video_nr=-1,2,-1 would assign minor number 2 to the second
+                registered camera and use auto for the first one and for every
+                other camera.
+Default:        -1
+-------------------------------------------------------------------------------
+Name:           force_munmap
+Type:           bool array (min = 0, max = 64)
+Syntax:         <0|1[,...]>
+Description:    Force the application to unmap previously mapped buffer memory
+                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+                all the applications support this feature. This parameter is
+                specific for each detected camera.
+                0 = do not force memory unmapping
+                1 = force memory unmapping (save memory)
+Default:        0
+-------------------------------------------------------------------------------
+Name:           debug
+Type:           ushort
+Syntax:         <n>
+Description:    Debugging information level, from 0 to 3:
+                0 = none (use carefully)
+                1 = critical errors
+                2 = significant informations
+                3 = more verbose messages
+                Level 3 is useful for testing only, when only one device
+                is used at the same time. It also shows some more informations
+                about the hardware being detected. This module parameter can be
+                changed at runtime thanks to the /sys filesystem interface.
+Default:        2
+-------------------------------------------------------------------------------
+
+
+8. Optional device control through "sysfs"
+==========================================
+If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
+it is possible to read and write both the ET61X[12]51 and the image sensor
+registers by using the "sysfs" filesystem interface.
+
+There are four files in the /sys/class/video4linux/videoX directory for each
+registered camera: "reg", "val", "i2c_reg" and "i2c_val". The first two files
+control the ET61X[12]51 bridge, while the other two control the sensor chip.
+"reg" and "i2c_reg" hold the values of the current register index where the
+following reading/writing operations are addressed at through "val" and
+"i2c_val". Their use is not intended for end-users, unless you know what you
+are doing. Remember that you must be logged in as root before writing to them.
+
+As an example, suppose we were to want to read the value contained in the
+register number 1 of the sensor register table - which is usually the product
+identifier - of the camera registered as "/dev/video0":
+
+	[root@localhost #] cd /sys/class/video4linux/video0
+	[root@localhost #] echo 1 > i2c_reg
+	[root@localhost #] cat i2c_val
+
+Note that if the sensor registers can not be read, "cat" will fail.
+To avoid race conditions, all the I/O accesses to the files are serialized.
+
+
+9. Supported devices
+====================
+None of the names of the companies as well as their products will be mentioned
+here. They have never collaborated with the author, so no advertising.
+
+From the point of view of a driver, what unambiguously identify a device are
+its vendor and product USB identifiers. Below is a list of known identifiers of
+devices mounting the ET61X[12]51 PC camera controllers:
+
+Vendor ID  Product ID
+---------  ----------
+0x102c     0x6151
+0x102c     0x6251
+0x102c     0x6253
+0x102c     0x6254
+0x102c     0x6255
+0x102c     0x6256
+0x102c     0x6257
+0x102c     0x6258
+0x102c     0x6259
+0x102c     0x625a
+0x102c     0x625b
+0x102c     0x625c
+0x102c     0x625d
+0x102c     0x625e
+0x102c     0x625f
+0x102c     0x6260
+0x102c     0x6261
+0x102c     0x6262
+0x102c     0x6263
+0x102c     0x6264
+0x102c     0x6265
+0x102c     0x6266
+0x102c     0x6267
+0x102c     0x6268
+0x102c     0x6269
+
+The following image sensors are supported:
+
+Model       Manufacturer
+-----       ------------
+TAS5130D1B  Taiwan Advanced Sensor Corporation
+
+All the available control settings of each image sensor are supported through
+the V4L2 interface.
+
+
+10. Notes for V4L2 application developers
+========================================
+This driver follows the V4L2 API specifications. In particular, it enforces two
+rules:
+
+- exactly one I/O method, either "mmap" or "read", is associated with each
+file descriptor. Once it is selected, the application must close and reopen the
+device to switch to the other I/O method;
+
+- although it is not mandatory, previously mapped buffer memory should always
+be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's.
+The same number of buffers as before will be allocated again to match the size
+of the new video frames, so you have to map the buffers again before any I/O
+attempts on them.
+
+Consistently with the hardware limits, this driver also supports image
+downscaling with arbitrary scaling factors from 1 and 2 in both directions.
+However, the V4L2 API specifications don't correctly define how the scaling
+factor can be chosen arbitrarily by the "negotiation" of the "source" and
+"target" rectangles. To work around this flaw, we have added the convention
+that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
+scaling factor is restored to 1.
+
+This driver supports two different video formats: the first one is the "8-bit
+Sequential Bayer" format and can be used to obtain uncompressed video data
+from the device through the current I/O method, while the second one provides
+"raw" compressed video data (without frame headers not related to the
+compressed data). The current compression quality may vary from 0 to 1 and can
+be selected or queried thanks to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP
+V4L2 ioctl's.
+
+
+11. Contact information
+=======================
+The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
+
+GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is
+'FCE635A4'; the public 1024-bit key should be available at any keyserver;
+the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt
index 3f8a119..c6b7641 100644
--- a/Documentation/usb/sn9c102.txt
+++ b/Documentation/usb/sn9c102.txt
@@ -17,16 +17,15 @@
 7.  Module parameters
 8.  Optional device control through "sysfs"
 9.  Supported devices
-10. How to add plug-in's for new image sensors
-11. Notes for V4L2 application developers
-12. Video frame formats
-13. Contact information
-14. Credits
+10. Notes for V4L2 application developers
+11. Video frame formats
+12. Contact information
+13. Credits
 
 
 1. Copyright
 ============
-Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>
+Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>
 
 
 2. Disclaimer
@@ -54,9 +53,8 @@
 
 4. Overview and features
 ========================
-This driver attempts to support the video and audio streaming capabilities of
-the devices mounting the SONiX SN9C101, SN9C102 and SN9C103 PC Camera
-Controllers.
+This driver attempts to support the video interface of the devices mounting the
+SONiX SN9C101, SN9C102 and SN9C103 PC Camera Controllers.
 
 It's worth to note that SONiX has never collaborated with the author during the
 development of this project, despite several requests for enough detailed
@@ -78,6 +76,7 @@
 - available mmap or read/poll methods for video streaming through isochronous
   data transfers;
 - automatic detection of image sensor;
+- support for built-in microphone interface;
 - support for any window resolutions and optional panning within the maximum
   pixel area of image sensor;
 - image downscaling with arbitrary scaling factors from 1, 2 and 4 in both
@@ -96,7 +95,7 @@
   parameters" paragraph);
 - up to 64 cameras can be handled at the same time; they can be connected and
   disconnected from the host many times without turning off the computer, if
-  your system supports hotplugging;
+  the system supports hotplugging;
 - no known bugs.
 
 
@@ -112,6 +111,12 @@
 	#
 	CONFIG_VIDEO_DEV=m
 
+To enable advanced debugging functionality on the device through /sysfs:
+
+	# Multimedia devices
+	#
+	CONFIG_VIDEO_ADV_DEBUG=y
+
 	# USB support
 	#
 	CONFIG_USB=m
@@ -125,6 +130,21 @@
 	CONFIG_USB_UHCI_HCD=m
 	CONFIG_USB_OHCI_HCD=m
 
+The SN9C103 controller also provides a built-in microphone interface. It is
+supported by the USB Audio driver thanks to the ALSA API:
+
+	# Sound
+	#
+	CONFIG_SOUND=y
+
+	# Advanced Linux Sound Architecture
+	#
+	CONFIG_SND=m
+
+	# USB devices
+	#
+	CONFIG_SND_USB_AUDIO=m
+
 And finally:
 
 	# USB Multimedia devices
@@ -153,7 +173,7 @@
 Module parameters are listed below:
 -------------------------------------------------------------------------------
 Name:           video_nr
-Type:           int array (min = 0, max = 64)
+Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]> 
 Description:    Specify V4L2 minor mode number:
                 -1 = use next available
@@ -165,19 +185,19 @@
                 other camera.
 Default:        -1
 -------------------------------------------------------------------------------
-Name:           force_munmap;
+Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]> 
 Description:    Force the application to unmap previously mapped buffer memory
                 before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
                 all the applications support this feature. This parameter is
                 specific for each detected camera.
-                0 = do not force memory unmapping"
-                1 = force memory unmapping (save memory)"
+                0 = do not force memory unmapping
+                1 = force memory unmapping (save memory)
 Default:        0
 -------------------------------------------------------------------------------
 Name:           debug
-Type:           int
+Type:           ushort
 Syntax:         <n> 
 Description:    Debugging information level, from 0 to 3:
                 0 = none (use carefully)
@@ -187,14 +207,15 @@
                 Level 3 is useful for testing only, when only one device
                 is used. It also shows some more informations about the
                 hardware being detected. This parameter can be changed at
-                runtime thanks to the /sys filesystem.
+                runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 
 
 8. Optional device control through "sysfs" [1]
 ==========================================
-It is possible to read and write both the SN9C10x and the image sensor
+If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
+it is possible to read and write both the SN9C10x and the image sensor
 registers by using the "sysfs" filesystem interface.
 
 Every time a supported device is recognized, a write-only file named "green" is
@@ -236,7 +257,7 @@
 
 The sysfs interface also provides the "frame_header" entry, which exports the
 frame header of the most recent requested and captured video frame. The header
-is 12-bytes long and is appended to every video frame by the SN9C10x
+is always 18-bytes long and is appended to every video frame by the SN9C10x
 controllers. As an example, this additional information can be used by the user
 application for implementing auto-exposure features via software. 
 
@@ -250,7 +271,8 @@
 0x03    0xC4          Frame synchronisation pattern.
 0x04    0xC4          Frame synchronisation pattern.
 0x05    0x96          Frame synchronisation pattern.
-0x06    0x00 or 0x01  Unknown meaning. The exact value depends on the chip.
+0x06    0xXX          Unknown meaning. The exact value depends on the chip;
+                      possible values are 0x00, 0x01 and 0x20.
 0x07    0xXX          Variable value, whose bits are ff00uzzc, where ff is a
                       frame counter, u is unknown, zz is a size indicator
                       (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
@@ -267,12 +289,23 @@
                       times the area outside of the specified AE area. For
                       images that are not pure white, the value scales down
                       according to relative whiteness.
+                      according to relative whiteness.
+
+The following bytes are used by the SN9C103 bridge only:
+
+0x0C    0xXX          Unknown meaning
+0x0D    0xXX          Unknown meaning
+0x0E    0xXX          Unknown meaning
+0x0F    0xXX          Unknown meaning
+0x10    0xXX          Unknown meaning
+0x11    0xXX          Unknown meaning
 
 The AE area (sx, sy, ex, ey) in the active window can be set by programming the
 registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C10x controllers, where one unit
 corresponds to 32 pixels.
 
-[1] The frame header has been documented by Bertrik Sikken.
+[1] Part of the meaning of the frame header has been documented by Bertrik
+    Sikken.
 
 
 9. Supported devices
@@ -298,6 +331,7 @@
 0x0c45     0x602b
 0x0c45     0x602c
 0x0c45     0x602d
+0x0c45     0x602e
 0x0c45     0x6030
 0x0c45     0x6080
 0x0c45     0x6082
@@ -348,18 +382,7 @@
 driver.
 
 
-10. How to add plug-in's for new image sensors
-==============================================
-It should be easy to write plug-in's for new sensors by using the small API
-that has been created for this purpose, which is present in "sn9c102_sensor.h"
-(documentation is included there). As an example, have a look at the code in
-"sn9c102_pas106b.c", which uses the mentioned interface.
-
-At the moment, possible unsupported image sensors are: CIS-VF10 (VGA),
-OV7620 (VGA), OV7630 (VGA).
-
-
-11. Notes for V4L2 application developers
+10. Notes for V4L2 application developers
 =========================================
 This driver follows the V4L2 API specifications. In particular, it enforces two
 rules:
@@ -394,7 +417,7 @@
 supplied by this driver).
 
 
-12. Video frame formats [1]
+11. Video frame formats [1]
 =======================
 The SN9C10x PC Camera Controllers can send images in two possible video
 formats over the USB: either native "Sequential RGB Bayer" or Huffman
@@ -455,7 +478,7 @@
     documented by Bertrik Sikken.
 
 
-13. Contact information
+12. Contact information
 =======================
 The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
 
@@ -464,7 +487,7 @@
 the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
 
 
-14. Credits
+13. Credits
 ===========
 Many thanks to following persons for their contribute (listed in alphabetical
 order):
@@ -480,5 +503,5 @@
 - Bertrik Sikken, who reverse-engineered and documented the Huffman compression
   algorithm used in the SN9C10x controllers and implemented the first decoder;
 - Mizuno Takafumi for the donation of a webcam;
-- An "anonymous" donator (who didn't want his name to be revealed) for the
+- an "anonymous" donator (who didn't want his name to be revealed) for the
   donation of a webcam.
diff --git a/Documentation/usb/w9968cf.txt b/Documentation/usb/w9968cf.txt
index 18a4773..9d46cd0 100644
--- a/Documentation/usb/w9968cf.txt
+++ b/Documentation/usb/w9968cf.txt
@@ -57,16 +57,12 @@
 The driver is divided into two modules: the basic one, "w9968cf", is needed for
 the supported devices to work; the second one, "w9968cf-vpp", is an optional
 module, which provides some useful video post-processing functions like video
-decoding, up-scaling and colour conversions. Once the driver is installed,
-every time an application tries to open a recognized device, "w9968cf" checks
-the presence of the "w9968cf-vpp" module and loads it automatically by default.
+decoding, up-scaling and colour conversions.
 
-Please keep in mind that official kernels do not include the second module for
-performance purposes. However it is always recommended to download and install
-the latest and complete release of the driver, replacing the existing one, if
-present: it will be still even possible not to load the "w9968cf-vpp" module at
-all, if you ever want to. Another important missing feature of the version in
-the official Linux 2.4 kernels is the writeable /proc filesystem interface.
+Note that the official kernels do neither include nor support the second
+module for performance purposes. Therefore, it is always recommended to
+download and install the latest and complete release of the driver,
+replacing the existing one, if present.
 
 The latest and full-featured version of the W996[87]CF driver can be found at:
 http://www.linux-projects.org. Please refer to the documentation included in
@@ -201,22 +197,6 @@
                  enabled for the 'ovcamchip' module to be loaded and for
                  this parameter to be present.
 -------------------------------------------------------------------------------
-Name:           vppmod_load
-Type:           bool
-Syntax:         <0|1>
-Description:    Automatic 'w9968cf-vpp' module loading: 0 disabled, 1 enabled.
-                If enabled, every time an application attempts to open a
-                camera, 'insmod' searches for the video post-processing module
-                in the system and loads it automatically (if present).
-                The optional 'w9968cf-vpp' module adds extra image manipulation
-                capabilities to the 'w9968cf' module,like software up-scaling,
-                colour conversions and video decompression for very high frame
-                rates.
-Default:        1
-Note:           The kernel must be compiled with the CONFIG_KMOD option
-                enabled for the 'w9968cf-vpp' module to be loaded and for
-                this parameter to be present.
--------------------------------------------------------------------------------
 Name:           simcams 
 Type:           int 
 Syntax:         <n> 
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
index 56e194f..8bea3fb 100644
--- a/Documentation/video4linux/CARDLIST.cx88
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -42,4 +42,4 @@
  41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  [0070:9800,0070:9802]
  42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025]
  43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1]
- 44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50]
+ 44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50,18ac:db54]
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index cb3a59b..8a35259 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -1,7 +1,7 @@
   0 -> UNKNOWN/GENERIC
   1 -> Proteus Pro [philips reference design]   [1131:2001,1131:2001]
   2 -> LifeView FlyVIDEO3000                    [5168:0138,4e42:0138]
-  3 -> LifeView FlyVIDEO2000                    [5168:0138]
+  3 -> LifeView/Typhoon FlyVIDEO2000            [5168:0138,4e42:0138]
   4 -> EMPRESS                                  [1131:6752]
   5 -> SKNet Monster TV                         [1131:4e85]
   6 -> Tevion MD 9717
@@ -53,12 +53,12 @@
  52 -> AverMedia AverTV/305                     [1461:2108]
  53 -> ASUS TV-FM 7135                          [1043:4845]
  54 -> LifeView FlyTV Platinum FM               [5168:0214,1489:0214]
- 55 -> LifeView FlyDVB-T DUO                    [5168:0502,5168:0306]
+ 55 -> LifeView FlyDVB-T DUO                    [5168:0306]
  56 -> Avermedia AVerTV 307                     [1461:a70a]
  57 -> Avermedia AVerTV GO 007 FM               [1461:f31f]
  58 -> ADS Tech Instant TV (saa7135)            [1421:0350,1421:0351,1421:0370,1421:1370]
  59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
- 60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502]
+ 60 -> LifeView/Typhoon FlyDVB-T Duo Cardbus    [5168:0502,4e42:0502]
  61 -> Philips TOUGH DVB-T reference design     [1131:2004]
  62 -> Compro VideoMate TV Gold+II
  63 -> Kworld Xpert TV PVR7134
diff --git a/Documentation/vm/page_migration b/Documentation/vm/page_migration
new file mode 100644
index 0000000..c52820f
--- /dev/null
+++ b/Documentation/vm/page_migration
@@ -0,0 +1,129 @@
+Page migration
+--------------
+
+Page migration allows the moving of the physical location of pages between
+nodes in a numa system while the process is running. This means that the
+virtual addresses that the process sees do not change. However, the
+system rearranges the physical location of those pages.
+
+The main intend of page migration is to reduce the latency of memory access
+by moving pages near to the processor where the process accessing that memory
+is running.
+
+Page migration allows a process to manually relocate the node on which its
+pages are located through the MF_MOVE and MF_MOVE_ALL options while setting
+a new memory policy. The pages of process can also be relocated
+from another process using the sys_migrate_pages() function call. The
+migrate_pages function call takes two sets of nodes and moves pages of a
+process that are located on the from nodes to the destination nodes.
+
+Manual migration is very useful if for example the scheduler has relocated
+a process to a processor on a distant node. A batch scheduler or an
+administrator may detect the situation and move the pages of the process
+nearer to the new processor. At some point in the future we may have
+some mechanism in the scheduler that will automatically move the pages.
+
+Larger installations usually partition the system using cpusets into
+sections of nodes. Paul Jackson has equipped cpusets with the ability to
+move pages when a task is moved to another cpuset. This allows automatic
+control over locality of a process. If a task is moved to a new cpuset
+then also all its pages are moved with it so that the performance of the
+process does not sink dramatically (as is the case today).
+
+Page migration allows the preservation of the relative location of pages
+within a group of nodes for all migration techniques which will preserve a
+particular memory allocation pattern generated even after migrating a
+process. This is necessary in order to preserve the memory latencies.
+Processes will run with similar performance after migration.
+
+Page migration occurs in several steps. First a high level
+description for those trying to use migrate_pages() and then
+a low level description of how the low level details work.
+
+A. Use of migrate_pages()
+-------------------------
+
+1. Remove pages from the LRU.
+
+   Lists of pages to be migrated are generated by scanning over
+   pages and moving them into lists. This is done by
+   calling isolate_lru_page() or __isolate_lru_page().
+   Calling isolate_lru_page increases the references to the page
+   so that it cannot vanish under us.
+
+2. Generate a list of newly allocates page to move the contents
+   of the first list to.
+
+3. The migrate_pages() function is called which attempts
+   to do the migration. It returns the moved pages in the
+   list specified as the third parameter and the failed
+   migrations in the fourth parameter. The first parameter
+   will contain the pages that could still be retried.
+
+4. The leftover pages of various types are returned
+   to the LRU using putback_to_lru_pages() or otherwise
+   disposed of. The pages will still have the refcount as
+   increased by isolate_lru_pages()!
+
+B. Operation of migrate_pages()
+--------------------------------
+
+migrate_pages does several passes over its list of pages. A page is moved
+if all references to a page are removable at the time.
+
+Steps:
+
+1. Lock the page to be migrated
+
+2. Insure that writeback is complete.
+
+3. Make sure that the page has assigned swap cache entry if
+   it is an anonyous page. The swap cache reference is necessary
+   to preserve the information contain in the page table maps.
+
+4. Prep the new page that we want to move to. It is locked
+   and set to not being uptodate so that all accesses to the new
+   page immediately lock while we are moving references.
+
+5. All the page table references to the page are either dropped (file backed)
+   or converted to swap references (anonymous pages). This should decrease the
+   reference count.
+
+6. The radix tree lock is taken
+
+7. The refcount of the page is examined and we back out if references remain
+   otherwise we know that we are the only one referencing this page.
+
+8. The radix tree is checked and if it does not contain the pointer to this
+   page then we back out.
+
+9. The mapping is checked. If the mapping is gone then a truncate action may
+   be in progress and we back out.
+
+10. The new page is prepped with some settings from the old page so that accesses
+   to the new page will be discovered to have the correct settings.
+
+11. The radix tree is changed to point to the new page.
+
+12. The reference count of the old page is dropped because the reference has now
+    been removed.
+
+13. The radix tree lock is dropped.
+
+14. The page contents are copied to the new page.
+
+15. The remaining page flags are copied to the new page.
+
+16. The old page flags are cleared to indicate that the page does
+    not use any information anymore.
+
+17. Queued up writeback on the new page is triggered.
+
+18. If swap pte's were generated for the page then remove them again.
+
+19. The locks are dropped from the old and new page.
+
+20. The new page is moved to the LRU.
+
+Christoph Lameter, December 19, 2005.
+
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 9c5fc15d..153740f 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -40,6 +40,18 @@
    no_timer_check Don't check the IO-APIC timer. This can work around
 		 problems with incorrect timer initialization on some boards.
 
+   apicmaintimer Run time keeping from the local APIC timer instead
+                 of using the PIT/HPET interrupt for this. This is useful
+                 when the PIT/HPET interrupts are unreliable.
+
+   noapicmaintimer  Don't do time keeping using the APIC timer.
+		 Useful when this option was auto selected, but doesn't work.
+
+   apicpmtimer
+		 Do APIC timer calibration using the pmtimer. Implies
+		 apicmaintimer. Useful when your PIT timer is totally
+		 broken.
+
 Early Console
 
    syntax: earlyprintk=vga
diff --git a/MAINTAINERS b/MAINTAINERS
index ff16eac..9c592aa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -540,7 +540,8 @@
 
 BTTV VIDEO4LINUX DRIVER
 P:	Mauro Carvalho Chehab
-M:	mchehab@brturbo.com.br
+M:	mchehab@infradead.org
+M:	v4l-dvb-maintainer@linuxtv.org
 L:	video4linux-list@redhat.com
 W:	http://linuxtv.org
 T:	git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
@@ -557,7 +558,8 @@
 
 CONFIGFS
 P:	Joel Becker
-M:	Joel Becker <joel.becker@oracle.com>
+M:	joel.becker@oracle.com
+L:	linux-kernel@vger.kernel.org
 S:	Supported
 
 CIRRUS LOGIC GENERIC FBDEV DRIVER
@@ -836,11 +838,12 @@
 
 DVB SUBSYSTEM AND DRIVERS
 P:	LinuxTV.org Project
-M: 	linux-dvb-maintainer@linuxtv.org
+M:	mchehab@infradead.org
+M:	v4l-dvb-maintainer@linuxtv.org
 L: 	linux-dvb@linuxtv.org (subscription required)
 W:	http://linuxtv.org/
 T:	git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
-S:	Supported
+S:	Maintained
 
 EATA-DMA SCSI DRIVER
 P:	Michael Neuffer
@@ -867,6 +870,15 @@
 W:	http://ebtables.sourceforge.net/
 S:	Maintained
 
+EDAC-CORE
+P:      Doug Thompson
+M:      norsk5@xmission.com, dthompson@linuxnetworx.com
+P:      Dave Peterson
+M:      dsp@llnl.gov, dave_peterson@pobox.com
+L:      bluesmoke-devel@lists.sourceforge.net
+W:      bluesmoke.sourceforge.net
+S:      Maintained
+
 EEPRO100 NETWORK DRIVER
 P:	Andrey V. Savochkin
 M:	saw@saw.sw.com.sg
@@ -919,6 +931,12 @@
 L:	ext3-users@redhat.com
 S:	Maintained
 
+F71805F HARDWARE MONITORING DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
 FARSYNC SYNCHRONOUS DRIVER
 P:	Kevin Curtis
 M:	kevin.curtis@farsite.co.uk
@@ -1167,8 +1185,8 @@
 S:	Maintained
 
 SN-IA64 (Itanium) SUB-PLATFORM
-P:	Greg Edwards
-M:	edwardsg@sgi.com
+P:	Jes Sorensen
+M:	jes@sgi.com
 L:	linux-altix@sgi.com
 L:	linux-ia64@vger.kernel.org
 W:	http://www.sgi.com/altix
@@ -1398,7 +1416,7 @@
 P:	Jean Tourrilhes
 L:	irda-users@lists.sourceforge.net (subscribers-only)
 W:	http://irda.sourceforge.net/
-S:	Maintained
+S:	Odd Fixes
 
 ISAPNP
 P:	Jaroslav Kysela
@@ -1843,7 +1861,14 @@
 P:	Patrick McHardy
 M:	kaber@coreworks.de
 L:	netdev@vger.kernel.org
-T:	git kernel.org:/pub/scm/linux/kernel/davem/net-2.6.git
+T:	git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git
+S:	Maintained
+
+NETWORKING [WIRELESS]
+P:	John W. Linville
+M:	linville@tuxdriver.com
+L:	netdev@vger.kernel.org
+T:	git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
 S:	Maintained
 
 IPVS
@@ -1968,7 +1993,6 @@
 P:	Tim Waugh
 M:	tim@cyberelk.net
 P:	David Campbell
-M:	campbell@torque.net
 P:	Andrea Arcangeli
 M:	andrea@suse.de
 L:	linux-parport@lists.infradead.org
@@ -2208,7 +2232,23 @@
 M:	schwidefsky@de.ibm.com
 M:	linux390@de.ibm.com
 L:	linux-390@vm.marist.edu
-W:	http://oss.software.ibm.com/developerworks/opensource/linux390
+W:	http://www.ibm.com/developerworks/linux/linux390/
+S:	Supported
+
+S390 NETWORK DRIVERS
+P:	Frank Pavlic
+M:	fpavlic@de.ibm.com
+M:	linux390@de.ibm.com
+L:	linux-390@vm.marist.edu
+W:	http://www.ibm.com/developerworks/linux/linux390/
+S:	Supported
+
+S390 ZFCP DRIVER
+P:	Andreas Herrmann
+M:	aherrman@de.ibm.com
+M:	linux390@de.ibm.com
+L:	linux-390@vm.marist.edu
+W:	http://www.ibm.com/developerworks/linux/linux390/
 S:	Supported
 
 SAA7146 VIDEO4LINUX-2 DRIVER
@@ -2282,7 +2322,7 @@
 
 SELINUX SECURITY MODULE
 P:	Stephen Smalley
-M:	sds@epoch.ncsc.mil
+M:	sds@tycho.nsa.gov
 P:	James Morris
 M:	jmorris@namei.org
 L:	linux-kernel@vger.kernel.org (kernel issues)
@@ -2536,11 +2576,11 @@
 
 TIPC NETWORK LAYER
 P:	Per Liden
-M:	per.liden@nospam.ericsson.com
+M:	per.liden@ericsson.com
 P:	Jon Maloy
-M:	jon.maloy@nospam.ericsson.com
+M:	jon.maloy@ericsson.com
 P:	Allan Stephens
-M:	allan.stephens@nospam.windriver.com
+M:	allan.stephens@windriver.com
 L:	tipc-discussion@lists.sourceforge.net
 W:	http://tipc.sourceforge.net/
 W:	http://tipc.cslab.ericsson.net/
@@ -2657,6 +2697,14 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
+USB ET61X[12]51 DRIVER
+P:	Luca Risolia
+M:	luca.risolia@studio.unibo.it
+L:	linux-usb-devel@lists.sourceforge.net
+L:	video4linux-list@redhat.com
+W:	http://www.linux-projects.org
+S:	Maintained
+
 USB HID/HIDBP DRIVERS
 P:	Vojtech Pavlik
 M:	vojtech@suse.cz
@@ -2820,6 +2868,7 @@
 P:	Luca Risolia
 M:	luca.risolia@studio.unibo.it
 L:	linux-usb-devel@lists.sourceforge.net
+L:	video4linux-list@redhat.com
 W:	http://www.linux-projects.org
 S:	Maintained
 
@@ -2849,6 +2898,7 @@
 P:	Luca Risolia
 M:	luca.risolia@studio.unibo.it
 L:	linux-usb-devel@lists.sourceforge.net
+L:	video4linux-list@redhat.com
 W:	http://www.linux-projects.org
 S:	Maintained
 
@@ -2930,7 +2980,8 @@
 
 VIDEO FOR LINUX
 P:	Mauro Carvalho Chehab
-M:	mchehab@brturbo.com.br
+M:	mchehab@infradead.org
+M:	v4l-dvb-maintainer@linuxtv.org
 L:	video4linux-list@redhat.com
 W:	http://linuxtv.org
 T:	git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
diff --git a/Makefile b/Makefile
index 252a659..74d67b2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 16
-EXTRAVERSION =-rc1
+EXTRAVERSION =-rc3
 NAME=Sliding Snow Leopard
 
 # *DOCUMENTATION*
@@ -442,7 +442,7 @@
 config %config: scripts_basic outputmakefile FORCE
 	$(Q)mkdir -p include/linux
 	$(Q)$(MAKE) $(build)=scripts/kconfig $@
-	$(Q)$(MAKE) .kernelrelease
+	$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
 
 else
 # ===========================================================================
diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c
index 8f2e5c7..6c56c75 100644
--- a/arch/alpha/kernel/asm-offsets.c
+++ b/arch/alpha/kernel/asm-offsets.c
@@ -28,6 +28,7 @@
         DEFINE(TASK_GID, offsetof(struct task_struct, gid));
         DEFINE(TASK_EGID, offsetof(struct task_struct, egid));
         DEFINE(TASK_REAL_PARENT, offsetof(struct task_struct, real_parent));
+        DEFINE(TASK_GROUP_LEADER, offsetof(struct task_struct, group_leader));
         DEFINE(TASK_TGID, offsetof(struct task_struct, tgid));
         BLANK();
 
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index e38671c..7af15bf 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -879,17 +879,19 @@
 
 	/* See linux/kernel/timer.c sys_getppid for discussion
 	   about this loop.  */
-	ldq	$3, TASK_REAL_PARENT($2)
-1:	ldl	$1, TASK_TGID($3)
+	ldq	$3, TASK_GROUP_LEADER($2)
+	ldq	$4, TASK_REAL_PARENT($3)
+	ldl	$0, TASK_TGID($2)
+1:	ldl	$1, TASK_TGID($4)
 #ifdef CONFIG_SMP
-	mov	$3, $4
+	mov	$4, $5
 	mb
-	ldq	$3, TASK_REAL_PARENT($2)
-	cmpeq	$3, $4, $4
-	beq	$4, 1b
+	ldq	$3, TASK_GROUP_LEADER($2)
+	ldq	$4, TASK_REAL_PARENT($3)
+	cmpeq	$4, $5, $5
+	beq	$5, 1b
 #endif
 	stq	$1, 80($sp)
-	ldl	$0, TASK_TGID($2)
 	ret
 .end sys_getxpid
 
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index 76be5cf..9006063 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -68,34 +68,32 @@
 #ifdef CONFIG_SMP
 	int j;
 #endif
-	int i = *(loff_t *) v;
+	int irq = *(loff_t *) v;
 	struct irqaction * action;
 	unsigned long flags;
 
 #ifdef CONFIG_SMP
-	if (i == 0) {
+	if (irq == 0) {
 		seq_puts(p, "           ");
-		for (i = 0; i < NR_CPUS; i++)
-			if (cpu_online(i))
-				seq_printf(p, "CPU%d       ", i);
+		for_each_online_cpu(j)
+			seq_printf(p, "CPU%d       ", j);
 		seq_putc(p, '\n');
 	}
 #endif
 
-	if (i < ACTUAL_NR_IRQS) {
-		spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+	if (irq < ACTUAL_NR_IRQS) {
+		spin_lock_irqsave(&irq_desc[irq].lock, flags);
+		action = irq_desc[irq].action;
 		if (!action) 
 			goto unlock;
-		seq_printf(p, "%3d: ",i);
+		seq_printf(p, "%3d: ", irq);
 #ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(irq));
 #else
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[irq]);
 #endif
-		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, " %14s", irq_desc[irq].handler->typename);
 		seq_printf(p, "  %c%s",
 			(action->flags & SA_INTERRUPT)?'+':' ',
 			action->name);
@@ -108,13 +106,12 @@
 
 		seq_putc(p, '\n');
 unlock:
-		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == ACTUAL_NR_IRQS) {
+		spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+	} else if (irq == ACTUAL_NR_IRQS) {
 #ifdef CONFIG_SMP
 		seq_puts(p, "IPI: ");
-		for (i = 0; i < NR_CPUS; i++)
-			if (cpu_online(i))
-				seq_printf(p, "%10lu ", cpu_data[i].ipi_count);
+		for_each_online_cpu(j)
+			seq_printf(p, "%10lu ", cpu_data[j].ipi_count);
 		seq_putc(p, '\n');
 #endif
 		seq_printf(p, "ERR: %10lu\n", irq_err_count);
@@ -122,7 +119,6 @@
 	return 0;
 }
 
-
 /*
  * handle_irq handles all normal device IRQ's (the special
  * SMP cross-CPU interrupts have their own specific
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 01fe990..7fb14f4 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -960,7 +960,7 @@
 			return -EFAULT;
 	}
 
-	return do_utimes(filename, tvs ? ktvs : NULL);
+	return do_utimes(AT_FDCWD, filename, tvs ? ktvs : NULL);
 }
 
 #define MAX_SELECT_SECONDS \
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 4b87352..02c2db0 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -73,9 +73,6 @@
 
 EXPORT_SYMBOL(cpu_online_map);
 
-/* cpus reported in the hwrpb */
-static unsigned long hwrpb_cpu_present_mask __initdata = 0;
-
 int smp_num_probed;		/* Internal processor count */
 int smp_num_cpus = 1;		/* Number that came online.  */
 
@@ -442,7 +439,7 @@
 			if ((cpu->flags & 0x1cc) == 0x1cc) {
 				smp_num_probed++;
 				/* Assume here that "whami" == index */
-				hwrpb_cpu_present_mask |= (1UL << i);
+				cpu_set(i, cpu_possible_map);
 				cpu->pal_revision = boot_cpu_palrev;
 			}
 
@@ -453,12 +450,12 @@
 		}
 	} else {
 		smp_num_probed = 1;
-		hwrpb_cpu_present_mask = (1UL << boot_cpuid);
+		cpu_set(boot_cpuid, cpu_possible_map);
 	}
 	cpu_present_mask = cpumask_of_cpu(boot_cpuid);
 
 	printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
-	       smp_num_probed, hwrpb_cpu_present_mask);
+	       smp_num_probed, cpu_possible_map.bits[0]);
 }
 
 /*
@@ -467,8 +464,6 @@
 void __init
 smp_prepare_cpus(unsigned int max_cpus)
 {
-	int cpu_count, i;
-
 	/* Take care of some initial bookkeeping.  */
 	memset(ipi_data, 0, sizeof(ipi_data));
 
@@ -486,19 +481,7 @@
 
 	printk(KERN_INFO "SMP starting up secondaries.\n");
 
-	cpu_count = 1;
-	for (i = 0; (i < NR_CPUS) && (cpu_count < max_cpus); i++) {
-		if (i == boot_cpuid)
-			continue;
-
-		if (((hwrpb_cpu_present_mask >> i) & 1) == 0)
-			continue;
-
-		cpu_set(i, cpu_possible_map);
-		cpu_count++;
-	}
-
-	smp_num_cpus = cpu_count;
+	smp_num_cpus = smp_num_probed;
 }
 
 void __devinit
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5959e36..15dc1a0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -10,9 +10,9 @@
 	default y
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
-	  licensed by ARM ltd and targeted at embedded applications and
+	  licensed by ARM Ltd and targeted at embedded applications and
 	  handhelds such as the Compaq IPAQ.  ARM-based PCs are no longer
-	  manufactured, but  legacy ARM-based PC hardware remains popular in
+	  manufactured, but legacy ARM-based PC hardware remains popular in
 	  Europe.  There is an ARM Linux project with a web page at
 	  <http://www.arm.linux.org.uk/>.
 
@@ -69,6 +69,9 @@
 config FIQ
 	bool
 
+config ARCH_MTD_XIP
+	bool
+
 source "init/Kconfig"
 
 menu "System Type"
@@ -81,45 +84,62 @@
 	bool "Cirrus-CL-PS7500FE"
 	select TIMER_ACORN
 	select ISA
+	help
+	  Support for the Cirrus Logic PS7500FE system-on-a-chip.
 
 config ARCH_CLPS711X
 	bool "CLPS711x/EP721x-based"
+	help
+	  Support for Cirrus Logic 711x/721x based boards.
 
 config ARCH_CO285
 	bool "Co-EBSA285"
 	select FOOTBRIDGE
 	select FOOTBRIDGE_ADDIN
+	help
+	  Support for Intel's EBSA285 companion chip.
 
 config ARCH_EBSA110
 	bool "EBSA-110"
 	select ISA
 	help
 	  This is an evaluation board for the StrongARM processor available
-	  from Digital. It has limited hardware on-board, including an onboard
+	  from Digital. It has limited hardware on-board, including an
 	  Ethernet interface, two PCMCIA sockets, two serial ports and a
 	  parallel port.
 
 config ARCH_FOOTBRIDGE
 	bool "FootBridge"
 	select FOOTBRIDGE
+	help
+	  Support for systems based on the DC21285 companion chip
+	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
 
 config ARCH_INTEGRATOR
 	bool "Integrator"
 	select ARM_AMBA
 	select ICST525
+	help
+	  Support for ARM's Integrator platform.
 
 config ARCH_IOP3XX
 	bool "IOP3xx-based"
 	select PCI
+	help
+	  Support for Intel's IOP3XX (XScale) family of processors.
 
 config ARCH_IXP4XX
 	bool "IXP4xx-based"
 	select DMABOUNCE
 	select PCI
+	help
+	  Support for Intel's IXP4XX (XScale) family of processors.
 
 config ARCH_IXP2000
 	bool "IXP2400/2800-based"
 	select PCI
+	help
+	  Support for Intel's IXP2400/2800 (XScale) family of processors.
 
 config ARCH_L7200
 	bool "LinkUp-L7200"
@@ -136,6 +156,9 @@
 
 config ARCH_PXA
 	bool "PXA2xx-based"
+	select ARCH_MTD_XIP
+	help
+	  Support for Intel's PXA2XX processor line.
 
 config ARCH_RPC
 	bool "RiscPC"
@@ -152,19 +175,25 @@
 	bool "SA1100-based"
 	select ISA
 	select ARCH_DISCONTIGMEM_ENABLE
+	select ARCH_MTD_XIP
+	help
+	  Support for StrongARM 11x0 based boards.
 
 config ARCH_S3C2410
 	bool "Samsung S3C2410"
 	help
 	  Samsung S3C2410X CPU based systems, such as the Simtec Electronics
 	  BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
-	  the Samsung SMDK2410 development board (and derviatives).
+	  the Samsung SMDK2410 development board (and derivatives).
 
 config ARCH_SHARK
 	bool "Shark"
 	select ISA
 	select ISA_DMA
 	select PCI
+	help
+	  Support for the StrongARM based Digital DNARD machine, also known
+	  as "Shark" (<http://www.shark-linux.de/shark.html>).
 
 config ARCH_LH7A40X
 	bool "Sharp LH7A40X"
@@ -176,6 +205,8 @@
 
 config ARCH_OMAP
 	bool "TI OMAP"
+	help
+	  Support for TI's OMAP platform (OMAP1 and OMAP2).
 
 config ARCH_VERSATILE
 	bool "Versatile"
@@ -194,6 +225,8 @@
 
 config ARCH_IMX
 	bool "IMX"
+	help
+	  Support for Motorola's i.MX family of processors (MX1, MXL).
 
 config ARCH_H720X
 	bool "Hynix-HMS720x-based"
@@ -210,8 +243,8 @@
 config ARCH_AT91RM9200
 	bool "AT91RM9200"
 	help
-	  Say Y here if you intend to run this kernel on an AT91RM9200-based
-	  board.
+	  Say Y here if you intend to run this kernel on an Atmel
+	  AT91RM9200-based board.
 
 endchoice
 
@@ -417,8 +450,8 @@
 	  To use this you need GCC version 4.0.0 or later.
 
 config OABI_COMPAT
-	bool "Allow old ABI binaries to run with this kernel"
-	depends on AEABI
+	bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)"
+	depends on AEABI && EXPERIMENTAL
 	default y
 	help
 	  This option preserves the old syscall interface along with the
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index aaa4740..db3389d 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -334,7 +334,7 @@
 		mov	r1, #0x12
 		orr	r1, r1, #3 << 10
 		add	r2, r3, #16384
-1:		cmp	r1, r8			@ if virt > start of RAM
+1:		cmp	r1, r9			@ if virt > start of RAM
 		orrhs	r1, r1, #0x0c		@ set cacheable, bufferable
 		cmp	r1, r10			@ if virt > end of RAM
 		bichs	r1, r1, #0x0c		@ clear cacheable, bufferable
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
index 5cdd13a..1fe73d1 100644
--- a/arch/arm/configs/at91rm9200dk_defconfig
+++ b/arch/arm/configs/at91rm9200dk_defconfig
@@ -85,7 +85,6 @@
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
index 20838cc..b7d934c 100644
--- a/arch/arm/configs/at91rm9200ek_defconfig
+++ b/arch/arm/configs/at91rm9200ek_defconfig
@@ -85,7 +85,6 @@
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/bast_defconfig b/arch/arm/configs/bast_defconfig
index 6886001..4a8564f 100644
--- a/arch/arm/configs/bast_defconfig
+++ b/arch/arm/configs/bast_defconfig
@@ -14,8 +14,7 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
+CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
@@ -360,7 +359,6 @@
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
@@ -781,7 +779,6 @@
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 # CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig
index 15468a0..c9aa878 100644
--- a/arch/arm/configs/collie_defconfig
+++ b/arch/arm/configs/collie_defconfig
@@ -13,8 +13,7 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
+CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -308,9 +307,7 @@
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
 CONFIG_MTD_OBSOLETE_CHIPS=y
-# CONFIG_MTD_AMDSTD is not set
 CONFIG_MTD_SHARP=y
-# CONFIG_MTD_JEDEC is not set
 
 #
 # Mapping drivers for chip access
@@ -396,7 +393,6 @@
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
@@ -741,7 +737,6 @@
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
index 885a318..94bd993 100644
--- a/arch/arm/configs/csb337_defconfig
+++ b/arch/arm/configs/csb337_defconfig
@@ -85,7 +85,6 @@
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig
index 95a96a5..1519124 100644
--- a/arch/arm/configs/csb637_defconfig
+++ b/arch/arm/configs/csb637_defconfig
@@ -85,7 +85,6 @@
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
index 9592e39..5fdaf3c 100644
--- a/arch/arm/configs/enp2611_defconfig
+++ b/arch/arm/configs/enp2611_defconfig
@@ -171,7 +171,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0"
 # CONFIG_XIP_KERNEL is not set
 
 #
diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig
index fbe312e..3c73b70 100644
--- a/arch/arm/configs/ep80219_defconfig
+++ b/arch/arm/configs/ep80219_defconfig
@@ -522,6 +522,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig
index c07628c..3246716 100644
--- a/arch/arm/configs/iq31244_defconfig
+++ b/arch/arm/configs/iq31244_defconfig
@@ -493,6 +493,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig
index 18fa161..b000da7 100644
--- a/arch/arm/configs/iq80321_defconfig
+++ b/arch/arm/configs/iq80321_defconfig
@@ -415,6 +415,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig
index f50035d..46c79e1 100644
--- a/arch/arm/configs/iq80331_defconfig
+++ b/arch/arm/configs/iq80331_defconfig
@@ -496,6 +496,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/iq80332_defconfig b/arch/arm/configs/iq80332_defconfig
index 18b3f37..11959b7 100644
--- a/arch/arm/configs/iq80332_defconfig
+++ b/arch/arm/configs/iq80332_defconfig
@@ -496,6 +496,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index d9d6bb8..c67fc44 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -172,7 +172,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0"
 # CONFIG_XIP_KERNEL is not set
 
 #
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
index 2dc9d49..60d66e8 100644
--- a/arch/arm/configs/ixdp2401_defconfig
+++ b/arch/arm/configs/ixdp2401_defconfig
@@ -172,7 +172,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0"
 # CONFIG_XIP_KERNEL is not set
 
 #
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
index ea8f4b4..f54f3dc 100644
--- a/arch/arm/configs/ixdp2801_defconfig
+++ b/arch/arm/configs/ixdp2801_defconfig
@@ -172,7 +172,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware ixdp2x01_clock=50000000"
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0"
 # CONFIG_XIP_KERNEL is not set
 
 #
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 33f3108..6695b07 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,11 +1,10 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-rc1
-# Sun Nov 13 17:41:24 2005
+# Linux kernel version: 2.6.16-rc2
+# Mon Feb  6 11:17:23 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
-CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 
@@ -13,8 +12,7 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
+CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -29,27 +27,31 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
 
 #
 # Loadable module support
@@ -103,6 +105,7 @@
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_H720X is not set
 # CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
 
 #
 # S3C24XX Implementations
@@ -161,7 +164,6 @@
 # Bus support
 #
 CONFIG_ISA=y
-CONFIG_ISA_DMA_API=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -173,6 +175,7 @@
 #
 # CONFIG_PREEMPT is not set
 # CONFIG_NO_IDLE_HZ is not set
+# CONFIG_AEABI is not set
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -215,6 +218,8 @@
 # Power management options
 #
 CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
 CONFIG_APM=y
 
 #
@@ -260,6 +265,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -277,7 +287,6 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -301,6 +310,11 @@
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
@@ -413,8 +427,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -473,7 +485,6 @@
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
@@ -504,7 +515,6 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_SMC91X is not set
 CONFIG_DM9000=y
@@ -609,11 +619,11 @@
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
 # CONFIG_DIGIEPCA is not set
-# CONFIG_ESPSERIAL is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
+# CONFIG_SYNCLINK_GT is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_RISCOM8 is not set
 # CONFIG_SPECIALIX is not set
@@ -627,6 +637,7 @@
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -689,6 +700,7 @@
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 # CONFIG_TELCLOCK is not set
 
 #
@@ -733,6 +745,12 @@
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
@@ -865,6 +883,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
 CONFIG_INOTIFY=y
@@ -896,10 +915,10 @@
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -968,6 +987,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
@@ -1023,12 +1043,13 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1037,6 +1058,7 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_WAITQ is not set
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 75e6f9a..8c3035d 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -7,337 +7,334 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- *  This file is included twice in entry-common.S
+ *  This file is included thrice in entry-common.S
  */
-#ifndef NR_syscalls
-#define NR_syscalls 328
-#else
-
-100:
-/* 0 */		.long	sys_restart_syscall
-		.long	sys_exit
-		.long	sys_fork_wrapper
-		.long	sys_read
-		.long	sys_write
-/* 5 */		.long	sys_open
-		.long	sys_close
-		.long	sys_ni_syscall		/* was sys_waitpid */
-		.long	sys_creat
-		.long	sys_link
-/* 10 */	.long	sys_unlink
-		.long	sys_execve_wrapper
-		.long	sys_chdir
-		.long	OBSOLETE(sys_time)	/* used by libc4 */
-		.long	sys_mknod
-/* 15 */	.long	sys_chmod
-		.long	sys_lchown16
-		.long	sys_ni_syscall		/* was sys_break */
-		.long	sys_ni_syscall		/* was sys_stat */
-		.long	sys_lseek
-/* 20 */	.long	sys_getpid
-		.long	sys_mount
-		.long	OBSOLETE(sys_oldumount)	/* used by libc4 */
-		.long	sys_setuid16
-		.long	sys_getuid16
-/* 25 */	.long	OBSOLETE(sys_stime)
-		.long	sys_ptrace
-		.long	OBSOLETE(sys_alarm)	/* used by libc4 */
-		.long	sys_ni_syscall		/* was sys_fstat */
-		.long	sys_pause
-/* 30 */	.long	OBSOLETE(sys_utime)	/* used by libc4 */
-		.long	sys_ni_syscall		/* was sys_stty */
-		.long	sys_ni_syscall		/* was sys_getty */
-		.long	sys_access
-		.long	sys_nice
-/* 35 */	.long	sys_ni_syscall		/* was sys_ftime */
-		.long	sys_sync
-		.long	sys_kill
-		.long	sys_rename
-		.long	sys_mkdir
-/* 40 */	.long	sys_rmdir
-		.long	sys_dup
-		.long	sys_pipe
-		.long	sys_times
-		.long	sys_ni_syscall		/* was sys_prof */
-/* 45 */	.long	sys_brk
-		.long	sys_setgid16
-		.long	sys_getgid16
-		.long	sys_ni_syscall		/* was sys_signal */
-		.long	sys_geteuid16
-/* 50 */	.long	sys_getegid16
-		.long	sys_acct
-		.long	sys_umount
-		.long	sys_ni_syscall		/* was sys_lock */
-		.long	sys_ioctl
-/* 55 */	.long	sys_fcntl
-		.long	sys_ni_syscall		/* was sys_mpx */
-		.long	sys_setpgid
-		.long	sys_ni_syscall		/* was sys_ulimit */
-		.long	sys_ni_syscall		/* was sys_olduname */
-/* 60 */	.long	sys_umask
-		.long	sys_chroot
-		.long	sys_ustat
-		.long	sys_dup2
-		.long	sys_getppid
-/* 65 */	.long	sys_getpgrp
-		.long	sys_setsid
-		.long	sys_sigaction
-		.long	sys_ni_syscall		/* was sys_sgetmask */
-		.long	sys_ni_syscall		/* was sys_ssetmask */
-/* 70 */	.long	sys_setreuid16
-		.long	sys_setregid16
-		.long	sys_sigsuspend_wrapper
-		.long	sys_sigpending
-		.long	sys_sethostname
-/* 75 */	.long	sys_setrlimit
-		.long	OBSOLETE(sys_old_getrlimit) /* used by libc4 */
-		.long	sys_getrusage
-		.long	sys_gettimeofday
-		.long	sys_settimeofday
-/* 80 */	.long	sys_getgroups16
-		.long	sys_setgroups16
-		.long	OBSOLETE(old_select)	/* used by libc4 */
-		.long	sys_symlink
-		.long	sys_ni_syscall		/* was sys_lstat */
-/* 85 */	.long	sys_readlink
-		.long	sys_uselib
-		.long	sys_swapon
-		.long	sys_reboot
-		.long	OBSOLETE(old_readdir)	/* used by libc4 */
-/* 90 */	.long	OBSOLETE(old_mmap)	/* used by libc4 */
-		.long	sys_munmap
-		.long	sys_truncate
-		.long	sys_ftruncate
-		.long	sys_fchmod
-/* 95 */	.long	sys_fchown16
-		.long	sys_getpriority
-		.long	sys_setpriority
-		.long	sys_ni_syscall		/* was sys_profil */
-		.long	sys_statfs
-/* 100 */	.long	sys_fstatfs
-		.long	sys_ni_syscall
-		.long	OBSOLETE(sys_socketcall)
-		.long	sys_syslog
-		.long	sys_setitimer
-/* 105 */	.long	sys_getitimer
-		.long	sys_newstat
-		.long	sys_newlstat
-		.long	sys_newfstat
-		.long	sys_ni_syscall		/* was sys_uname */
-/* 110 */	.long	sys_ni_syscall		/* was sys_iopl */
-		.long	sys_vhangup
-		.long	sys_ni_syscall
-		.long	OBSOLETE(sys_syscall)	/* call a syscall */
-		.long	sys_wait4
-/* 115 */	.long	sys_swapoff
-		.long	sys_sysinfo
-		.long	OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))
-		.long	sys_fsync
-		.long	sys_sigreturn_wrapper
-/* 120 */	.long	sys_clone_wrapper
-		.long	sys_setdomainname
-		.long	sys_newuname
-		.long	sys_ni_syscall
-		.long	sys_adjtimex
-/* 125 */	.long	sys_mprotect
-		.long	sys_sigprocmask
-		.long	sys_ni_syscall		/* was sys_create_module */
-		.long	sys_init_module
-		.long	sys_delete_module
-/* 130 */	.long	sys_ni_syscall		/* was sys_get_kernel_syms */
-		.long	sys_quotactl
-		.long	sys_getpgid
-		.long	sys_fchdir
-		.long	sys_bdflush
-/* 135 */	.long	sys_sysfs
-		.long	sys_personality
-		.long	sys_ni_syscall		/* .long	_sys_afs_syscall */
-		.long	sys_setfsuid16
-		.long	sys_setfsgid16
-/* 140 */	.long	sys_llseek
-		.long	sys_getdents
-		.long	sys_select
-		.long	sys_flock
-		.long	sys_msync
-/* 145 */	.long	sys_readv
-		.long	sys_writev
-		.long	sys_getsid
-		.long	sys_fdatasync
-		.long	sys_sysctl
-/* 150 */	.long	sys_mlock
-		.long	sys_munlock
-		.long	sys_mlockall
-		.long	sys_munlockall
-		.long	sys_sched_setparam
-/* 155 */	.long	sys_sched_getparam
-		.long	sys_sched_setscheduler
-		.long	sys_sched_getscheduler
-		.long	sys_sched_yield
-		.long	sys_sched_get_priority_max
-/* 160 */	.long	sys_sched_get_priority_min
-		.long	sys_sched_rr_get_interval
-		.long	sys_nanosleep
-		.long	sys_arm_mremap
-		.long	sys_setresuid16
-/* 165 */	.long	sys_getresuid16
-		.long	sys_ni_syscall
-		.long	sys_ni_syscall		/* was sys_query_module */
-		.long	sys_poll
-		.long	sys_nfsservctl
-/* 170 */	.long	sys_setresgid16
-		.long	sys_getresgid16
-		.long	sys_prctl
-		.long	sys_rt_sigreturn_wrapper
-		.long	sys_rt_sigaction
-/* 175 */	.long	sys_rt_sigprocmask
-		.long	sys_rt_sigpending
-		.long	sys_rt_sigtimedwait
-		.long	sys_rt_sigqueueinfo
-		.long	sys_rt_sigsuspend_wrapper
-/* 180 */	.long	ABI(sys_pread64, sys_oabi_pread64)
-		.long	ABI(sys_pwrite64, sys_oabi_pwrite64)
-		.long	sys_chown16
-		.long	sys_getcwd
-		.long	sys_capget
-/* 185 */	.long	sys_capset
-		.long	sys_sigaltstack_wrapper
-		.long	sys_sendfile
-		.long	sys_ni_syscall
-		.long	sys_ni_syscall
-/* 190 */	.long	sys_vfork_wrapper
-		.long	sys_getrlimit
-		.long	sys_mmap2
-		.long	ABI(sys_truncate64, sys_oabi_truncate64)
-		.long	ABI(sys_ftruncate64, sys_oabi_ftruncate64)
-/* 195 */	.long	ABI(sys_stat64, sys_oabi_stat64)
-		.long	ABI(sys_lstat64, sys_oabi_lstat64)
-		.long	ABI(sys_fstat64, sys_oabi_fstat64)
-		.long	sys_lchown
-		.long	sys_getuid
-/* 200 */	.long	sys_getgid
-		.long	sys_geteuid
-		.long	sys_getegid
-		.long	sys_setreuid
-		.long	sys_setregid
-/* 205 */	.long	sys_getgroups
-		.long	sys_setgroups
-		.long	sys_fchown
-		.long	sys_setresuid
-		.long	sys_getresuid
-/* 210 */	.long	sys_setresgid
-		.long	sys_getresgid
-		.long	sys_chown
-		.long	sys_setuid
-		.long	sys_setgid
-/* 215 */	.long	sys_setfsuid
-		.long	sys_setfsgid
-		.long	sys_getdents64
-		.long	sys_pivot_root
-		.long	sys_mincore
-/* 220 */	.long	sys_madvise
-		.long	ABI(sys_fcntl64, sys_oabi_fcntl64)
-		.long	sys_ni_syscall /* TUX */
-		.long	sys_ni_syscall
-		.long	sys_gettid
-/* 225 */	.long	ABI(sys_readahead, sys_oabi_readahead)
-		.long	sys_setxattr
-		.long	sys_lsetxattr
-		.long	sys_fsetxattr
-		.long	sys_getxattr
-/* 230 */	.long	sys_lgetxattr
-		.long	sys_fgetxattr
-		.long	sys_listxattr
-		.long	sys_llistxattr
-		.long	sys_flistxattr
-/* 235 */	.long	sys_removexattr
-		.long	sys_lremovexattr
-		.long	sys_fremovexattr
-		.long	sys_tkill
-		.long	sys_sendfile64
-/* 240 */	.long	sys_futex
-		.long	sys_sched_setaffinity
-		.long	sys_sched_getaffinity
-		.long	sys_io_setup
-		.long	sys_io_destroy
-/* 245 */	.long	sys_io_getevents
-		.long	sys_io_submit
-		.long	sys_io_cancel
-		.long	sys_exit_group
-		.long	sys_lookup_dcookie
-/* 250 */	.long	sys_epoll_create
-		.long	ABI(sys_epoll_ctl, sys_oabi_epoll_ctl)
-		.long	ABI(sys_epoll_wait, sys_oabi_epoll_wait)
-	 	.long	sys_remap_file_pages
-		.long	sys_ni_syscall	/* sys_set_thread_area */
-/* 255 */	.long	sys_ni_syscall	/* sys_get_thread_area */
- 		.long	sys_set_tid_address
-		.long	sys_timer_create
-		.long	sys_timer_settime
-		.long	sys_timer_gettime
-/* 260 */	.long	sys_timer_getoverrun
-		.long	sys_timer_delete
-		.long	sys_clock_settime
-		.long	sys_clock_gettime
-		.long	sys_clock_getres
-/* 265 */	.long	sys_clock_nanosleep
-		.long	sys_statfs64_wrapper
-		.long	sys_fstatfs64_wrapper
-		.long	sys_tgkill
-		.long	sys_utimes
-/* 270 */	.long	sys_arm_fadvise64_64
-		.long	sys_pciconfig_iobase
-		.long	sys_pciconfig_read
-		.long	sys_pciconfig_write
-		.long	sys_mq_open
-/* 275 */	.long	sys_mq_unlink
-		.long	sys_mq_timedsend
-		.long	sys_mq_timedreceive
-		.long	sys_mq_notify
-		.long	sys_mq_getsetattr
-/* 280 */	.long	sys_waitid
-		.long	sys_socket
-		.long	sys_bind
-		.long	sys_connect
-		.long	sys_listen
-/* 285 */	.long	sys_accept
-		.long	sys_getsockname
-		.long	sys_getpeername
-		.long	sys_socketpair
-		.long	sys_send
-/* 290 */	.long	sys_sendto
-		.long	sys_recv
-		.long	sys_recvfrom
-		.long	sys_shutdown
-		.long	sys_setsockopt
-/* 295 */	.long	sys_getsockopt
-		.long	sys_sendmsg
-		.long	sys_recvmsg
-		.long	ABI(sys_semop, sys_oabi_semop)
-		.long	sys_semget
-/* 300 */	.long	sys_semctl
-		.long	sys_msgsnd
-		.long	sys_msgrcv
-		.long	sys_msgget
-		.long	sys_msgctl
-/* 305 */	.long	sys_shmat
-		.long	sys_shmdt
-		.long	sys_shmget
-		.long	sys_shmctl
-		.long	sys_add_key
-/* 310 */	.long	sys_request_key
-		.long	sys_keyctl
-		.long	ABI(sys_semtimedop, sys_oabi_semtimedop)
-/* vserver */	.long	sys_ni_syscall
-		.long	sys_ioprio_set
-/* 315 */	.long	sys_ioprio_get
-		.long	sys_inotify_init
-		.long	sys_inotify_add_watch
-		.long	sys_inotify_rm_watch
-		.long	sys_mbind
-/* 320 */	.long	sys_get_mempolicy
-		.long	sys_set_mempolicy
-
-		.rept	NR_syscalls - (. - 100b) / 4
-			.long	sys_ni_syscall
-		.endr
+/* 0 */		CALL(sys_restart_syscall)
+		CALL(sys_exit)
+		CALL(sys_fork_wrapper)
+		CALL(sys_read)
+		CALL(sys_write)
+/* 5 */		CALL(sys_open)
+		CALL(sys_close)
+		CALL(sys_ni_syscall)		/* was sys_waitpid */
+		CALL(sys_creat)
+		CALL(sys_link)
+/* 10 */	CALL(sys_unlink)
+		CALL(sys_execve_wrapper)
+		CALL(sys_chdir)
+		CALL(OBSOLETE(sys_time))	/* used by libc4 */
+		CALL(sys_mknod)
+/* 15 */	CALL(sys_chmod)
+		CALL(sys_lchown16)
+		CALL(sys_ni_syscall)		/* was sys_break */
+		CALL(sys_ni_syscall)		/* was sys_stat */
+		CALL(sys_lseek)
+/* 20 */	CALL(sys_getpid)
+		CALL(sys_mount)
+		CALL(OBSOLETE(sys_oldumount))	/* used by libc4 */
+		CALL(sys_setuid16)
+		CALL(sys_getuid16)
+/* 25 */	CALL(OBSOLETE(sys_stime))
+		CALL(sys_ptrace)
+		CALL(OBSOLETE(sys_alarm))	/* used by libc4 */
+		CALL(sys_ni_syscall)		/* was sys_fstat */
+		CALL(sys_pause)
+/* 30 */	CALL(OBSOLETE(sys_utime))	/* used by libc4 */
+		CALL(sys_ni_syscall)		/* was sys_stty */
+		CALL(sys_ni_syscall)		/* was sys_getty */
+		CALL(sys_access)
+		CALL(sys_nice)
+/* 35 */	CALL(sys_ni_syscall)		/* was sys_ftime */
+		CALL(sys_sync)
+		CALL(sys_kill)
+		CALL(sys_rename)
+		CALL(sys_mkdir)
+/* 40 */	CALL(sys_rmdir)
+		CALL(sys_dup)
+		CALL(sys_pipe)
+		CALL(sys_times)
+		CALL(sys_ni_syscall)		/* was sys_prof */
+/* 45 */	CALL(sys_brk)
+		CALL(sys_setgid16)
+		CALL(sys_getgid16)
+		CALL(sys_ni_syscall)		/* was sys_signal */
+		CALL(sys_geteuid16)
+/* 50 */	CALL(sys_getegid16)
+		CALL(sys_acct)
+		CALL(sys_umount)
+		CALL(sys_ni_syscall)		/* was sys_lock */
+		CALL(sys_ioctl)
+/* 55 */	CALL(sys_fcntl)
+		CALL(sys_ni_syscall)		/* was sys_mpx */
+		CALL(sys_setpgid)
+		CALL(sys_ni_syscall)		/* was sys_ulimit */
+		CALL(sys_ni_syscall)		/* was sys_olduname */
+/* 60 */	CALL(sys_umask)
+		CALL(sys_chroot)
+		CALL(sys_ustat)
+		CALL(sys_dup2)
+		CALL(sys_getppid)
+/* 65 */	CALL(sys_getpgrp)
+		CALL(sys_setsid)
+		CALL(sys_sigaction)
+		CALL(sys_ni_syscall)		/* was sys_sgetmask */
+		CALL(sys_ni_syscall)		/* was sys_ssetmask */
+/* 70 */	CALL(sys_setreuid16)
+		CALL(sys_setregid16)
+		CALL(sys_sigsuspend_wrapper)
+		CALL(sys_sigpending)
+		CALL(sys_sethostname)
+/* 75 */	CALL(sys_setrlimit)
+		CALL(OBSOLETE(sys_old_getrlimit)) /* used by libc4 */
+		CALL(sys_getrusage)
+		CALL(sys_gettimeofday)
+		CALL(sys_settimeofday)
+/* 80 */	CALL(sys_getgroups16)
+		CALL(sys_setgroups16)
+		CALL(OBSOLETE(old_select))	/* used by libc4 */
+		CALL(sys_symlink)
+		CALL(sys_ni_syscall)		/* was sys_lstat */
+/* 85 */	CALL(sys_readlink)
+		CALL(sys_uselib)
+		CALL(sys_swapon)
+		CALL(sys_reboot)
+		CALL(OBSOLETE(old_readdir))	/* used by libc4 */
+/* 90 */	CALL(OBSOLETE(old_mmap))	/* used by libc4 */
+		CALL(sys_munmap)
+		CALL(sys_truncate)
+		CALL(sys_ftruncate)
+		CALL(sys_fchmod)
+/* 95 */	CALL(sys_fchown16)
+		CALL(sys_getpriority)
+		CALL(sys_setpriority)
+		CALL(sys_ni_syscall)		/* was sys_profil */
+		CALL(sys_statfs)
+/* 100 */	CALL(sys_fstatfs)
+		CALL(sys_ni_syscall)
+		CALL(OBSOLETE(sys_socketcall))
+		CALL(sys_syslog)
+		CALL(sys_setitimer)
+/* 105 */	CALL(sys_getitimer)
+		CALL(sys_newstat)
+		CALL(sys_newlstat)
+		CALL(sys_newfstat)
+		CALL(sys_ni_syscall)		/* was sys_uname */
+/* 110 */	CALL(sys_ni_syscall)		/* was sys_iopl */
+		CALL(sys_vhangup)
+		CALL(sys_ni_syscall)
+		CALL(OBSOLETE(sys_syscall))	/* call a syscall */
+		CALL(sys_wait4)
+/* 115 */	CALL(sys_swapoff)
+		CALL(sys_sysinfo)
+		CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
+		CALL(sys_fsync)
+		CALL(sys_sigreturn_wrapper)
+/* 120 */	CALL(sys_clone_wrapper)
+		CALL(sys_setdomainname)
+		CALL(sys_newuname)
+		CALL(sys_ni_syscall)
+		CALL(sys_adjtimex)
+/* 125 */	CALL(sys_mprotect)
+		CALL(sys_sigprocmask)
+		CALL(sys_ni_syscall)		/* was sys_create_module */
+		CALL(sys_init_module)
+		CALL(sys_delete_module)
+/* 130 */	CALL(sys_ni_syscall)		/* was sys_get_kernel_syms */
+		CALL(sys_quotactl)
+		CALL(sys_getpgid)
+		CALL(sys_fchdir)
+		CALL(sys_bdflush)
+/* 135 */	CALL(sys_sysfs)
+		CALL(sys_personality)
+		CALL(sys_ni_syscall)		/* CALL(_sys_afs_syscall) */
+		CALL(sys_setfsuid16)
+		CALL(sys_setfsgid16)
+/* 140 */	CALL(sys_llseek)
+		CALL(sys_getdents)
+		CALL(sys_select)
+		CALL(sys_flock)
+		CALL(sys_msync)
+/* 145 */	CALL(sys_readv)
+		CALL(sys_writev)
+		CALL(sys_getsid)
+		CALL(sys_fdatasync)
+		CALL(sys_sysctl)
+/* 150 */	CALL(sys_mlock)
+		CALL(sys_munlock)
+		CALL(sys_mlockall)
+		CALL(sys_munlockall)
+		CALL(sys_sched_setparam)
+/* 155 */	CALL(sys_sched_getparam)
+		CALL(sys_sched_setscheduler)
+		CALL(sys_sched_getscheduler)
+		CALL(sys_sched_yield)
+		CALL(sys_sched_get_priority_max)
+/* 160 */	CALL(sys_sched_get_priority_min)
+		CALL(sys_sched_rr_get_interval)
+		CALL(sys_nanosleep)
+		CALL(sys_arm_mremap)
+		CALL(sys_setresuid16)
+/* 165 */	CALL(sys_getresuid16)
+		CALL(sys_ni_syscall)
+		CALL(sys_ni_syscall)		/* was sys_query_module */
+		CALL(sys_poll)
+		CALL(sys_nfsservctl)
+/* 170 */	CALL(sys_setresgid16)
+		CALL(sys_getresgid16)
+		CALL(sys_prctl)
+		CALL(sys_rt_sigreturn_wrapper)
+		CALL(sys_rt_sigaction)
+/* 175 */	CALL(sys_rt_sigprocmask)
+		CALL(sys_rt_sigpending)
+		CALL(sys_rt_sigtimedwait)
+		CALL(sys_rt_sigqueueinfo)
+		CALL(sys_rt_sigsuspend_wrapper)
+/* 180 */	CALL(ABI(sys_pread64, sys_oabi_pread64))
+		CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
+		CALL(sys_chown16)
+		CALL(sys_getcwd)
+		CALL(sys_capget)
+/* 185 */	CALL(sys_capset)
+		CALL(sys_sigaltstack_wrapper)
+		CALL(sys_sendfile)
+		CALL(sys_ni_syscall)
+		CALL(sys_ni_syscall)
+/* 190 */	CALL(sys_vfork_wrapper)
+		CALL(sys_getrlimit)
+		CALL(sys_mmap2)
+		CALL(ABI(sys_truncate64, sys_oabi_truncate64))
+		CALL(ABI(sys_ftruncate64, sys_oabi_ftruncate64))
+/* 195 */	CALL(ABI(sys_stat64, sys_oabi_stat64))
+		CALL(ABI(sys_lstat64, sys_oabi_lstat64))
+		CALL(ABI(sys_fstat64, sys_oabi_fstat64))
+		CALL(sys_lchown)
+		CALL(sys_getuid)
+/* 200 */	CALL(sys_getgid)
+		CALL(sys_geteuid)
+		CALL(sys_getegid)
+		CALL(sys_setreuid)
+		CALL(sys_setregid)
+/* 205 */	CALL(sys_getgroups)
+		CALL(sys_setgroups)
+		CALL(sys_fchown)
+		CALL(sys_setresuid)
+		CALL(sys_getresuid)
+/* 210 */	CALL(sys_setresgid)
+		CALL(sys_getresgid)
+		CALL(sys_chown)
+		CALL(sys_setuid)
+		CALL(sys_setgid)
+/* 215 */	CALL(sys_setfsuid)
+		CALL(sys_setfsgid)
+		CALL(sys_getdents64)
+		CALL(sys_pivot_root)
+		CALL(sys_mincore)
+/* 220 */	CALL(sys_madvise)
+		CALL(ABI(sys_fcntl64, sys_oabi_fcntl64))
+		CALL(sys_ni_syscall) /* TUX */
+		CALL(sys_ni_syscall)
+		CALL(sys_gettid)
+/* 225 */	CALL(ABI(sys_readahead, sys_oabi_readahead))
+		CALL(sys_setxattr)
+		CALL(sys_lsetxattr)
+		CALL(sys_fsetxattr)
+		CALL(sys_getxattr)
+/* 230 */	CALL(sys_lgetxattr)
+		CALL(sys_fgetxattr)
+		CALL(sys_listxattr)
+		CALL(sys_llistxattr)
+		CALL(sys_flistxattr)
+/* 235 */	CALL(sys_removexattr)
+		CALL(sys_lremovexattr)
+		CALL(sys_fremovexattr)
+		CALL(sys_tkill)
+		CALL(sys_sendfile64)
+/* 240 */	CALL(sys_futex)
+		CALL(sys_sched_setaffinity)
+		CALL(sys_sched_getaffinity)
+		CALL(sys_io_setup)
+		CALL(sys_io_destroy)
+/* 245 */	CALL(sys_io_getevents)
+		CALL(sys_io_submit)
+		CALL(sys_io_cancel)
+		CALL(sys_exit_group)
+		CALL(sys_lookup_dcookie)
+/* 250 */	CALL(sys_epoll_create)
+		CALL(ABI(sys_epoll_ctl, sys_oabi_epoll_ctl))
+		CALL(ABI(sys_epoll_wait, sys_oabi_epoll_wait))
+	 	CALL(sys_remap_file_pages)
+		CALL(sys_ni_syscall)	/* sys_set_thread_area */
+/* 255 */	CALL(sys_ni_syscall)	/* sys_get_thread_area */
+ 		CALL(sys_set_tid_address)
+		CALL(sys_timer_create)
+		CALL(sys_timer_settime)
+		CALL(sys_timer_gettime)
+/* 260 */	CALL(sys_timer_getoverrun)
+		CALL(sys_timer_delete)
+		CALL(sys_clock_settime)
+		CALL(sys_clock_gettime)
+		CALL(sys_clock_getres)
+/* 265 */	CALL(sys_clock_nanosleep)
+		CALL(sys_statfs64_wrapper)
+		CALL(sys_fstatfs64_wrapper)
+		CALL(sys_tgkill)
+		CALL(sys_utimes)
+/* 270 */	CALL(sys_arm_fadvise64_64)
+		CALL(sys_pciconfig_iobase)
+		CALL(sys_pciconfig_read)
+		CALL(sys_pciconfig_write)
+		CALL(sys_mq_open)
+/* 275 */	CALL(sys_mq_unlink)
+		CALL(sys_mq_timedsend)
+		CALL(sys_mq_timedreceive)
+		CALL(sys_mq_notify)
+		CALL(sys_mq_getsetattr)
+/* 280 */	CALL(sys_waitid)
+		CALL(sys_socket)
+		CALL(ABI(sys_bind, sys_oabi_bind))
+		CALL(ABI(sys_connect, sys_oabi_connect))
+		CALL(sys_listen)
+/* 285 */	CALL(sys_accept)
+		CALL(sys_getsockname)
+		CALL(sys_getpeername)
+		CALL(sys_socketpair)
+		CALL(sys_send)
+/* 290 */	CALL(ABI(sys_sendto, sys_oabi_sendto))
+		CALL(sys_recv)
+		CALL(sys_recvfrom)
+		CALL(sys_shutdown)
+		CALL(sys_setsockopt)
+/* 295 */	CALL(sys_getsockopt)
+		CALL(ABI(sys_sendmsg, sys_oabi_sendmsg))
+		CALL(sys_recvmsg)
+		CALL(ABI(sys_semop, sys_oabi_semop))
+		CALL(sys_semget)
+/* 300 */	CALL(sys_semctl)
+		CALL(sys_msgsnd)
+		CALL(sys_msgrcv)
+		CALL(sys_msgget)
+		CALL(sys_msgctl)
+/* 305 */	CALL(sys_shmat)
+		CALL(sys_shmdt)
+		CALL(sys_shmget)
+		CALL(sys_shmctl)
+		CALL(sys_add_key)
+/* 310 */	CALL(sys_request_key)
+		CALL(sys_keyctl)
+		CALL(ABI(sys_semtimedop, sys_oabi_semtimedop))
+/* vserver */	CALL(sys_ni_syscall)
+		CALL(sys_ioprio_set)
+/* 315 */	CALL(sys_ioprio_get)
+		CALL(sys_inotify_init)
+		CALL(sys_inotify_add_watch)
+		CALL(sys_inotify_rm_watch)
+		CALL(sys_mbind)
+/* 320 */	CALL(sys_get_mempolicy)
+		CALL(sys_set_mempolicy)
+#ifndef syscalls_counted
+.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
+#define syscalls_counted
 #endif
+.rept syscalls_padding
+		CALL(sys_ni_syscall)
+.endr
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 874e6bb..964cd71 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -333,10 +333,14 @@
 					@ from the exception stack
 
 #if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
+#ifndef CONFIG_MMU
+#warning "NPTL on non MMU needs fixing"
+#else
 	@ make sure our user space atomic helper is aborted
 	cmp	r2, #TASK_SIZE
 	bichs	r3, r3, #PSR_Z_BIT
 #endif
+#endif
 
 	@
 	@ We are now ready to fill in the remaining blanks on the stack:
@@ -705,7 +709,12 @@
  * The C flag is also set if *ptr was changed to allow for assembly
  * optimization in the calling code.
  *
- * Note: this routine already includes memory barriers as needed.
+ * Notes:
+ *
+ *    - This routine already includes memory barriers as needed.
+ *
+ *    - A failure might be transient, i.e. it is possible, although unlikely,
+ *      that "failure" be returned even if *ptr == oldval.
  *
  * For example, a user space atomic_add implementation could look like this:
  *
@@ -735,8 +744,11 @@
 	 * The kernel itself must perform the operation.
 	 * A special ghost syscall is used for that (see traps.c).
 	 */
+	stmfd	sp!, {r7, lr}
+	mov	r7, #0xff00		@ 0xfff0 into r7 for EABI
+	orr	r7, r7, #0xf0
 	swi	#0x9ffff0
-	mov	pc, lr
+	ldmfd	sp!, {r7, pc}
 
 #elif __LINUX_ARM_ARCH__ < 6
 
@@ -753,12 +765,18 @@
 	 * exception happening just after the str instruction which would
 	 * clear the Z flag although the exchange was done.
 	 */
+#ifdef CONFIG_MMU
 	teq	ip, ip			@ set Z flag
 	ldr	ip, [r2]		@ load current val
 	add	r3, r2, #1		@ prepare store ptr
 	teqeq	ip, r0			@ compare with oldval if still allowed
 	streq	r1, [r3, #-1]!		@ store newval if still allowed
 	subs	r0, r2, r3		@ if r2 == r3 the str occured
+#else
+#warning "NPTL on non MMU needs fixing"
+	mov	r0, #-1
+	adds	r0, r0, #0
+#endif
 	mov	pc, lr
 
 #else
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 2b92ce8..dbcb11a 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -87,7 +87,11 @@
 	b	ret_slow_syscall
 	
 
+	.equ NR_syscalls,0
+#define CALL(x) .equ NR_syscalls,NR_syscalls+1
 #include "calls.S"
+#undef CALL
+#define CALL(x) .long x
 
 /*=============================================================================
  * SWI handler
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 765922b..a0cd0a9 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -30,15 +30,21 @@
 #define SWI_SYS_RT_SIGRETURN	(0xef000000|(__NR_rt_sigreturn))
 
 /*
+ * With EABI, the syscall number has to be loaded into r7.
+ */
+#define MOV_R7_NR_SIGRETURN	(0xe3a07000 | (__NR_sigreturn - __NR_SYSCALL_BASE))
+#define MOV_R7_NR_RT_SIGRETURN	(0xe3a07000 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
+
+/*
  * For Thumb syscalls, we pass the syscall number via r7.  We therefore
  * need two 16-bit instructions.
  */
 #define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
 #define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
 
-const unsigned long sigreturn_codes[4] = {
-	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
-	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
+const unsigned long sigreturn_codes[7] = {
+	MOV_R7_NR_SIGRETURN,    SWI_SYS_SIGRETURN,    SWI_THUMB_SIGRETURN,
+	MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
 };
 
 static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
@@ -189,7 +195,7 @@
 struct sigframe {
 	struct sigcontext sc;
 	unsigned long extramask[_NSIG_WORDS-1];
-	unsigned long retcode;
+	unsigned long retcode[2];
 	struct aux_sigframe aux __attribute__((aligned(8)));
 };
 
@@ -198,7 +204,7 @@
 	void __user *puc;
 	struct siginfo info;
 	struct ucontext uc;
-	unsigned long retcode;
+	unsigned long retcode[2];
 	struct aux_sigframe aux __attribute__((aligned(8)));
 };
 
@@ -436,12 +442,13 @@
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		retcode = (unsigned long)ka->sa.sa_restorer;
 	} else {
-		unsigned int idx = thumb;
+		unsigned int idx = thumb << 1;
 
 		if (ka->sa.sa_flags & SA_SIGINFO)
-			idx += 2;
+			idx += 3;
 
-		if (__put_user(sigreturn_codes[idx], rc))
+		if (__put_user(sigreturn_codes[idx],   rc) ||
+		    __put_user(sigreturn_codes[idx+1], rc+1))
 			return 1;
 
 		if (cpsr & MODE32_BIT) {
@@ -456,7 +463,7 @@
 			 * the return code written onto the stack.
 			 */
 			flush_icache_range((unsigned long)rc,
-					   (unsigned long)(rc + 1));
+					   (unsigned long)(rc + 2));
 
 			retcode = ((unsigned long)rc) + thumb;
 		}
@@ -488,7 +495,7 @@
 	}
 
 	if (err == 0)
-		err = setup_return(regs, ka, &frame->retcode, frame, usig);
+		err = setup_return(regs, ka, frame->retcode, frame, usig);
 
 	return err;
 }
@@ -522,7 +529,7 @@
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
 	if (err == 0)
-		err = setup_return(regs, ka, &frame->retcode, frame, usig);
+		err = setup_return(regs, ka, frame->retcode, frame, usig);
 
 	if (err == 0) {
 		/*
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
index 91d26fa..9991049 100644
--- a/arch/arm/kernel/signal.h
+++ b/arch/arm/kernel/signal.h
@@ -9,4 +9,4 @@
  */
 #define KERN_SIGRETURN_CODE	0xffff0500
 
-extern const unsigned long sigreturn_codes[4];
+extern const unsigned long sigreturn_codes[7];
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index eafa8e5..9d4b764 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -59,6 +59,16 @@
  *   struct sembuf loses its padding with EABI.  Since arrays of them are
  *   used they have to be copyed to remove the padding. Compatibility wrappers
  *   provided below.
+ *
+ * sys_bind:
+ * sys_connect:
+ * sys_sendmsg:
+ * sys_sendto:
+ *
+ *   struct sockaddr_un loses its padding with EABI.  Since the size of the
+ *   structure is used as a validation test in unix_mkname(), we need to
+ *   change the length argument to 110 whenever it is 112.  Compatibility
+ *   wrappers provided below.
  */
 
 #include <linux/syscalls.h>
@@ -67,6 +77,7 @@
 #include <linux/fcntl.h>
 #include <linux/eventpoll.h>
 #include <linux/sem.h>
+#include <linux/socket.h>
 #include <asm/ipc.h>
 #include <asm/uaccess.h>
 
@@ -337,3 +348,63 @@
 		return sys_ipc(call, first, second, third, ptr, fifth);
 	}
 }
+
+asmlinkage long sys_oabi_bind(int fd, struct sockaddr __user *addr, int addrlen)
+{
+	sa_family_t sa_family;
+	if (addrlen == 112 &&
+	    get_user(sa_family, &addr->sa_family) == 0 &&
+	    sa_family == AF_UNIX)
+			addrlen = 110;
+	return sys_bind(fd, addr, addrlen);
+}
+
+asmlinkage long sys_oabi_connect(int fd, struct sockaddr __user *addr, int addrlen)
+{
+	sa_family_t sa_family;
+	if (addrlen == 112 &&
+	    get_user(sa_family, &addr->sa_family) == 0 &&
+	    sa_family == AF_UNIX)
+			addrlen = 110;
+	return sys_connect(fd, addr, addrlen);
+}
+
+asmlinkage long sys_oabi_sendto(int fd, void __user *buff,
+				size_t len, unsigned flags,
+				struct sockaddr __user *addr,
+				int addrlen)
+{
+	sa_family_t sa_family;
+	if (addrlen == 112 &&
+	    get_user(sa_family, &addr->sa_family) == 0 &&
+	    sa_family == AF_UNIX)
+			addrlen = 110;
+	return sys_sendto(fd, buff, len, flags, addr, addrlen);
+}
+
+asmlinkage long sys_oabi_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
+{
+	struct sockaddr __user *addr;
+	int msg_namelen;
+	sa_family_t sa_family;
+	if (msg &&
+	    get_user(msg_namelen, &msg->msg_namelen) == 0 &&
+	    msg_namelen == 112 &&
+	    get_user(addr, &msg->msg_name) == 0 &&
+	    get_user(sa_family, &addr->sa_family) == 0 &&
+	    sa_family == AF_UNIX)
+	{
+		/*
+		 * HACK ALERT: there is a limit to how much backward bending
+		 * we should do for what is actually a transitional
+		 * compatibility layer.  This already has known flaws with
+		 * a few ioctls that we don't intend to fix.  Therefore
+		 * consider this blatent hack as another one... and take care
+		 * to run for cover.  In most cases it will "just work fine".
+		 * If it doesn't, well, tough.
+		 */
+		put_user(110, &msg->msg_namelen);
+	}
+	return sys_sendmsg(fd, msg, flags);
+}
+
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index 0793dcf..0e2b641 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -24,6 +24,8 @@
 
 config ARCH_CLEP7312
 	bool "CLEP7312"
+	help
+	  Boards based on the Cirrus Logic 7212/7312 chips.
 
 config ARCH_EDB7211
 	bool "EDB7211"
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index dc31e3f..8ab1b04 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -27,7 +27,6 @@
 #include <asm/mach/arch.h>
 #include <linux/interrupt.h>
 #include "generic.h"
-#include <asm/serial.h>
 
 static struct resource cs89x0_resources[] = {
 	[0] = {
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 3182017..a0724f2 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -469,7 +469,9 @@
 	if (fb->fb.var.bits_per_pixel <= 8)
 		val = CM_CTRL_LCDMUXSEL_VGA_8421BPP;
 	else if (fb->fb.var.bits_per_pixel <= 16)
-		val = CM_CTRL_LCDMUXSEL_VGA_16BPP;
+		val = CM_CTRL_LCDMUXSEL_VGA_16BPP
+			| CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1
+			| CM_CTRL_STATIC1 | CM_CTRL_STATIC2;
 	else
 		val = 0; /* no idea for this, don't trust the docs */
 
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index 9e5a13b..52fac89 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -106,6 +106,7 @@
 {
 	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
 	ixp2000_pci_preinit();
+	pcibios_setup("firmware");
 }
 
 static inline int enp2611_pci_valid_device(struct pci_bus *bus,
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
index 7c78240..0910127 100644
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -68,6 +68,7 @@
 {
 	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
 	ixp2000_pci_preinit();
+	pcibios_setup("firmware");
 }
 
 int ixdp2400_pci_setup(int nr, struct pci_sys_data *sys)
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index 10f0660..150519f 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -212,6 +212,7 @@
 {
 	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00000000);
 	ixp2000_pci_preinit();
+	pcibios_setup("firmware");
 }
 
 #define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
@@ -299,7 +300,9 @@
 
 int __init ixdp2x01_pci_init(void)
 {
-	pci_common_init(&ixdp2x01_pci);
+	if (machine_is_ixdp2401() || machine_is_ixdp2801())
+		pci_common_init(&ixdp2x01_pci);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 6b39369..4bdc9d4 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -333,6 +333,7 @@
 };
 
 unsigned long ixp4xx_exp_bus_size;
+EXPORT_SYMBOL(ixp4xx_exp_bus_size);
 
 void __init ixp4xx_sys_init(void)
 {
@@ -352,7 +353,7 @@
 		}
 	}
 
-	printk("IXP4xx: Using %uMiB expansion bus window size\n",
+	printk("IXP4xx: Using %luMiB expansion bus window size\n",
 			ixp4xx_exp_bus_size >> 20);
 }
 
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index bdc20b5..a177e78 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -30,6 +30,7 @@
 
 static void __init omap_generic_init_irq(void)
 {
+	omap1_init_common_hw();
 	omap_init_irq();
 }
 
@@ -104,7 +105,7 @@
 
 static void __init omap_generic_map_io(void)
 {
-	omap_map_common_io();
+	omap1_map_common_io();
 }
 
 MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 9533c36..89f0cc7 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -128,6 +128,7 @@
 
 static void __init h2_init_irq(void)
 {
+	omap1_init_common_hw();
 	omap_init_irq();
 	omap_gpio_init();
 	h2_init_smc91x();
@@ -194,7 +195,7 @@
 
 static void __init h2_map_io(void)
 {
-	omap_map_common_io();
+	omap1_map_common_io();
 }
 
 MACHINE_START(OMAP_H2, "TI-H2")
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index d665efc..d9f3862 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -203,6 +203,7 @@
 
 void h3_init_irq(void)
 {
+	omap1_init_common_hw();
 	omap_init_irq();
 	omap_gpio_init();
 	h3_init_smc91x();
@@ -210,7 +211,7 @@
 
 static void __init h3_map_io(void)
 {
-	omap_map_common_io();
+	omap1_map_common_io();
 }
 
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 652f37c..a04e433 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -181,6 +181,7 @@
 
 void innovator_init_irq(void)
 {
+	omap1_init_common_hw();
 	omap_init_irq();
 	omap_gpio_init();
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -285,7 +286,7 @@
 
 static void __init innovator_map_io(void)
 {
-	omap_map_common_io();
+	omap1_map_common_io();
 
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (cpu_is_omap1510()) {
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
index 58f7839..60d5f8a 100644
--- a/arch/arm/mach-omap1/board-netstar.c
+++ b/arch/arm/mach-omap1/board-netstar.c
@@ -65,6 +65,7 @@
 
 static void __init netstar_init_irq(void)
 {
+	omap1_init_common_hw();
 	omap_init_irq();
 	omap_gpio_init();
 }
@@ -108,7 +109,7 @@
 
 static void __init netstar_map_io(void)
 {
-	omap_map_common_io();
+	omap1_map_common_io();
 }
 
 #define MACHINE_PANICED		1
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index e5d126e..543fa13 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -169,6 +169,7 @@
 
 static void __init osk_init_irq(void)
 {
+	omap1_init_common_hw();
 	omap_init_irq();
 	omap_gpio_init();
 	osk_init_smc91x();
@@ -269,7 +270,7 @@
 
 static void __init osk_map_io(void)
 {
-	omap_map_common_io();
+	omap1_map_common_io();
 }
 
 MACHINE_START(OMAP_OSK, "TI-OSK")
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 67fada2..e488f72 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -34,6 +34,7 @@
 
 static void __init omap_generic_init_irq(void)
 {
+	omap1_init_common_hw();
 	omap_init_irq();
 }
 
@@ -72,7 +73,7 @@
 
 static void __init omap_generic_map_io(void)
 {
-	omap_map_common_io();
+	omap1_map_common_io();
 }
 
 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 88708a0..3913a3c 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -144,6 +144,7 @@
 
 void omap_perseus2_init_irq(void)
 {
+	omap1_init_common_hw();
 	omap_init_irq();
 	omap_gpio_init();
 	perseus2_init_smc91x();
@@ -160,7 +161,7 @@
 
 static void __init omap_perseus2_map_io(void)
 {
-	omap_map_common_io();
+	omap1_map_common_io();
 	iotable_init(omap_perseus2_io_desc,
 		     ARRAY_SIZE(omap_perseus2_io_desc));
 
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 959b4b8..bfd5fdd 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -162,6 +162,7 @@
 
 static void __init voiceblue_init_irq(void)
 {
+	omap1_init_common_hw();
 	omap_init_irq();
 	omap_gpio_init();
 }
@@ -206,7 +207,7 @@
 
 static void __init voiceblue_map_io(void)
 {
-	omap_map_common_io();
+	omap1_map_common_io();
 }
 
 #define MACHINE_PANICED		1
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 9d862f8..75110ba 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -50,10 +50,10 @@
 {
 	int retval;
 
-	retval = omap1_clk_use(&api_ck.clk);
+	retval = omap1_clk_enable(&api_ck.clk);
 	if (!retval) {
-		retval = omap1_clk_enable(clk);
-		omap1_clk_unuse(&api_ck.clk);
+		retval = omap1_clk_enable_generic(clk);
+		omap1_clk_disable(&api_ck.clk);
 	}
 
 	return retval;
@@ -61,9 +61,9 @@
 
 static void omap1_clk_disable_dsp_domain(struct clk *clk)
 {
-	if (omap1_clk_use(&api_ck.clk) == 0) {
-		omap1_clk_disable(clk);
-		omap1_clk_unuse(&api_ck.clk);
+	if (omap1_clk_enable(&api_ck.clk) == 0) {
+		omap1_clk_disable_generic(clk);
+		omap1_clk_disable(&api_ck.clk);
 	}
 }
 
@@ -72,7 +72,7 @@
 	int ret;
 	struct uart_clk *uclk;
 
-	ret = omap1_clk_enable(clk);
+	ret = omap1_clk_enable_generic(clk);
 	if (ret == 0) {
 		/* Set smart idle acknowledgement mode */
 		uclk = (struct uart_clk *)clk;
@@ -91,7 +91,7 @@
 	uclk = (struct uart_clk *)clk;
 	omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr);
 
-	omap1_clk_disable(clk);
+	omap1_clk_disable_generic(clk);
 }
 
 static void omap1_clk_allow_idle(struct clk *clk)
@@ -230,9 +230,9 @@
 	 * Note that DSP_CKCTL virt addr = phys addr, so
 	 * we must use __raw_readw() instead of omap_readw().
 	 */
-	omap1_clk_use(&api_ck.clk);
+	omap1_clk_enable(&api_ck.clk);
 	dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
-	omap1_clk_unuse(&api_ck.clk);
+	omap1_clk_disable(&api_ck.clk);
 
 	if (unlikely(clk->rate == clk->parent->rate / dsor))
 		return; /* No change, quick exit */
@@ -412,12 +412,12 @@
 	clk-> rate = 96000000 / dsor;
 }
 
-static int omap1_clk_use(struct clk *clk)
+static int omap1_clk_enable(struct clk *clk)
 {
 	int ret = 0;
 	if (clk->usecount++ == 0) {
 		if (likely(clk->parent)) {
-			ret = omap1_clk_use(clk->parent);
+			ret = omap1_clk_enable(clk->parent);
 
 			if (unlikely(ret != 0)) {
 				clk->usecount--;
@@ -432,7 +432,7 @@
 		ret = clk->enable(clk);
 
 		if (unlikely(ret != 0) && clk->parent) {
-			omap1_clk_unuse(clk->parent);
+			omap1_clk_disable(clk->parent);
 			clk->usecount--;
 		}
 	}
@@ -440,12 +440,12 @@
 	return ret;
 }
 
-static void omap1_clk_unuse(struct clk *clk)
+static void omap1_clk_disable(struct clk *clk)
 {
 	if (clk->usecount > 0 && !(--clk->usecount)) {
 		clk->disable(clk);
 		if (likely(clk->parent)) {
-			omap1_clk_unuse(clk->parent);
+			omap1_clk_disable(clk->parent);
 			if (clk->flags & CLOCK_NO_IDLE_PARENT)
 				if (!cpu_is_omap24xx())
 					omap1_clk_allow_idle(clk->parent);
@@ -453,7 +453,7 @@
 	}
 }
 
-static int omap1_clk_enable(struct clk *clk)
+static int omap1_clk_enable_generic(struct clk *clk)
 {
 	__u16 regval16;
 	__u32 regval32;
@@ -492,7 +492,7 @@
 	return 0;
 }
 
-static void omap1_clk_disable(struct clk *clk)
+static void omap1_clk_disable_generic(struct clk *clk)
 {
 	__u16 regval16;
 	__u32 regval32;
@@ -654,8 +654,8 @@
 #endif
 
 static struct clk_functions omap1_clk_functions = {
-	.clk_use		= omap1_clk_use,
-	.clk_unuse		= omap1_clk_unuse,
+	.clk_enable		= omap1_clk_enable,
+	.clk_disable		= omap1_clk_disable,
 	.clk_round_rate		= omap1_clk_round_rate,
 	.clk_set_rate		= omap1_clk_set_rate,
 };
@@ -780,9 +780,9 @@
 	 * Only enable those clocks we will need, let the drivers
 	 * enable other clocks as necessary
 	 */
-	clk_use(&armper_ck.clk);
-	clk_use(&armxor_ck.clk);
-	clk_use(&armtim_ck.clk); /* This should be done by timer code */
+	clk_enable(&armper_ck.clk);
+	clk_enable(&armxor_ck.clk);
+	clk_enable(&armtim_ck.clk); /* This should be done by timer code */
 
 	if (cpu_is_omap1510())
 		clk_enable(&arm_gpio_ck);
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index f3bdfb5..4f18d1b 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -13,8 +13,8 @@
 #ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H
 #define __ARCH_ARM_MACH_OMAP1_CLOCK_H
 
-static int omap1_clk_enable(struct clk * clk);
-static void omap1_clk_disable(struct clk * clk);
+static int omap1_clk_enable_generic(struct clk * clk);
+static void omap1_clk_disable_generic(struct clk * clk);
 static void omap1_ckctl_recalc(struct clk * clk);
 static void omap1_watchdog_recalc(struct clk * clk);
 static void omap1_ckctl_recalc_dsp_domain(struct clk * clk);
@@ -30,8 +30,8 @@
 static void omap1_init_ext_clk(struct clk * clk);
 static int omap1_select_table_rate(struct clk * clk, unsigned long rate);
 static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate);
-static int omap1_clk_use(struct clk *clk);
-static void omap1_clk_unuse(struct clk *clk);
+static int omap1_clk_enable(struct clk *clk);
+static void omap1_clk_disable(struct clk *clk);
 
 struct mpu_rate {
 	unsigned long		rate;
@@ -152,8 +152,8 @@
 	.rate		= 12000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
 			  ALWAYS_ENABLED,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk ck_dpll1 = {
@@ -161,8 +161,8 @@
 	.parent		= &ck_ref,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
 			  RATE_PROPAGATES | ALWAYS_ENABLED,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct arm_idlect1_clk ck_dpll1out = {
@@ -173,8 +173,8 @@
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_CKOUT_ARM,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable,
-		.disable	= &omap1_clk_disable,
+		.enable		= &omap1_clk_enable_generic,
+		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 12,
 };
@@ -186,8 +186,8 @@
 			  RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.rate_offset	= CKCTL_ARMDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct arm_idlect1_clk armper_ck = {
@@ -200,8 +200,8 @@
 		.enable_bit	= EN_PERCK,
 		.rate_offset	= CKCTL_PERDIV_OFFSET,
 		.recalc		= &omap1_ckctl_recalc,
-		.enable		= &omap1_clk_enable,
-		.disable	= &omap1_clk_disable,
+		.enable		= &omap1_clk_enable_generic,
+		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 2,
 };
@@ -213,8 +213,8 @@
 	.enable_reg	= (void __iomem *)ARM_IDLECT2,
 	.enable_bit	= EN_GPIOCK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct arm_idlect1_clk armxor_ck = {
@@ -226,8 +226,8 @@
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_XORPCK,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable,
-		.disable	= &omap1_clk_disable,
+		.enable		= &omap1_clk_enable_generic,
+		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 1,
 };
@@ -241,8 +241,8 @@
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_TIMCK,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable,
-		.disable	= &omap1_clk_disable,
+		.enable		= &omap1_clk_enable_generic,
+		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 9,
 };
@@ -256,8 +256,8 @@
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_WDTCK,
 		.recalc		= &omap1_watchdog_recalc,
-		.enable		= &omap1_clk_enable,
-		.disable	= &omap1_clk_disable,
+		.enable		= &omap1_clk_enable_generic,
+		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 0,
 };
@@ -272,8 +272,8 @@
 	 *
 	 * 1510 version is in TC clocks.
 	 */
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk dsp_ck = {
@@ -285,8 +285,8 @@
 	.enable_bit	= EN_DSPCK,
 	.rate_offset	= CKCTL_DSPDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk dspmmu_ck = {
@@ -296,8 +296,8 @@
 			  RATE_CKCTL | ALWAYS_ENABLED,
 	.rate_offset	= CKCTL_DSPMMUDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk dspper_ck = {
@@ -349,8 +349,8 @@
 				  CLOCK_IDLE_CONTROL,
 		.rate_offset	= CKCTL_TCDIV_OFFSET,
 		.recalc		= &omap1_ckctl_recalc,
-		.enable		= &omap1_clk_enable,
-		.disable	= &omap1_clk_disable,
+		.enable		= &omap1_clk_enable_generic,
+		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 6,
 };
@@ -364,8 +364,8 @@
 	 *
 	 * 16xx version is in MPU clocks.
 	 */
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk tipb_ck = {
@@ -374,8 +374,8 @@
 	.parent		= &tc_ck.clk,
 	.flags		= CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk l3_ocpi_ck = {
@@ -386,8 +386,8 @@
 	.enable_reg	= (void __iomem *)ARM_IDLECT3,
 	.enable_bit	= EN_OCPI_CK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk tc1_ck = {
@@ -397,8 +397,8 @@
 	.enable_reg	= (void __iomem *)ARM_IDLECT3,
 	.enable_bit	= EN_TC1_CK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk tc2_ck = {
@@ -408,8 +408,8 @@
 	.enable_reg	= (void __iomem *)ARM_IDLECT3,
 	.enable_bit	= EN_TC2_CK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk dma_ck = {
@@ -419,8 +419,8 @@
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
 			  ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk dma_lcdfree_ck = {
@@ -428,8 +428,8 @@
 	.parent		= &tc_ck.clk,
 	.flags		= CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct arm_idlect1_clk api_ck = {
@@ -441,8 +441,8 @@
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_APICK,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable,
-		.disable	= &omap1_clk_disable,
+		.enable		= &omap1_clk_enable_generic,
+		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 8,
 };
@@ -455,8 +455,8 @@
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_LBCK,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable,
-		.disable	= &omap1_clk_disable,
+		.enable		= &omap1_clk_enable_generic,
+		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 4,
 };
@@ -466,8 +466,8 @@
 	.parent		= &tc_ck.clk,
 	.flags		= CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk rhea2_ck = {
@@ -475,8 +475,8 @@
 	.parent		= &tc_ck.clk,
 	.flags		= CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk lcd_ck_16xx = {
@@ -487,8 +487,8 @@
 	.enable_bit	= EN_LCDCK,
 	.rate_offset	= CKCTL_LCDDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct arm_idlect1_clk lcd_ck_1510 = {
@@ -501,8 +501,8 @@
 		.enable_bit	= EN_LCDCK,
 		.rate_offset	= CKCTL_LCDDIV_OFFSET,
 		.recalc		= &omap1_ckctl_recalc,
-		.enable		= &omap1_clk_enable,
-		.disable	= &omap1_clk_disable,
+		.enable		= &omap1_clk_enable_generic,
+		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 3,
 };
@@ -518,8 +518,8 @@
 	.enable_bit	= 29,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
 	.recalc		= &omap1_uart_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct uart_clk uart1_16xx = {
@@ -550,8 +550,8 @@
 	.enable_bit	= 30,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
 	.recalc		= &omap1_uart_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk uart3_1510 = {
@@ -565,8 +565,8 @@
 	.enable_bit	= 31,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
 	.recalc		= &omap1_uart_recalc,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct uart_clk uart3_16xx = {
@@ -593,8 +593,8 @@
 			  RATE_FIXED | ENABLE_REG_32BIT,
 	.enable_reg	= (void __iomem *)ULPD_CLOCK_CTRL,
 	.enable_bit	= USB_MCLK_EN_BIT,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk usb_hhc_ck1510 = {
@@ -605,8 +605,8 @@
 			  RATE_FIXED | ENABLE_REG_32BIT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= USB_HOST_HHC_UHOST_EN,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk usb_hhc_ck16xx = {
@@ -618,8 +618,8 @@
 			  RATE_FIXED | ENABLE_REG_32BIT,
 	.enable_reg	= (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */,
 	.enable_bit	= 8 /* UHOST_EN */,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk usb_dc_ck = {
@@ -629,8 +629,8 @@
 	.flags		= CLOCK_IN_OMAP16XX | RATE_FIXED,
 	.enable_reg	= (void __iomem *)SOFT_REQ_REG,
 	.enable_bit	= 4,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk mclk_1510 = {
@@ -638,8 +638,8 @@
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
 	.flags		= CLOCK_IN_OMAP1510 | RATE_FIXED,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk mclk_16xx = {
@@ -651,8 +651,8 @@
 	.set_rate	= &omap1_set_ext_clk_rate,
 	.round_rate	= &omap1_round_ext_clk_rate,
 	.init		= &omap1_init_ext_clk,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk bclk_1510 = {
@@ -660,8 +660,8 @@
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
 	.flags		= CLOCK_IN_OMAP1510 | RATE_FIXED,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk bclk_16xx = {
@@ -673,8 +673,8 @@
 	.set_rate	= &omap1_set_ext_clk_rate,
 	.round_rate	= &omap1_round_ext_clk_rate,
 	.init		= &omap1_init_ext_clk,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk mmc1_ck = {
@@ -686,8 +686,8 @@
 			  RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 23,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk mmc2_ck = {
@@ -699,8 +699,8 @@
 			  RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 20,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk virtual_ck_mpu = {
@@ -711,8 +711,8 @@
 	.recalc		= &followparent_recalc,
 	.set_rate	= &omap1_select_table_rate,
 	.round_rate	= &omap1_round_to_table_rate,
-	.enable		= &omap1_clk_enable,
-	.disable	= &omap1_clk_disable,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk * onchip_clks[] = {
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index a7a19f7..82d556b 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
+#include <asm/tlb.h>
 #include <asm/mach/map.h>
 #include <asm/io.h>
 #include <asm/arch/mux.h>
@@ -83,15 +84,24 @@
 };
 #endif
 
-static int initialized = 0;
-
-static void __init _omap_map_io(void)
+/*
+ * Maps common IO regions for omap1. This should only get called from
+ * board specific init.
+ */
+void __init omap1_map_common_io(void)
 {
-	initialized = 1;
-
-	/* We have to initialize the IO space mapping before we can run
-	 * cpu_is_omapxxx() macros. */
 	iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
+
+	/* Normally devicemaps_init() would flush caches and tlb after
+	 * mdesc->map_io(), but we must also do it here because of the CPU
+	 * revision check below.
+	 */
+	local_flush_tlb_all();
+	flush_cache_all();
+
+	/* We want to check CPU revision early for cpu_is_omapxxxx() macros.
+	 * IO space mapping must be initialized before we can do that.
+	 */
 	omap_check_revision();
 
 #ifdef CONFIG_ARCH_OMAP730
@@ -111,7 +121,14 @@
 #endif
 
 	omap_sram_init();
+}
 
+/*
+ * Common low-level hardware init for omap1. This should only get called from
+ * board specific init.
+ */
+void __init omap1_init_common_hw()
+{
 	/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
 	 * on a Posted Write in the TIPB Bridge".
 	 */
@@ -121,16 +138,7 @@
 	/* Must init clocks early to assure that timer interrupt works
 	 */
 	omap1_clk_init();
-}
 
-/*
- * This should only get called from board specific init
- */
-void __init omap_map_common_io(void)
-{
-	if (!initialized) {
-		_omap_map_io();
-		omap1_mux_init();
-	}
+	omap1_mux_init();
 }
 
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 7a68f09..e924e0c 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -146,7 +146,7 @@
 			if (IS_ERR(uart1_ck))
 				printk("Could not get uart1_ck\n");
 			else {
-				clk_use(uart1_ck);
+				clk_enable(uart1_ck);
 				if (cpu_is_omap1510())
 					clk_set_rate(uart1_ck, 12000000);
 			}
@@ -166,7 +166,7 @@
 			if (IS_ERR(uart2_ck))
 				printk("Could not get uart2_ck\n");
 			else {
-				clk_use(uart2_ck);
+				clk_enable(uart2_ck);
 				if (cpu_is_omap1510())
 					clk_set_rate(uart2_ck, 12000000);
 				else
@@ -188,7 +188,7 @@
 			if (IS_ERR(uart3_ck))
 				printk("Could not get uart3_ck\n");
 			else {
-				clk_use(uart3_ck);
+				clk_enable(uart3_ck);
 				if (cpu_is_omap1510())
 					clk_set_rate(uart3_ck, 12000000);
 			}
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index b937123..eaecbf4 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -33,6 +33,7 @@
 
 static void __init omap_generic_init_irq(void)
 {
+	omap2_init_common_hw();
 	omap_init_irq();
 }
 
@@ -64,7 +65,7 @@
 
 static void __init omap_generic_map_io(void)
 {
-	omap_map_common_io();
+	omap2_map_common_io();
 }
 
 MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index c3c35d4..a300d63 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -136,6 +136,7 @@
 
 static void __init omap_h4_init_irq(void)
 {
+	omap2_init_common_hw();
 	omap_init_irq();
 	omap_gpio_init();
 	h4_init_smc91x();
@@ -181,7 +182,7 @@
 
 static void __init omap_h4_map_io(void)
 {
-	omap_map_common_io();
+	omap2_map_common_io();
 }
 
 MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 5407b95..180f675 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -111,7 +111,7 @@
 /* Enables clock without considering parent dependencies or use count
  * REVISIT: Maybe change this to use clk->enable like on omap1?
  */
-static int omap2_clk_enable(struct clk * clk)
+static int _omap2_clk_enable(struct clk * clk)
 {
 	u32 regval32;
 
@@ -150,7 +150,7 @@
 }
 
 /* Disables clock without considering parent dependencies or use count */
-static void omap2_clk_disable(struct clk *clk)
+static void _omap2_clk_disable(struct clk *clk)
 {
 	u32 regval32;
 
@@ -167,23 +167,23 @@
 	__raw_writel(regval32, clk->enable_reg);
 }
 
-static int omap2_clk_use(struct clk *clk)
+static int omap2_clk_enable(struct clk *clk)
 {
 	int ret = 0;
 
 	if (clk->usecount++ == 0) {
 		if (likely((u32)clk->parent))
-			ret = omap2_clk_use(clk->parent);
+			ret = omap2_clk_enable(clk->parent);
 
 		if (unlikely(ret != 0)) {
 			clk->usecount--;
 			return ret;
 		}
 
-		ret = omap2_clk_enable(clk);
+		ret = _omap2_clk_enable(clk);
 
 		if (unlikely(ret != 0) && clk->parent) {
-			omap2_clk_unuse(clk->parent);
+			omap2_clk_disable(clk->parent);
 			clk->usecount--;
 		}
 	}
@@ -191,12 +191,12 @@
 	return ret;
 }
 
-static void omap2_clk_unuse(struct clk *clk)
+static void omap2_clk_disable(struct clk *clk)
 {
 	if (clk->usecount > 0 && !(--clk->usecount)) {
-		omap2_clk_disable(clk);
+		_omap2_clk_disable(clk);
 		if (likely((u32)clk->parent))
-			omap2_clk_unuse(clk->parent);
+			omap2_clk_disable(clk->parent);
 	}
 }
 
@@ -873,7 +873,7 @@
 		reg = (void __iomem *)src_sel;
 
 		if (clk->usecount > 0)
-			omap2_clk_disable(clk);
+			_omap2_clk_disable(clk);
 
 		/* Set new source value (previous dividers if any in effect) */
 		reg_val = __raw_readl(reg) & ~(field_mask << src_off);
@@ -884,7 +884,7 @@
 			__raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
 
 		if (clk->usecount > 0)
-			omap2_clk_enable(clk);
+			_omap2_clk_enable(clk);
 
 		clk->parent = new_parent;
 
@@ -999,8 +999,6 @@
 static struct clk_functions omap2_clk_functions = {
 	.clk_enable		= omap2_clk_enable,
 	.clk_disable		= omap2_clk_disable,
-	.clk_use		= omap2_clk_use,
-	.clk_unuse		= omap2_clk_unuse,
 	.clk_round_rate		= omap2_clk_round_rate,
 	.clk_set_rate		= omap2_clk_set_rate,
 	.clk_set_parent		= omap2_clk_set_parent,
@@ -1045,7 +1043,7 @@
 			continue;
 
 		printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name);
-		omap2_clk_disable(ck);
+		_omap2_clk_disable(ck);
 	}
 }
 late_initcall(omap2_disable_unused_clocks);
@@ -1120,10 +1118,10 @@
 	 * Only enable those clocks we will need, let the drivers
 	 * enable other clocks as necessary
 	 */
-	clk_use(&sync_32k_ick);
-	clk_use(&omapctrl_ick);
+	clk_enable(&sync_32k_ick);
+	clk_enable(&omapctrl_ick);
 	if (cpu_is_omap2430())
-		clk_use(&sdrc_ick);
+		clk_enable(&sdrc_ick);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 4aeab55..6cab20b 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -24,7 +24,7 @@
 static void omap2_mpu_recalc(struct clk * clk);
 static int omap2_select_table_rate(struct clk * clk, unsigned long rate);
 static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate);
-static void omap2_clk_unuse(struct clk *clk);
+static void omap2_clk_disable(struct clk *clk);
 static void omap2_sys_clk_recalc(struct clk * clk);
 static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val);
 static u32 omap2_clksel_get_divisor(struct clk *clk);
@@ -859,7 +859,7 @@
 
 static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
-	.parent		= &core_ck,
+	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP |
 				CONFIG_PARTICIPANT,
@@ -1045,7 +1045,7 @@
 	.name		= "gpt1_ick",
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-	.enable_reg	= (void __iomem *)&CM_ICLKEN_WKUP,	/* Bit4 */
+	.enable_reg	= (void __iomem *)&CM_ICLKEN_WKUP,	/* Bit0 */
 	.enable_bit	= 0,
 	.recalc		= &omap2_followparent_recalc,
 };
@@ -1055,7 +1055,7 @@
 	.parent		= &func_32k_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				CM_WKUP_SEL1,
-	.enable_reg	= (void __iomem *)&CM_FCLKEN_WKUP,
+	.enable_reg	= (void __iomem *)&CM_FCLKEN_WKUP,	/* Bit0 */
 	.enable_bit	= 0,
 	.src_offset	= 0,
 	.recalc		= &omap2_followparent_recalc,
@@ -1065,7 +1065,7 @@
 	.name		= "gpt2_ick",
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	/* bit4 */
+	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	/* Bit4 */
 	.enable_bit	= 0,
 	.recalc		= &omap2_followparent_recalc,
 };
@@ -1839,7 +1839,7 @@
 
 static struct clk usbhs_ick = {
 	.name		= "usbhs_ick",
-	.parent		= &l4_ck,
+	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
 	.enable_bit	= 6,
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index e1bd46a..24dd374 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -119,14 +119,14 @@
 			if (IS_ERR(uart1_ick))
 				printk("Could not get uart1_ick\n");
 			else {
-				clk_use(uart1_ick);
+				clk_enable(uart1_ick);
 			}
 
 			uart1_fck = clk_get(NULL, "uart1_fck");
 			if (IS_ERR(uart1_fck))
 				printk("Could not get uart1_fck\n");
 			else {
-				clk_use(uart1_fck);
+				clk_enable(uart1_fck);
 			}
 			break;
 		case 1:
@@ -134,14 +134,14 @@
 			if (IS_ERR(uart2_ick))
 				printk("Could not get uart2_ick\n");
 			else {
-				clk_use(uart2_ick);
+				clk_enable(uart2_ick);
 			}
 
 			uart2_fck = clk_get(NULL, "uart2_fck");
 			if (IS_ERR(uart2_fck))
 				printk("Could not get uart2_fck\n");
 			else {
-				clk_use(uart2_fck);
+				clk_enable(uart2_fck);
 			}
 			break;
 		case 2:
@@ -149,14 +149,14 @@
 			if (IS_ERR(uart3_ick))
 				printk("Could not get uart3_ick\n");
 			else {
-				clk_use(uart3_ick);
+				clk_enable(uart3_ick);
 			}
 
 			uart3_fck = clk_get(NULL, "uart3_fck");
 			if (IS_ERR(uart3_fck))
 				printk("Could not get uart3_fck\n");
 			else {
-				clk_use(uart3_fck);
+				clk_enable(uart3_fck);
 			}
 			break;
 		}
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 23d36b1..1d2f5ac 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -104,7 +104,7 @@
 	if (IS_ERR(sys_ck))
 		printk(KERN_ERR "Could not get sys_ck\n");
 	else {
-		clk_use(sys_ck);
+		clk_enable(sys_ck);
 		tick_period = clk_get_rate(sys_ck) / 100;
 		clk_put(sys_ck);
 	}
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index b41b1ef..3baa708 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -44,7 +44,7 @@
 
 	/* Read clkcfg register: it has turbo, b, half-turbo (and f) */
 	asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg) );
-	t  = clkcfg & (1 << 1);
+	t  = clkcfg & (1 << 0);
 	ht = clkcfg & (1 << 2);
 	b  = clkcfg & (1 << 3);
 
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 4a222f5..4303d98 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -182,7 +182,7 @@
 static void realview_oscvco_set(struct clk *clk, struct icst307_vco vco)
 {
 	void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET;
-	void __iomem *sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC1_OFFSET;
+	void __iomem *sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET;
 	u32 val;
 
 	val = readl(sys_osc) & ~0x7ffff;
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index b4f1e05..1217bf0 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -10,9 +10,13 @@
 obj-n			:=
 obj-			:=
 
+# S3C2400 support files
+obj-$(CONFIG_CPU_S3C2400)  += s3c2400-gpio.o
+
 # S3C2410 support files
 
 obj-$(CONFIG_CPU_S3C2410)  += s3c2410.o
+obj-$(CONFIG_CPU_S3C2410)  += s3c2410-gpio.o
 obj-$(CONFIG_S3C2410_DMA)  += dma.o
 
 # Power Management support
@@ -25,6 +29,7 @@
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440.o s3c2440-dsc.o
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440-irq.o
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440-clock.o
+obj-$(CONFIG_CPU_S3C2440)  += s3c2410-gpio.o
 
 # bast extras
 
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index af2f3d5..08489ef 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -40,7 +40,6 @@
 #include <linux/mutex.h>
 
 #include <asm/hardware.h>
-#include <asm/atomic.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 
@@ -59,22 +58,18 @@
 void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable)
 {
 	unsigned long clkcon;
-	unsigned long flags;
-
-	local_irq_save(flags);
 
 	clkcon = __raw_readl(S3C2410_CLKCON);
-	clkcon &= ~clocks;
 
 	if (enable)
 		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
 
 	/* ensure none of the special function bits set */
 	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
 
 	__raw_writel(clkcon, S3C2410_CLKCON);
-
-	local_irq_restore(flags);
 }
 
 /* enable and disable calls for use with the clk struct */
@@ -138,16 +133,32 @@
 
 int clk_enable(struct clk *clk)
 {
-	if (IS_ERR(clk))
+	if (IS_ERR(clk) || clk == NULL)
 		return -EINVAL;
 
-	return (clk->enable)(clk, 1);
+	clk_enable(clk->parent);
+
+	mutex_lock(&clocks_mutex);
+
+	if ((clk->usage++) == 0)
+		(clk->enable)(clk, 1);
+
+	mutex_unlock(&clocks_mutex);
+	return 0;
 }
 
 void clk_disable(struct clk *clk)
 {
-	if (!IS_ERR(clk))
+	if (IS_ERR(clk) || clk == NULL)
+		return;
+
+	mutex_lock(&clocks_mutex);
+
+	if ((--clk->usage) == 0)
 		(clk->enable)(clk, 0);
+
+	mutex_unlock(&clocks_mutex);
+	clk_disable(clk->parent);
 }
 
 
@@ -361,6 +372,14 @@
 	if (clk->enable == NULL)
 		clk->enable = clk_null_enable;
 
+	/* if this is a standard clock, set the usage state */
+
+	if (clk->ctrlbit) {
+		unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
+
+		clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0;
+	}
+
 	/* add to the list of available clocks */
 
 	mutex_lock(&clocks_mutex);
@@ -402,6 +421,8 @@
 	 * the LCD clock if it is not needed.
 	*/
 
+	mutex_lock(&clocks_mutex);
+
 	s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0);
 	s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0);
 	s3c24xx_clk_enable(S3C2410_CLKCON_USBD, 0);
@@ -409,6 +430,8 @@
 	s3c24xx_clk_enable(S3C2410_CLKCON_IIC, 0);
 	s3c24xx_clk_enable(S3C2410_CLKCON_SPI, 0);
 
+	mutex_unlock(&clocks_mutex);
+
 	/* assume uart clocks are correctly setup */
 
 	/* register our clocks */
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
index 177d5c8..eb5c95d 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/arch/arm/mach-s3c2410/clock.h
@@ -16,6 +16,7 @@
 	struct clk           *parent;
 	const char           *name;
 	int		      id;
+	int		      usage;
 	unsigned long         rate;
 	unsigned long         ctrlbit;
 	int		    (*enable)(struct clk *, int enable);
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
index 687fe37..00a3793 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/mach-s3c2410/cpu.c
@@ -40,6 +40,7 @@
 
 #include "cpu.h"
 #include "clock.h"
+#include "s3c2400.h"
 #include "s3c2410.h"
 #include "s3c2440.h"
 
@@ -55,6 +56,7 @@
 
 /* table of supported CPUs */
 
+static const char name_s3c2400[]  = "S3C2400";
 static const char name_s3c2410[]  = "S3C2410";
 static const char name_s3c2440[]  = "S3C2440";
 static const char name_s3c2410a[] = "S3C2410A";
@@ -96,7 +98,16 @@
 		.init_uarts	= s3c2440_init_uarts,
 		.init		= s3c2440_init,
 		.name		= name_s3c2440a
-	}
+	},
+	{
+		.idcode		= 0x0,   /* S3C2400 doesn't have an idcode */
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2400_map_io,
+		.init_clocks	= s3c2400_init_clocks,
+		.init_uarts	= s3c2400_init_uarts,
+		.init		= s3c2400_init,
+		.name		= name_s3c2400
+	},
 };
 
 /* minimal IO mapping */
@@ -148,12 +159,15 @@
 
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 {
-	unsigned long idcode;
+	unsigned long idcode = 0x0;
 
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 
+#ifndef CONFIG_CPU_S3C2400
 	idcode = __raw_readl(S3C2410_GSTATUS1);
+#endif
+
 	cpu = s3c_lookup_cpu(idcode);
 
 	if (cpu == NULL) {
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
index 9cbe5ee..fc10677 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/arch/arm/mach-s3c2410/cpu.h
@@ -17,11 +17,12 @@
  *     14-Jan-2005 BJD  Added s3c24xx_init_clocks() call
  *     10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} & IODESC_ENT
  *     14-Mar-2005 BJD  Updated for __iomem
+ *     15-Jan-2006 LCVR Updated S3C2410_PA_##x to new S3C24XX_PA_##x macro
 */
 
 /* todo - fix when rmk changes iodescs to use `void __iomem *` */
 
-#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C2410_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
+#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef MHZ
 #define MHZ (1000*1000)
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index f58406e..0a47d38 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     15-Jan-2006 LCVR Using S3C24XX_PA_##x macro for common S3C24XX devices
  *     10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
  *     10-Feb-2005 BJD  Added camera from guillaume.gourat@nexvision.tv
  *     29-Aug-2004 BJD  Added timers 0 through 3
@@ -46,8 +47,8 @@
 
 static struct resource s3c_usb_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_USBHOST,
-		.end   = S3C2410_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
+		.start = S3C24XX_PA_USBHOST,
+		.end   = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -76,8 +77,8 @@
 
 static struct resource s3c_lcd_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_LCD,
-		.end   = S3C2410_PA_LCD + S3C24XX_SZ_LCD - 1,
+		.start = S3C24XX_PA_LCD,
+		.end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -139,8 +140,8 @@
 
 static struct resource s3c_usbgadget_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_USBDEV,
-		.end   = S3C2410_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
+		.start = S3C24XX_PA_USBDEV,
+		.end   = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -164,8 +165,8 @@
 
 static struct resource s3c_wdt_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_WATCHDOG,
-		.end   = S3C2410_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,
+		.start = S3C24XX_PA_WATCHDOG,
+		.end   = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -189,8 +190,8 @@
 
 static struct resource s3c_i2c_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_IIC,
-		.end   = S3C2410_PA_IIC + S3C24XX_SZ_IIC - 1,
+		.start = S3C24XX_PA_IIC,
+		.end   = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -214,8 +215,8 @@
 
 static struct resource s3c_iis_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_IIS,
-		.end   = S3C2410_PA_IIS + S3C24XX_SZ_IIS -1,
+		.start = S3C24XX_PA_IIS,
+		.end   = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1,
 		.flags = IORESOURCE_MEM,
 	}
 };
@@ -239,8 +240,8 @@
 
 static struct resource s3c_rtc_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_RTC,
-		.end   = S3C2410_PA_RTC + 0xff,
+		.start = S3C24XX_PA_RTC,
+		.end   = S3C24XX_PA_RTC + 0xff,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -268,12 +269,17 @@
 
 static struct resource s3c_adc_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_ADC,
-		.end   = S3C2410_PA_ADC + S3C24XX_SZ_ADC - 1,
+		.start = S3C24XX_PA_ADC,
+		.end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
 		.start = IRQ_TC,
+		.end   = IRQ_TC,
+		.flags = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start = IRQ_ADC,
 		.end   = IRQ_ADC,
 		.flags = IORESOURCE_IRQ,
 	}
@@ -316,8 +322,8 @@
 
 static struct resource s3c_spi0_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_SPI,
-		.end   = S3C2410_PA_SPI + 0x1f,
+		.start = S3C24XX_PA_SPI,
+		.end   = S3C24XX_PA_SPI + 0x1f,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -341,8 +347,8 @@
 
 static struct resource s3c_spi1_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_SPI + 0x20,
-		.end   = S3C2410_PA_SPI + 0x20 + 0x1f,
+		.start = S3C24XX_PA_SPI + 0x20,
+		.end   = S3C24XX_PA_SPI + 0x20 + 0x1f,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -366,8 +372,8 @@
 
 static struct resource s3c_timer0_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_TIMER + 0x0C,
-		.end   = S3C2410_PA_TIMER + 0x0C + 0xB,
+		.start = S3C24XX_PA_TIMER + 0x0C,
+		.end   = S3C24XX_PA_TIMER + 0x0C + 0xB,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -391,8 +397,8 @@
 
 static struct resource s3c_timer1_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_TIMER + 0x18,
-		.end   = S3C2410_PA_TIMER + 0x23,
+		.start = S3C24XX_PA_TIMER + 0x18,
+		.end   = S3C24XX_PA_TIMER + 0x23,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -416,8 +422,8 @@
 
 static struct resource s3c_timer2_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_TIMER + 0x24,
-		.end   = S3C2410_PA_TIMER + 0x2F,
+		.start = S3C24XX_PA_TIMER + 0x24,
+		.end   = S3C24XX_PA_TIMER + 0x2F,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -441,8 +447,8 @@
 
 static struct resource s3c_timer3_resource[] = {
 	[0] = {
-		.start = S3C2410_PA_TIMER + 0x30,
-		.end   = S3C2410_PA_TIMER + 0x3B,
+		.start = S3C24XX_PA_TIMER + 0x30,
+		.end   = S3C24XX_PA_TIMER + 0x3B,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 65feaf2..4dbd8e7 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -1152,7 +1152,7 @@
 
 	printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n");
 
-	dma_base = ioremap(S3C2410_PA_DMA, 0x200);
+	dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
 	if (dma_base == NULL) {
 		printk(KERN_ERR "dma failed to remap register block\n");
 		return -ENOMEM;
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index 23ea3d5..cd39e86 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -31,6 +31,7 @@
  *	05-Nov-2004  BJD  EXPORT_SYMBOL() added for all code
  *	13-Mar-2005  BJD  Updates for __iomem
  *	26-Oct-2005  BJD  Added generic configuration types
+ *	15-Jan-2006  LCVR Added support for the S3C2400
  */
 
 
@@ -48,7 +49,7 @@
 
 void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
 {
-	void __iomem *base = S3C2410_GPIO_BASE(pin);
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
 	unsigned long mask;
 	unsigned long con;
 	unsigned long flags;
@@ -95,7 +96,7 @@
 
 unsigned int s3c2410_gpio_getcfg(unsigned int pin)
 {
-	void __iomem *base = S3C2410_GPIO_BASE(pin);
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
 	unsigned long mask;
 
 	if (pin < S3C2410_GPIO_BANKB) {
@@ -111,7 +112,7 @@
 
 void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
 {
-	void __iomem *base = S3C2410_GPIO_BASE(pin);
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
 	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
 	unsigned long flags;
 	unsigned long up;
@@ -133,7 +134,7 @@
 
 void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
 {
-	void __iomem *base = S3C2410_GPIO_BASE(pin);
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
 	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
 	unsigned long flags;
 	unsigned long dat;
@@ -152,7 +153,7 @@
 
 unsigned int s3c2410_gpio_getpin(unsigned int pin)
 {
-	void __iomem *base = S3C2410_GPIO_BASE(pin);
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
 	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
 
 	return __raw_readl(base + 0x04) & (1<< offs);
@@ -166,70 +167,13 @@
 	unsigned long misccr;
 
 	local_irq_save(flags);
-	misccr = __raw_readl(S3C2410_MISCCR);
+	misccr = __raw_readl(S3C24XX_MISCCR);
 	misccr &= ~clear;
 	misccr ^= change;
-	__raw_writel(misccr, S3C2410_MISCCR);
+	__raw_writel(misccr, S3C24XX_MISCCR);
 	local_irq_restore(flags);
 
 	return misccr;
 }
 
 EXPORT_SYMBOL(s3c2410_modify_misccr);
-
-int s3c2410_gpio_getirq(unsigned int pin)
-{
-	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23)
-		return -1;	/* not valid interrupts */
-
-	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
-		return -1;	/* not valid pin */
-
-	if (pin < S3C2410_GPF4)
-		return (pin - S3C2410_GPF0) + IRQ_EINT0;
-
-	if (pin < S3C2410_GPG0)
-		return (pin - S3C2410_GPF4) + IRQ_EINT4;
-
-	return (pin - S3C2410_GPG0) + IRQ_EINT8;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getirq);
-
-int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-			   unsigned int config)
-{
-	void __iomem *reg = S3C2410_EINFLT0;
-	unsigned long flags;
-	unsigned long val;
-
-	if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
-		return -1;
-
-	config &= 0xff;
-
-	pin -= S3C2410_GPG8_EINT16;
-	reg += pin & ~3;
-
-	local_irq_save(flags);
-
-	/* update filter width and clock source */
-
-	val = __raw_readl(reg);
-	val &= ~(0xff << ((pin & 3) * 8));
-	val |= config << ((pin & 3) * 8);
-	__raw_writel(val, reg);
-
-	/* update filter enable */
-
-	val = __raw_readl(S3C2410_EXTINT2);
-	val &= ~(1 << ((pin * 4) + 3));
-	val |= on << ((pin * 4) + 3);
-	__raw_writel(val, S3C2410_EXTINT2);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 1c316f1..646a3a5 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -46,10 +46,11 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-//#include <asm/debug-ll.h>
+
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-lcd.h>
 
+#include <asm/arch/h1940-latch.h>
 #include <asm/arch/fb.h>
 
 #include <linux/serial_core.h>
@@ -59,7 +60,12 @@
 #include "cpu.h"
 
 static struct map_desc h1940_iodesc[] __initdata = {
-	/* nothing here yet */
+	[0] = {
+		.virtual	= (unsigned long)H1940_LATCH,
+		.pfn		= __phys_to_pfn(H1940_PA_LATCH),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE
+	},
 };
 
 #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
@@ -92,6 +98,25 @@
 	}
 };
 
+/* Board control latch control */
+
+static unsigned int latch_state = H1940_LATCH_DEFAULT;
+
+void h1940_latch_control(unsigned int clear, unsigned int set)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	latch_state &= ~clear;
+	latch_state |= set;
+
+	__raw_writel(latch_state, H1940_LATCH);
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL_GPL(h1940_latch_control);
 
 
 /**
diff --git a/arch/arm/mach-s3c2410/s3c2400-gpio.c b/arch/arm/mach-s3c2410/s3c2400-gpio.c
new file mode 100644
index 0000000..5127f39
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2400-gpio.c
@@ -0,0 +1,45 @@
+/* linux/arch/arm/mach-s3c2410/gpio.c
+ *
+ * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org>
+ *
+ * S3C2400 GPIO support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ *
+ * Changelog
+ *	15-Jan-2006  LCVR  Splitted from gpio.c, adding support for the S3C2400
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-gpio.h>
+
+int s3c2400_gpio_getirq(unsigned int pin)
+{
+	if (pin < S3C2410_GPE0 || pin > S3C2400_GPE7_EINT7)
+		return -1;  /* not valid interrupts */
+
+	return (pin - S3C2410_GPE0) + IRQ_EINT0;
+}
+
+EXPORT_SYMBOL(s3c2400_gpio_getirq);
diff --git a/arch/arm/mach-s3c2410/s3c2400.h b/arch/arm/mach-s3c2410/s3c2400.h
new file mode 100644
index 0000000..8b2394e
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2400.h
@@ -0,0 +1,31 @@
+/* arch/arm/mach-s3c2410/s3c2400.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2400 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ *     09-Fev-2006 LCVR  First version, based on s3c2410.h
+*/
+
+#ifdef CONFIG_CPU_S3C2400
+
+extern  int s3c2400_init(void);
+
+extern void s3c2400_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2400_init_clocks(int xtal);
+
+#else
+#define s3c2400_init_clocks NULL
+#define s3c2400_init_uarts NULL
+#define s3c2400_map_io NULL
+#define s3c2400_init NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c
new file mode 100644
index 0000000..d5e1cae
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2410-gpio.c
@@ -0,0 +1,93 @@
+/* linux/arch/arm/mach-s3c2410/gpio.c
+ *
+ * Copyright (c) 2004-2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 GPIO support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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
+ *
+ * Changelog
+ *	15-Jan-2006  LCVR  Splitted from gpio.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-gpio.h>
+
+int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+			   unsigned int config)
+{
+	void __iomem *reg = S3C2410_EINFLT0;
+	unsigned long flags;
+	unsigned long val;
+
+	if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
+		return -1;
+
+	config &= 0xff;
+
+	pin -= S3C2410_GPG8_EINT16;
+	reg += pin & ~3;
+
+	local_irq_save(flags);
+
+	/* update filter width and clock source */
+
+	val = __raw_readl(reg);
+	val &= ~(0xff << ((pin & 3) * 8));
+	val |= config << ((pin & 3) * 8);
+	__raw_writel(val, reg);
+
+	/* update filter enable */
+
+	val = __raw_readl(S3C2410_EXTINT2);
+	val &= ~(1 << ((pin * 4) + 3));
+	val |= on << ((pin * 4) + 3);
+	__raw_writel(val, S3C2410_EXTINT2);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
+
+int s3c2410_gpio_getirq(unsigned int pin)
+{
+	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23)
+		return -1;	/* not valid interrupts */
+
+	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
+		return -1;	/* not valid pin */
+
+	if (pin < S3C2410_GPF4)
+		return (pin - S3C2410_GPF0) + IRQ_EINT0;
+
+	if (pin < S3C2410_GPG0)
+		return (pin - S3C2410_GPF4) + IRQ_EINT4;
+
+	return (pin - S3C2410_GPG0) + IRQ_EINT8;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getirq);
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 61768da..832fb86 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -72,7 +72,7 @@
 	@@ prepare cpu to sleep
 
 	ldr	r4, =S3C2410_REFRESH
-	ldr	r5, =S3C2410_MISCCR
+	ldr	r5, =S3C24XX_MISCCR
 	ldr	r6, =S3C2410_CLKCON
 	ldr	r7, [ r4 ]		@ get REFRESH (and ensure in TLB)
 	ldr	r8, [ r5 ]		@ get MISCCR (and ensure in TLB)
@@ -133,12 +133,12 @@
 	@@ load UART to allow us to print the two characters for
 	@@ resume debug
 
-	mov	r2, #S3C2410_PA_UART & 0xff000000
-	orr	r2, r2, #S3C2410_PA_UART & 0xff000
+	mov	r2, #S3C24XX_PA_UART & 0xff000000
+	orr	r2, r2, #S3C24XX_PA_UART & 0xff000
 
 #if 0
 	/* SMDK2440 LED set */
-	mov	r14, #S3C2410_PA_GPIO
+	mov	r14, #S3C24XX_PA_GPIO
 	ldr	r12, [ r14, #0x54 ]
 	bic	r12, r12, #3<<4
 	orr	r12, r12, #1<<7
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 72966d9..d921c10 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -92,22 +92,16 @@
  *	- the Icache does not read data from the write buffer
  */
 ENTRY(v6_coherent_user_range)
-	bic	r0, r0, #CACHE_LINE_SIZE - 1
-1:
+
 #ifdef HARVARD_CACHE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D line
+	bic	r0, r0, #CACHE_LINE_SIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D line
 	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I line
-#endif
-	mcr	p15, 0, r0, c7, c5, 7		@ invalidate BTB entry
-	add	r0, r0, #BTB_FLUSH_SIZE
-	mcr	p15, 0, r0, c7, c5, 7		@ invalidate BTB entry
-	add	r0, r0, #BTB_FLUSH_SIZE
-	mcr	p15, 0, r0, c7, c5, 7		@ invalidate BTB entry
-	add	r0, r0, #BTB_FLUSH_SIZE
-	mcr	p15, 0, r0, c7, c5, 7		@ invalidate BTB entry
-	add	r0, r0, #BTB_FLUSH_SIZE
+	add	r0, r0, #CACHE_LINE_SIZE
 	cmp	r0, r1
 	blo	1b
+#endif
+	mcr	p15, 0, r0, c7, c5, 6		@ invalidate BTB
 #ifdef HARVARD_CACHE
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index de3ce1e..da9b359 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -142,7 +142,7 @@
  		return NULL;
  	addr = (unsigned long)area->addr;
  	if (remap_area_pages(addr, pfn, size, flags)) {
- 		vfree(addr);
+ 		vfree((void *)addr);
  		return NULL;
  	}
  	return (void __iomem *) (offset + (char *)addr);
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index d0245a3..ef8d30a 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -343,6 +343,12 @@
 				PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE |
 				PMD_SECT_TEX(1),
 		.domain    = DOMAIN_IO,
+	},
+	[MT_NONSHARED_DEVICE] = {
+		.prot_l1   = PMD_TYPE_TABLE,
+		.prot_sect = PMD_TYPE_SECT | PMD_SECT_NONSHARED_DEV |
+				PMD_SECT_AP_WRITE,
+		.domain    = DOMAIN_IO,
 	}
 };
 
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 861b3594..2d3823e 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -241,7 +241,15 @@
  *	it also trashes the mini I-cache used by JTAG debuggers.
  */
 ENTRY(xscale_coherent_kern_range)
-	/* FALLTHROUGH */
+	bic	r0, r0, #CACHELINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHELINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ Invalidate I cache & BTB
+	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mov	pc, lr
 
 /*
  *	coherent_user_range(start, end)
@@ -252,18 +260,16 @@
  *
  *	- start  - virtual start address
  *	- end	 - virtual end address
- *
- *	Note: single I-cache line invalidation isn't used here since
- *	it also trashes the mini I-cache used by JTAG debuggers.
  */
 ENTRY(xscale_coherent_user_range)
 	bic	r0, r0, #CACHELINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache entry
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
 	mov	r0, #0
-	mcr	p15, 0, r0, c7, c5, 0		@ Invalidate I cache & BTB
+	mcr	p15, 0, r0, c7, c5, 6		@ Invalidate BTB
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
 	mov	pc, lr
 
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index 1415930..6f8bc1f 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -137,8 +137,9 @@
 	if (spec) {
 		init_MUTEX(&op_arm_sem);
 
-		if (spec->init() < 0)
-			return -ENODEV;
+		ret = spec->init();
+		if (ret < 0)
+			return ret;
 
 		op_arm_model = spec;
 		init_driverfs();
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 7ebc5a2..3c2bfc0 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -34,7 +34,7 @@
 static struct clk_functions *arch_clock;
 
 /*-------------------------------------------------------------------------
- * Standard clock functions defined in asm/hardware/clock.h
+ * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
 
 struct clk * clk_get(struct device *dev, const char *id)
@@ -60,12 +60,8 @@
 	int ret = 0;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (clk->enable)
-		ret = clk->enable(clk);
-	else if (arch_clock->clk_enable)
+	if (arch_clock->clk_enable)
 		ret = arch_clock->clk_enable(clk);
-	else
-		printk(KERN_ERR "Could not enable clock %s\n", clk->name);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -77,41 +73,12 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (clk->disable)
-		clk->disable(clk);
-	else if (arch_clock->clk_disable)
+	if (arch_clock->clk_disable)
 		arch_clock->clk_disable(clk);
-	else
-		printk(KERN_ERR "Could not disable clock %s\n", clk->name);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
-int clk_use(struct clk *clk)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_use)
-		ret = arch_clock->clk_use(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_use);
-
-void clk_unuse(struct clk *clk)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_unuse)
-		arch_clock->clk_unuse(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-EXPORT_SYMBOL(clk_unuse);
-
 int clk_get_usecount(struct clk *clk)
 {
 	unsigned long flags;
@@ -146,7 +113,7 @@
 EXPORT_SYMBOL(clk_put);
 
 /*-------------------------------------------------------------------------
- * Optional clock functions defined in asm/hardware/clock.h
+ * Optional clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index ca3681a..b4d5b9e 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -853,19 +853,19 @@
 		if (IS_ERR(gpio_ick))
 			printk("Could not get arm_gpio_ck\n");
 		else
-			clk_use(gpio_ick);
+			clk_enable(gpio_ick);
 	}
 	if (cpu_is_omap24xx()) {
 		gpio_ick = clk_get(NULL, "gpios_ick");
 		if (IS_ERR(gpio_ick))
 			printk("Could not get gpios_ick\n");
 		else
-			clk_use(gpio_ick);
+			clk_enable(gpio_ick);
 		gpio_fck = clk_get(NULL, "gpios_fck");
 		if (IS_ERR(gpio_ick))
 			printk("Could not get gpios_fck\n");
 		else
-			clk_use(gpio_fck);
+			clk_enable(gpio_fck);
 	}
 
 #ifdef CONFIG_ARCH_OMAP15XX
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index be0e0f3..1cd2cac 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -190,11 +190,11 @@
 static void omap_mcbsp_dsp_request(void)
 {
 	if (cpu_is_omap1510() || cpu_is_omap16xx()) {
-		clk_use(mcbsp_dsp_ck);
-		clk_use(mcbsp_api_ck);
+		clk_enable(mcbsp_dsp_ck);
+		clk_enable(mcbsp_api_ck);
 
 		/* enable 12MHz clock to mcbsp 1 & 3 */
-		clk_use(mcbsp_dspxor_ck);
+		clk_enable(mcbsp_dspxor_ck);
 
 		/*
 		 * DSP external peripheral reset
@@ -208,9 +208,9 @@
 static void omap_mcbsp_dsp_free(void)
 {
 	if (cpu_is_omap1510() || cpu_is_omap16xx()) {
-		clk_unuse(mcbsp_dspxor_ck);
-		clk_unuse(mcbsp_dsp_ck);
-		clk_unuse(mcbsp_api_ck);
+		clk_disable(mcbsp_dspxor_ck);
+		clk_disable(mcbsp_dsp_ck);
+		clk_disable(mcbsp_api_ck);
 	}
 }
 
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c
index e40fcc8..5cc6775 100644
--- a/arch/arm/plat-omap/ocpi.c
+++ b/arch/arm/plat-omap/ocpi.c
@@ -88,7 +88,7 @@
 	if (IS_ERR(ocpi_ck))
 		return PTR_ERR(ocpi_ck);
 
-	clk_use(ocpi_ck);
+	clk_enable(ocpi_ck);
 	ocpi_enable();
 	printk("OMAP OCPI interconnect driver loaded\n");
 
@@ -102,7 +102,7 @@
 	if (!cpu_is_omap16xx())
 		return;
 
-	clk_unuse(ocpi_ck);
+	clk_disable(ocpi_ck);
 	clk_put(ocpi_ck);
 }
 
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 792f663..ee82763 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 
 #include <asm/mach/map.h>
+#include <asm/tlb.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
@@ -96,6 +97,14 @@
 	       omap_sram_io_desc[0].length);
 
 	/*
+	 * Normally devicemaps_init() would flush caches and tlb after
+	 * mdesc->map_io(), but since we're called from map_io(), we
+	 * must do it here.
+	 */
+	local_flush_tlb_all();
+	flush_cache_all();
+
+	/*
 	 * Looks like we need to preserve some bootloader code at the
 	 * beginning of SRAM for jumping to flash for reboot to work...
 	 */
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 274e070..dee23d8 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -53,14 +53,14 @@
 
 config ARCH_MAY_HAVE_PC_FDC
 	bool
-	default y
 
 source "init/Kconfig"
 
 
 menu "System Type"
 
-comment "Archimedes/A5000 Implementations (select only ONE)"
+choice
+	prompt "Archimedes/A5000 Implementations"
 
 config ARCH_ARC
         bool "Archimedes"
@@ -73,6 +73,7 @@
 
 config ARCH_A5K
         bool "A5000"
+	select ARCH_MAY_HAVE_PC_FDC
         help
           Say Y here to to support the Acorn A5000.
 
@@ -87,6 +88,7 @@
           Say Y here if your Archimedes or A5000 system has only 2MB of
           memory, otherwise say N.  The resulting kernel will not run on a
           machine with 4MB of memory.
+endchoice
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/arm26/kernel/fiq.c b/arch/arm26/kernel/fiq.c
index 08a97c9..a24272b 100644
--- a/arch/arm26/kernel/fiq.c
+++ b/arch/arm26/kernel/fiq.c
@@ -104,14 +104,14 @@
 {
 	register unsigned long tmp, tmp2;
 	__asm__ volatile (
-	"mov	%0, pc
-	bic	%1, %0, #0x3
-	orr	%1, %1, %3
-	teqp	%1, #0		@ select FIQ mode
-	mov	r0, r0
-	ldmia	%2, {r8 - r14}
-	teqp	%0, #0		@ return to SVC mode
-	mov	r0, r0"
+	"mov	%0, pc					\n"
+	"bic	%1, %0, #0x3				\n"
+	"orr	%1, %1, %3				\n"
+	"teqp	%1, #0		@ select FIQ mode	\n"
+	"mov	r0, r0					\n"
+	"ldmia	%2, {r8 - r14}				\n"
+	"teqp	%0, #0		@ return to SVC mode	\n"
+	"mov	r0, r0					"
 	: "=&r" (tmp), "=&r" (tmp2)
 	: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | MODE_FIQ26)
 	/* These registers aren't modified by the above code in a way
@@ -125,14 +125,14 @@
 {
 	register unsigned long tmp, tmp2;
 	__asm__ volatile (
-	"mov	%0, pc
-	bic	%1, %0, #0x3
-	orr	%1, %1, %3
-	teqp	%1, #0		@ select FIQ mode
-	mov	r0, r0
-	stmia	%2, {r8 - r14}
-	teqp	%0, #0		@ return to SVC mode
-	mov	r0, r0"
+	"mov	%0, pc					\n"
+	"bic	%1, %0, #0x3				\n"
+	"orr	%1, %1, %3				\n"
+	"teqp	%1, #0		@ select FIQ mode	\n"
+	"mov	r0, r0					\n"
+	"stmia	%2, {r8 - r14}				\n"
+	"teqp	%0, #0		@ return to SVC mode	\n"
+	"mov	r0, r0					"
 	: "=&r" (tmp), "=&r" (tmp2)
 	: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | MODE_FIQ26)
 	/* These registers aren't modified by the above code in a way
diff --git a/arch/arm26/kernel/signal.c b/arch/arm26/kernel/signal.c
index ce2055b..2a48c12 100644
--- a/arch/arm26/kernel/signal.c
+++ b/arch/arm26/kernel/signal.c
@@ -480,6 +480,7 @@
 {
 	siginfo_t info;
 	int signr;
+	struct k_sigaction ka;
 
 	/*
 	 * We want the common case to go fast, which
@@ -493,7 +494,7 @@
         if (current->ptrace & PT_SINGLESTEP)
                 ptrace_cancel_bpt(current);
 	
-        signr = get_signal_to_deliver(&info, regs, NULL);
+        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
         if (signr > 0) {
                 handle_signal(signr, &info, oldset, regs, syscall);
                 if (current->ptrace & PT_SINGLESTEP)
diff --git a/arch/cris/Makefile b/arch/cris/Makefile
index ea65d58..ee11469 100644
--- a/arch/cris/Makefile
+++ b/arch/cris/Makefile
@@ -119,7 +119,7 @@
 	@ln -sfn $(SRC_ARCH)/$(SARCH)/lib $(SRC_ARCH)/lib
 	@ln -sfn $(SRC_ARCH)/$(SARCH) $(SRC_ARCH)/arch
 	@ln -sfn $(SRC_ARCH)/$(SARCH)/vmlinux.lds.S $(SRC_ARCH)/kernel/vmlinux.lds.S
-	@ln -sfn $(SRC_ARCH)/$(SARCH)/asm-offsets.c $(SRC_ARCH)/kernel/asm-offsets.c
+	@ln -sfn $(SRC_ARCH)/$(SARCH)/kernel/asm-offsets.c $(SRC_ARCH)/kernel/asm-offsets.c
 	@touch $@
 
 # Create link to sub arch includes
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index f214f74..961c0d5 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -202,18 +202,18 @@
 		  	int i;
 			unsigned long tmp;
 			
+			ret = 0;
 			for (i = 0; i <= PT_MAX; i++) {
 				tmp = get_reg(child, i);
 				
 				if (put_user(tmp, datap)) {
 					ret = -EFAULT;
-					goto out_tsk;
+					break;
 				}
 				
 				data += sizeof(long);
 			}
 
-			ret = 0;
 			break;
 		}
 
@@ -222,10 +222,11 @@
 			int i;
 			unsigned long tmp;
 			
+			ret = 0;
 			for (i = 0; i <= PT_MAX; i++) {
 				if (get_user(tmp, datap)) {
 					ret = -EFAULT;
-					goto out_tsk;
+					break;
 				}
 				
 				if (i == PT_DCCR) {
@@ -237,7 +238,6 @@
 				data += sizeof(long);
 			}
 			
-			ret = 0;
 			break;
 		}
 
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index d11206e..1ba57ef 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -24,7 +24,6 @@
 /*
  * Setup options
  */
-struct drive_info_struct { char dummy[32]; } drive_info;
 struct screen_info screen_info;
 
 extern int root_mountflags;
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index 5b7146f..679c1d5 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -35,74 +35,22 @@
 	unsigned long	GOT;
 };
 
-static int do_signal(sigset_t *oldset);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-	sigset_t saveset;
-
 	mask &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	__frame->gr8 = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset))
-			/* return the signal number as the return value of this function
-			 * - this is an utterly evil hack. syscalls should not invoke do_signal()
-			 *   as entry.S sets regs->gr8 to the return value of the system call
-			 * - we can't just use sigpending() as we'd have to discard SIG_IGN signals
-			 *   and call waitpid() if SIGCHLD needed discarding
-			 * - this only works on the i386 because it passes arguments to the signal
-			 *   handler on the stack, and the return value in EAX is effectively
-			 *   discarded
-			 */
-			return __frame->gr8;
-	}
-}
-
-asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
-{
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	__frame->gr8 = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset))
-			/* return the signal number as the return value of this function
-			 * - this is an utterly evil hack. syscalls should not invoke do_signal()
-			 *   as entry.S sets regs->gr8 to the return value of the system call
-			 * - we can't just use sigpending() as we'd have to discard SIG_IGN signals
-			 *   and call waitpid() if SIGCHLD needed discarding
-			 * - this only works on the i386 because it passes arguments to the signal
-			 *   handler on the stack, and the return value in EAX is effectively
-			 *   discarded
-			 */
-			return __frame->gr8;
-	}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
 }
 
 asmlinkage int sys_sigaction(int sig,
@@ -372,11 +320,11 @@
 	       frame->pretcode);
 #endif
 
-	return 1;
+	return 0;
 
 give_sigsegv:
 	force_sig(SIGSEGV, current);
-	return 0;
+	return -EFAULT;
 
 } /* end setup_frame() */
 
@@ -471,11 +419,11 @@
 	       frame->pretcode);
 #endif
 
-	return 1;
+	return 0;
 
 give_sigsegv:
 	force_sig(SIGSEGV, current);
-	return 0;
+	return -EFAULT;
 
 } /* end setup_rt_frame() */
 
@@ -516,7 +464,7 @@
 	else
 		ret = setup_frame(sig, ka, oldset);
 
-	if (ret) {
+	if (ret == 0) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked, &current->blocked,
 			  &ka->sa.sa_mask);
@@ -536,10 +484,11 @@
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-static int do_signal(sigset_t *oldset)
+static void do_signal(void)
 {
 	struct k_sigaction ka;
 	siginfo_t info;
+	sigset_t *oldset;
 	int signr;
 
 	/*
@@ -549,43 +498,62 @@
 	 * if so.
 	 */
 	if (!user_mode(__frame))
-		return 1;
+		return;
 
 	if (try_to_freeze())
 		goto no_signal;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
-	if (signr > 0)
-		return handle_signal(signr, &info, &ka, oldset);
+	if (signr > 0) {
+		if (handle_signal(signr, &info, &ka, oldset) == 0) {
+			/* a signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+
+		return;
+	}
 
 no_signal:
 	/* Did we come from a system call? */
 	if (__frame->syscallno >= 0) {
 		/* Restart the system call - no handlers present */
-		if (__frame->gr8 == -ERESTARTNOHAND ||
-		    __frame->gr8 == -ERESTARTSYS ||
-		    __frame->gr8 == -ERESTARTNOINTR) {
+		switch (__frame->gr8) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
 			__frame->gr8 = __frame->orig_gr8;
 			__frame->pc -= 4;
-		}
+			break;
 
-		if (__frame->gr8 == -ERESTART_RESTARTBLOCK){
+		case -ERESTART_RESTARTBLOCK:
 			__frame->gr8 = __NR_restart_syscall;
 			__frame->pc -= 4;
+			break;
 		}
 	}
 
-	return 0;
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 
 } /* end do_signal() */
 
 /*****************************************************************************/
 /*
  * notification of userspace execution resumption
- * - triggered by current->work.notify_resume
+ * - triggered by the TIF_WORK_MASK flags
  */
 asmlinkage void do_notify_resume(__u32 thread_info_flags)
 {
@@ -594,7 +562,7 @@
 		clear_thread_flag(TIF_SINGLESTEP);
 
 	/* deal with pending signal delivery */
-	if (thread_info_flags & _TIF_SIGPENDING)
-		do_signal(NULL);
+	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+		do_signal();
 
 } /* end do_notify_resume() */
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index cbde675..0afec85 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -47,15 +47,6 @@
 
 source "init/Kconfig"
 
-config DOUBLEFAULT
-	default y
-	bool "Enable doublefault exception handler" if EMBEDDED
-	help
-          This option allows trapping of rare doublefault exceptions that
-          would otherwise cause a system to silently reboot. Disabling this
-          option saves about 4k and might cause you much additional grey
-          hair.
-
 menu "Processor type and features"
 
 choice
@@ -451,12 +442,50 @@
 
 config HIGHMEM64G
 	bool "64GB"
+	depends on X86_CMPXCHG64
 	help
 	  Select this if you have a 32-bit processor and more than 4
 	  gigabytes of physical RAM.
 
 endchoice
 
+choice
+	depends on EXPERIMENTAL && !X86_PAE
+	prompt "Memory split"
+	default VMSPLIT_3G
+	help
+	  Select the desired split between kernel and user memory.
+
+	  If the address range available to the kernel is less than the
+	  physical memory installed, the remaining memory will be available
+	  as "high memory". Accessing high memory is a little more costly
+	  than low memory, as it needs to be mapped into the kernel first.
+	  Note that increasing the kernel address space limits the range
+	  available to user programs, making the address space there
+	  tighter.  Selecting anything other than the default 3G/1G split
+	  will also likely make your kernel incompatible with binary-only
+	  kernel modules.
+
+	  If you are not absolutely sure what you are doing, leave this
+	  option alone!
+
+	config VMSPLIT_3G
+		bool "3G/1G user/kernel split"
+	config VMSPLIT_3G_OPT
+		bool "3G/1G user/kernel split (for full 1G low memory)"
+	config VMSPLIT_2G
+		bool "2G/2G user/kernel split"
+	config VMSPLIT_1G
+		bool "1G/3G user/kernel split"
+endchoice
+
+config PAGE_OFFSET
+	hex
+	default 0xB0000000 if VMSPLIT_3G_OPT
+	default 0x78000000 if VMSPLIT_2G
+	default 0x40000000 if VMSPLIT_1G
+	default 0xC0000000
+
 config HIGHMEM
 	bool
 	depends on HIGHMEM64G || HIGHMEM4G
@@ -711,6 +740,15 @@
 
 	  Say N.
 
+config DOUBLEFAULT
+	default y
+	bool "Enable doublefault exception handler" if EMBEDDED
+	help
+          This option allows trapping of rare doublefault exceptions that
+          would otherwise cause a system to silently reboot. Disabling this
+          option saves about 4k and might cause you much additional grey
+          hair.
+
 endmenu
 
 
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 6a431b9..3cbe6e9 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -644,6 +644,8 @@
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
+# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/i386/kernel/acpi/Makefile b/arch/i386/kernel/acpi/Makefile
index 267ca48..d51c731 100644
--- a/arch/i386/kernel/acpi/Makefile
+++ b/arch/i386/kernel/acpi/Makefile
@@ -3,6 +3,6 @@
 obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup.o
 
 ifneq ($(CONFIG_ACPI_PROCESSOR),)
-obj-y				+= cstate.o
+obj-y				+= cstate.o processor.o
 endif
 
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 2111529..79577f0 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -248,10 +248,17 @@
 
 	acpi_table_print_madt_entry(header);
 
-	/* Register even disabled CPUs for cpu hotplug */
+	/* Record local apic id only when enabled */
+	if (processor->flags.enabled)
+		x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
 
-	x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
-
+	/*
+	 * We need to register disabled CPU as well to permit
+	 * counting disabled CPUs. This allows us to size
+	 * cpus_possible_map more accurately, to permit
+	 * to not preallocating memory for all NR_CPUS
+	 * when we use CPU hotplug.
+	 */
 	mp_register_lapic(processor->id,	/* APIC ID */
 			  processor->flags.enabled);	/* Enabled? */
 
@@ -464,7 +471,7 @@
  * success: return IRQ number (>=0)
  * failure: return < 0
  */
-int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
+int acpi_register_gsi(u32 gsi, int triggering, int polarity)
 {
 	unsigned int irq;
 	unsigned int plat_gsi = gsi;
@@ -476,14 +483,14 @@
 	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
 		extern void eisa_set_level_irq(unsigned int irq);
 
-		if (edge_level == ACPI_LEVEL_SENSITIVE)
+		if (triggering == ACPI_LEVEL_SENSITIVE)
 			eisa_set_level_irq(gsi);
 	}
 #endif
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
-		plat_gsi = mp_register_gsi(gsi, edge_level, active_high_low);
+		plat_gsi = mp_register_gsi(gsi, triggering, polarity);
 	}
 #endif
 	acpi_gsi_to_irq(plat_gsi, &irq);
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c
index 4c3036b..25db49e 100644
--- a/arch/i386/kernel/acpi/cstate.c
+++ b/arch/i386/kernel/acpi/cstate.c
@@ -14,64 +14,6 @@
 #include <acpi/processor.h>
 #include <asm/acpi.h>
 
-static void acpi_processor_power_init_intel_pdc(struct acpi_processor_power
-						*pow)
-{
-	struct acpi_object_list *obj_list;
-	union acpi_object *obj;
-	u32 *buf;
-
-	/* allocate and initialize pdc. It will be used later. */
-	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
-	if (!obj_list) {
-		printk(KERN_ERR "Memory allocation error\n");
-		return;
-	}
-
-	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-	if (!obj) {
-		printk(KERN_ERR "Memory allocation error\n");
-		kfree(obj_list);
-		return;
-	}
-
-	buf = kmalloc(12, GFP_KERNEL);
-	if (!buf) {
-		printk(KERN_ERR "Memory allocation error\n");
-		kfree(obj);
-		kfree(obj_list);
-		return;
-	}
-
-	buf[0] = ACPI_PDC_REVISION_ID;
-	buf[1] = 1;
-	buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
-
-	obj->type = ACPI_TYPE_BUFFER;
-	obj->buffer.length = 12;
-	obj->buffer.pointer = (u8 *) buf;
-	obj_list->count = 1;
-	obj_list->pointer = obj;
-	pow->pdc = obj_list;
-
-	return;
-}
-
-/* Initialize _PDC data based on the CPU vendor */
-void acpi_processor_power_init_pdc(struct acpi_processor_power *pow,
-				   unsigned int cpu)
-{
-	struct cpuinfo_x86 *c = cpu_data + cpu;
-
-	pow->pdc = NULL;
-	if (c->x86_vendor == X86_VENDOR_INTEL)
-		acpi_processor_power_init_intel_pdc(pow);
-
-	return;
-}
-
-EXPORT_SYMBOL(acpi_processor_power_init_pdc);
-
 /*
  * Initialize bm_flags based on the CPU cache properties
  * On SMP it depends on cache configuration
diff --git a/arch/i386/kernel/acpi/processor.c b/arch/i386/kernel/acpi/processor.c
new file mode 100644
index 0000000..9f4cc02
--- /dev/null
+++ b/arch/i386/kernel/acpi/processor.c
@@ -0,0 +1,75 @@
+/*
+ * arch/i386/kernel/acpi/processor.c
+ *
+ * Copyright (C) 2005 Intel Corporation
+ * 	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * 	- Added _PDC for platforms with Intel CPUs
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+
+#include <acpi/processor.h>
+#include <asm/acpi.h>
+
+static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
+{
+	struct acpi_object_list *obj_list;
+	union acpi_object *obj;
+	u32 *buf;
+
+	/* allocate and initialize pdc. It will be used later. */
+	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
+	if (!obj_list) {
+		printk(KERN_ERR "Memory allocation error\n");
+		return;
+	}
+
+	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+	if (!obj) {
+		printk(KERN_ERR "Memory allocation error\n");
+		kfree(obj_list);
+		return;
+	}
+
+	buf = kmalloc(12, GFP_KERNEL);
+	if (!buf) {
+		printk(KERN_ERR "Memory allocation error\n");
+		kfree(obj);
+		kfree(obj_list);
+		return;
+	}
+
+	buf[0] = ACPI_PDC_REVISION_ID;
+	buf[1] = 1;
+	buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
+
+	if (cpu_has(c, X86_FEATURE_EST))
+		buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
+
+	obj->type = ACPI_TYPE_BUFFER;
+	obj->buffer.length = 12;
+	obj->buffer.pointer = (u8 *) buf;
+	obj_list->count = 1;
+	obj_list->pointer = obj;
+	pr->pdc = obj_list;
+
+	return;
+}
+
+/* Initialize _PDC data based on the CPU vendor */
+void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
+{
+	unsigned int cpu = pr->id;
+	struct cpuinfo_x86 *c = cpu_data + cpu;
+
+	pr->pdc = NULL;
+	if (c->x86_vendor == X86_VENDOR_INTEL)
+		init_intel_pdc(pr, c);
+
+	return;
+}
+
+EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index acd3f1e..f39e09e 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -75,8 +75,10 @@
 	 * holds up an irq slot - in excessive cases (when multiple
 	 * unexpected vectors occur) that might lock up the APIC
 	 * completely.
+	 * But only ack when the APIC is enabled -AK
 	 */
-	ack_APIC_irq();
+	if (cpu_has_apic)
+		ack_APIC_irq();
 }
 
 void __init apic_intr_init(void)
@@ -1303,6 +1305,7 @@
 	if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
 		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
 			boot_cpu_physical_apicid);
+		clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
 		return -1;
 	}
 
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 333578a..0810f81 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -282,3 +282,11 @@
 }
 
 //early_arch_initcall(amd_init_cpu);
+
+static int __init amd_exit_cpu(void)
+{
+	cpu_devs[X86_VENDOR_AMD] = NULL;
+	return 0;
+}
+
+late_initcall(amd_exit_cpu);
diff --git a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c
index 394814e..f52669e 100644
--- a/arch/i386/kernel/cpu/centaur.c
+++ b/arch/i386/kernel/cpu/centaur.c
@@ -405,10 +405,6 @@
 				winchip2_protect_mcr();
 #endif
 				break;
-			case 10:
-				name="4";
-				/* no info on the WC4 yet */
-				break;
 			default:
 				name="??";
 			}
@@ -474,3 +470,11 @@
 }
 
 //early_arch_initcall(centaur_init_cpu);
+
+static int __init centaur_exit_cpu(void)
+{
+	cpu_devs[X86_VENDOR_CENTAUR] = NULL;
+	return 0;
+}
+
+late_initcall(centaur_exit_cpu);
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 15aee26..7eb9213 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -44,6 +44,7 @@
 
 static struct cpu_dev default_cpu = {
 	.c_init	= default_init,
+	.c_vendor = "Unknown",
 };
 static struct cpu_dev * this_cpu = &default_cpu;
 
@@ -150,6 +151,7 @@
 {
 	char *v = c->x86_vendor_id;
 	int i;
+	static int printed;
 
 	for (i = 0; i < X86_VENDOR_NUM; i++) {
 		if (cpu_devs[i]) {
@@ -159,10 +161,17 @@
 				c->x86_vendor = i;
 				if (!early)
 					this_cpu = cpu_devs[i];
-				break;
+				return;
 			}
 		}
 	}
+	if (!printed) {
+		printed++;
+		printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
+		printk(KERN_ERR "CPU: Your system may be unstable.\n");
+	}
+	c->x86_vendor = X86_VENDOR_UNKNOWN;
+	this_cpu = &default_cpu;
 }
 
 
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 7975e79..3852d0a 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -295,68 +295,6 @@
 }
 
 
-/* 
- * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities
- * of this driver
- * @perf: processor-specific acpi_io_data struct
- * @cpu: CPU being initialized
- *
- * To avoid issues with legacy OSes, some BIOSes require to be informed of
- * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC 
- * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in
- * driver/acpi/processor.c
- */
-static void 
-acpi_processor_cpu_init_pdc_est(
-		struct acpi_processor_performance *perf, 
-		unsigned int cpu,
-		struct acpi_object_list *obj_list
-		)
-{
-	union acpi_object *obj;
-	u32 *buf;
-	struct cpuinfo_x86 *c = cpu_data + cpu;
-	dprintk("acpi_processor_cpu_init_pdc_est\n");
-
-	if (!cpu_has(c, X86_FEATURE_EST))
-		return;
-
-	/* Initialize pdc. It will be used later. */
-	if (!obj_list)
-		return;
-		
-	if (!(obj_list->count && obj_list->pointer))
-		return;
-
-	obj = obj_list->pointer;
-	if ((obj->buffer.length == 12) && obj->buffer.pointer) {
-		buf = (u32 *)obj->buffer.pointer;
-       		buf[0] = ACPI_PDC_REVISION_ID;
-       		buf[1] = 1;
-       		buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
-		perf->pdc = obj_list;
-	}
-	return;
-}
- 
-
-/* CPU specific PDC initialization */
-static void 
-acpi_processor_cpu_init_pdc(
-		struct acpi_processor_performance *perf, 
-		unsigned int cpu,
-		struct acpi_object_list *obj_list
-		)
-{
-	struct cpuinfo_x86 *c = cpu_data + cpu;
-	dprintk("acpi_processor_cpu_init_pdc\n");
-	perf->pdc = NULL;
-	if (cpu_has(c, X86_FEATURE_EST))
-		acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list);
-	return;
-}
-
-
 static int
 acpi_cpufreq_cpu_init (
 	struct cpufreq_policy   *policy)
@@ -367,14 +305,7 @@
 	unsigned int		result = 0;
 	struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
 
-	union acpi_object		arg0 = {ACPI_TYPE_BUFFER};
-	u32				arg0_buf[3];
-	struct acpi_object_list 	arg_list = {1, &arg0};
-
 	dprintk("acpi_cpufreq_cpu_init\n");
-	/* setup arg_list for _PDC settings */
-        arg0.buffer.length = 12;
-        arg0.buffer.pointer = (u8 *) arg0_buf;
 
 	data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
 	if (!data)
@@ -382,9 +313,7 @@
 
 	acpi_io_data[cpu] = data;
 
-	acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list);
 	result = acpi_processor_register_performance(&data->acpi_data, cpu);
-	data->acpi_data.pdc = NULL;
 
 	if (result)
 		goto err_free;
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 9a826cd..c173c0f 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -362,22 +362,10 @@
  */
 static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
 {
-	union acpi_object		arg0 = {ACPI_TYPE_BUFFER};
-	u32				arg0_buf[3];
-	struct acpi_object_list		arg_list = {1, &arg0};
 	unsigned long			cur_freq;
 	int				result = 0, i;
 	unsigned int			cpu = policy->cpu;
 
-	/* _PDC settings */
-	arg0.buffer.length = 12;
-	arg0.buffer.pointer = (u8 *) arg0_buf;
-	arg0_buf[0] = ACPI_PDC_REVISION_ID;
-	arg0_buf[1] = 1;
-	arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP_MSR;
-
-	p.pdc = &arg_list;
-
 	/* register with ACPI core */
 	if (acpi_processor_register_performance(&p, cpu)) {
 		dprintk(KERN_INFO PFX "obtaining ACPI data failed\n");
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index 7501597..00f2e05 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -345,7 +345,7 @@
 /*
  * Handle National Semiconductor branded processors
  */
-static void __devinit init_nsc(struct cpuinfo_x86 *c)
+static void __init init_nsc(struct cpuinfo_x86 *c)
 {
 	/* There may be GX1 processors in the wild that are branded
 	 * NSC and not Cyrix.
@@ -444,6 +444,14 @@
 
 //early_arch_initcall(cyrix_init_cpu);
 
+static int __init cyrix_exit_cpu(void)
+{
+	cpu_devs[X86_VENDOR_CYRIX] = NULL;
+	return 0;
+}
+
+late_initcall(cyrix_exit_cpu);
+
 static struct cpu_dev nsc_cpu_dev __initdata = {
 	.c_vendor	= "NSC",
 	.c_ident 	= { "Geode by NSC" },
@@ -458,3 +466,11 @@
 }
 
 //early_arch_initcall(nsc_init_cpu);
+
+static int __init nsc_exit_cpu(void)
+{
+	cpu_devs[X86_VENDOR_NSC] = NULL;
+	return 0;
+}
+
+late_initcall(nsc_exit_cpu);
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index fbfd374..ffe58ce 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -43,13 +43,23 @@
 	{ 0x2c, LVL_1_DATA, 32 },	/* 8-way set assoc, 64 byte line size */
 	{ 0x30, LVL_1_INST, 32 },	/* 8-way set assoc, 64 byte line size */
 	{ 0x39, LVL_2,      128 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x3a, LVL_2,      192 },	/* 6-way set assoc, sectored cache, 64 byte line size */
 	{ 0x3b, LVL_2,      128 },	/* 2-way set assoc, sectored cache, 64 byte line size */
 	{ 0x3c, LVL_2,      256 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x3d, LVL_2,      384 },	/* 6-way set assoc, sectored cache, 64 byte line size */
+	{ 0x3e, LVL_2,      512 },	/* 4-way set assoc, sectored cache, 64 byte line size */
 	{ 0x41, LVL_2,      128 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x42, LVL_2,      256 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x43, LVL_2,      512 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x44, LVL_2,      1024 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x45, LVL_2,      2048 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x46, LVL_3,      4096 },	/* 4-way set assoc, 64 byte line size */
+	{ 0x47, LVL_3,      8192 },	/* 8-way set assoc, 64 byte line size */
+	{ 0x49, LVL_3,      4096 },	/* 16-way set assoc, 64 byte line size */
+	{ 0x4a, LVL_3,      6144 },	/* 12-way set assoc, 64 byte line size */
+	{ 0x4b, LVL_3,      8192 },	/* 16-way set assoc, 64 byte line size */
+	{ 0x4c, LVL_3,     12288 },	/* 12-way set assoc, 64 byte line size */
+	{ 0x4d, LVL_3,     16384 },	/* 16-way set assoc, 64 byte line size */
 	{ 0x60, LVL_1_DATA, 16 },	/* 8-way set assoc, sectored cache, 64 byte line size */
 	{ 0x66, LVL_1_DATA, 8 },	/* 4-way set assoc, sectored cache, 64 byte line size */
 	{ 0x67, LVL_1_DATA, 16 },	/* 4-way set assoc, sectored cache, 64 byte line size */
@@ -57,6 +67,7 @@
 	{ 0x70, LVL_TRACE,  12 },	/* 8-way set assoc */
 	{ 0x71, LVL_TRACE,  16 },	/* 8-way set assoc */
 	{ 0x72, LVL_TRACE,  32 },	/* 8-way set assoc */
+	{ 0x73, LVL_TRACE,  64 },	/* 8-way set assoc */
 	{ 0x78, LVL_2,    1024 },	/* 4-way set assoc, 64 byte line size */
 	{ 0x79, LVL_2,     128 },	/* 8-way set assoc, sectored cache, 64 byte line size */
 	{ 0x7a, LVL_2,     256 },	/* 8-way set assoc, sectored cache, 64 byte line size */
@@ -141,6 +152,7 @@
 	return 0;
 }
 
+/* will only be called once; __init is safe here */
 static int __init find_num_cache_leaves(void)
 {
 	unsigned int		eax, ebx, ecx, edx;
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index 1e9db19..3b4618b 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -44,12 +44,10 @@
 #include <asm/msr.h>
 #include "mtrr.h"
 
-#define MTRR_VERSION            "2.0 (20020519)"
-
 u32 num_var_ranges = 0;
 
 unsigned int *usage_table;
-static DECLARE_MUTEX(main_lock);
+static DECLARE_MUTEX(mtrr_sem);
 
 u32 size_or_mask, size_and_mask;
 
@@ -335,7 +333,7 @@
 	/* No CPU hotplug when we change MTRR entries */
 	lock_cpu_hotplug();
 	/*  Search for existing MTRR  */
-	down(&main_lock);
+	down(&mtrr_sem);
 	for (i = 0; i < num_var_ranges; ++i) {
 		mtrr_if->get(i, &lbase, &lsize, &ltype);
 		if (base >= lbase + lsize)
@@ -373,7 +371,7 @@
 		printk(KERN_INFO "mtrr: no more MTRRs available\n");
 	error = i;
  out:
-	up(&main_lock);
+	up(&mtrr_sem);
 	unlock_cpu_hotplug();
 	return error;
 }
@@ -466,7 +464,7 @@
 	max = num_var_ranges;
 	/* No CPU hotplug when we change MTRR entries */
 	lock_cpu_hotplug();
-	down(&main_lock);
+	down(&mtrr_sem);
 	if (reg < 0) {
 		/*  Search for existing MTRR  */
 		for (i = 0; i < max; ++i) {
@@ -505,7 +503,7 @@
 		set_mtrr(reg, 0, 0, 0);
 	error = reg;
  out:
-	up(&main_lock);
+	up(&mtrr_sem);
 	unlock_cpu_hotplug();
 	return error;
 }
@@ -671,7 +669,6 @@
 			break;
 		}
 	}
-	printk(KERN_INFO "mtrr: v%s\n",MTRR_VERSION);
 
 	if (mtrr_if) {
 		set_num_var_ranges();
@@ -688,7 +685,7 @@
 	if (!mtrr_if || !use_intel())
 		return;
 	/*
-	 * Ideally we should hold main_lock here to avoid mtrr entries changed,
+	 * Ideally we should hold mtrr_sem here to avoid mtrr entries changed,
 	 * but this routine will be called in cpu boot time, holding the lock
 	 * breaks it. This routine is called in two cases: 1.very earily time
 	 * of software resume, when there absolutely isn't mtrr entry changes;
diff --git a/arch/i386/kernel/cpu/nexgen.c b/arch/i386/kernel/cpu/nexgen.c
index 30898a2..ad87fa5 100644
--- a/arch/i386/kernel/cpu/nexgen.c
+++ b/arch/i386/kernel/cpu/nexgen.c
@@ -61,3 +61,11 @@
 }
 
 //early_arch_initcall(nexgen_init_cpu);
+
+static int __init nexgen_exit_cpu(void)
+{
+	cpu_devs[X86_VENDOR_NEXGEN] = NULL;
+	return 0;
+}
+
+late_initcall(nexgen_exit_cpu);
diff --git a/arch/i386/kernel/cpu/rise.c b/arch/i386/kernel/cpu/rise.c
index 8602425..d08d5a2 100644
--- a/arch/i386/kernel/cpu/rise.c
+++ b/arch/i386/kernel/cpu/rise.c
@@ -51,3 +51,11 @@
 }
 
 //early_arch_initcall(rise_init_cpu);
+
+static int __init rise_exit_cpu(void)
+{
+	cpu_devs[X86_VENDOR_RISE] = NULL;
+	return 0;
+}
+
+late_initcall(rise_exit_cpu);
diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c
index fc42638..bdbeb77 100644
--- a/arch/i386/kernel/cpu/transmeta.c
+++ b/arch/i386/kernel/cpu/transmeta.c
@@ -84,7 +84,7 @@
 #endif
 }
 
-static void transmeta_identify(struct cpuinfo_x86 * c)
+static void __init transmeta_identify(struct cpuinfo_x86 * c)
 {
 	u32 xlvl;
 	generic_identify(c);
@@ -111,3 +111,11 @@
 }
 
 //early_arch_initcall(transmeta_init_cpu);
+
+static int __init transmeta_exit_cpu(void)
+{
+	cpu_devs[X86_VENDOR_TRANSMETA] = NULL;
+	return 0;
+}
+
+late_initcall(transmeta_exit_cpu);
diff --git a/arch/i386/kernel/cpu/umc.c b/arch/i386/kernel/cpu/umc.c
index 264fcad..2cd988f 100644
--- a/arch/i386/kernel/cpu/umc.c
+++ b/arch/i386/kernel/cpu/umc.c
@@ -31,3 +31,11 @@
 }
 
 //early_arch_initcall(umc_init_cpu);
+
+static int __init umc_exit_cpu(void)
+{
+	cpu_devs[X86_VENDOR_UMC] = NULL;
+	return 0;
+}
+
+late_initcall(umc_exit_cpu);
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index 5884469..2bee649 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -398,7 +398,11 @@
 	pushl 32(%esp)
 	pushl 40(%esp)
 	pushl $int_msg
+#ifdef CONFIG_EARLY_PRINTK
+	call early_printk
+#else
 	call printk
+#endif
 	addl $(5*4),%esp
 	popl %ds
 	popl %es
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 91a6401..0102f3d 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -1080,7 +1080,7 @@
 
 #define MAX_GSI_NUM	4096
 
-int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
+int mp_register_gsi (u32 gsi, int triggering, int polarity)
 {
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
@@ -1129,7 +1129,7 @@
 
 	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 
-	if (edge_level) {
+	if (triggering == ACPI_LEVEL_SENSITIVE) {
 		/*
 		 * For PCI devices assign IRQs in order, avoiding gaps
 		 * due to unused I/O APIC pins.
@@ -1151,8 +1151,8 @@
 	}
 
 	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
-		    edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
-		    active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
+		    triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+		    polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
 	return gsi;
 }
 
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index d661703..63f39a7 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -138,7 +138,7 @@
 	if (nmi_watchdog == NMI_LOCAL_APIC)
 		smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++)
+	for_each_cpu(cpu)
 		prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count;
 	local_irq_enable();
 	mdelay((10*1000)/nmi_hz); // wait 10 ticks
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 2185377..0480454 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -297,8 +297,10 @@
 
 	if (user_mode(regs))
 		printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
-	printk(" EFLAGS: %08lx    %s  (%s)\n",
-	       regs->eflags, print_tainted(), system_utsname.release);
+	printk(" EFLAGS: %08lx    %s  (%s %.*s)\n",
+	       regs->eflags, print_tainted(), system_utsname.release,
+	       (int)strcspn(system_utsname.version, " "),
+	       system_utsname.version);
 	printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
 		regs->eax,regs->ebx,regs->ecx,regs->edx);
 	printk("ESI: %08lx EDI: %08lx EBP: %08lx",
diff --git a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c
index aaf89cb..87ccdac 100644
--- a/arch/i386/kernel/quirks.c
+++ b/arch/i386/kernel/quirks.c
@@ -25,8 +25,7 @@
 
 	/* enable access to config space*/
 	pci_read_config_byte(dev, 0xf4, &config);
-	config |= 0x2;
-	pci_write_config_byte(dev, 0xf4, config);
+	pci_write_config_byte(dev, 0xf4, config|0x2);
 
 	/* read xTPR register */
 	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
@@ -42,9 +41,9 @@
 #endif
 	}
 
-	config &= ~0x2;
-	/* disable access to config space*/
-	pci_write_config_byte(dev, 0xf4, config);
+	/* put back the original value for config space*/
+	if (!(config & 0x2))
+		pci_write_config_byte(dev, 0xf4, config);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_intel_irqbalance);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quirk_intel_irqbalance);
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index adcd069..963616d 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -37,51 +37,17 @@
 asmlinkage int
 sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-	struct pt_regs * regs = (struct pt_regs *) &history0;
-	sigset_t saveset;
-
 	mask &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs->eax = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(regs, &saveset))
-			return -EINTR;
-	}
-}
-
-asmlinkage int
-sys_rt_sigsuspend(struct pt_regs regs)
-{
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (regs.ecx != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, (sigset_t __user *)regs.ebx, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs.eax = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&regs, &saveset))
-			return -EINTR;
-	}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
 }
 
 asmlinkage int 
@@ -433,11 +399,11 @@
 		current->comm, current->pid, frame, regs->eip, frame->pretcode);
 #endif
 
-	return 1;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
-	return 0;
+	return -EFAULT;
 }
 
 static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -527,11 +493,11 @@
 		current->comm, current->pid, frame, regs->eip, frame->pretcode);
 #endif
 
-	return 1;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
-	return 0;
+	return -EFAULT;
 }
 
 /*
@@ -581,7 +547,7 @@
 	else
 		ret = setup_frame(sig, ka, oldset, regs);
 
-	if (ret) {
+	if (ret == 0) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		if (!(ka->sa.sa_flags & SA_NODEFER))
@@ -598,11 +564,12 @@
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void fastcall do_signal(struct pt_regs *regs)
 {
 	siginfo_t info;
 	int signr;
 	struct k_sigaction ka;
+	sigset_t *oldset;
 
 	/*
 	 * We want the common case to go fast, which
@@ -613,12 +580,14 @@
  	 * CS suffices.
 	 */
 	if (!user_mode(regs))
-		return 1;
+		return;
 
 	if (try_to_freeze())
 		goto no_signal;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -628,38 +597,55 @@
 		 * have been cleared if the watchpoint triggered
 		 * inside the kernel.
 		 */
-		if (unlikely(current->thread.debugreg[7])) {
+		if (unlikely(current->thread.debugreg[7]))
 			set_debugreg(current->thread.debugreg[7], 7);
-		}
 
 		/* Whee!  Actually deliver the signal.  */
-		return handle_signal(signr, &info, &ka, oldset, regs);
+		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+			/* a signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+
+		return;
 	}
 
- no_signal:
+no_signal:
 	/* Did we come from a system call? */
 	if (regs->orig_eax >= 0) {
 		/* Restart the system call - no handlers present */
-		if (regs->eax == -ERESTARTNOHAND ||
-		    regs->eax == -ERESTARTSYS ||
-		    regs->eax == -ERESTARTNOINTR) {
+		switch (regs->eax) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
 			regs->eax = regs->orig_eax;
 			regs->eip -= 2;
-		}
-		if (regs->eax == -ERESTART_RESTARTBLOCK){
+			break;
+
+		case -ERESTART_RESTARTBLOCK:
 			regs->eax = __NR_restart_syscall;
 			regs->eip -= 2;
+			break;
 		}
 	}
-	return 0;
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
 
 /*
  * notification of userspace execution resumption
- * - triggered by current->work.notify_resume
+ * - triggered by the TIF_WORK_MASK flags
  */
 __attribute__((regparm(3)))
-void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
+void do_notify_resume(struct pt_regs *regs, void *_unused,
 		      __u32 thread_info_flags)
 {
 	/* Pending single-step? */
@@ -667,9 +653,10 @@
 		regs->eflags |= TF_MASK;
 		clear_thread_flag(TIF_SINGLESTEP);
 	}
+
 	/* deal with pending signal delivery */
-	if (thread_info_flags & _TIF_SIGPENDING)
-		do_signal(regs,oldset);
+	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+		do_signal(regs);
 	
 	clear_thread_flag(TIF_IRET);
 }
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 255adb4..fb00ab7 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -87,11 +87,7 @@
 cpumask_t cpu_callin_map;
 cpumask_t cpu_callout_map;
 EXPORT_SYMBOL(cpu_callout_map);
-#ifdef CONFIG_HOTPLUG_CPU
-cpumask_t cpu_possible_map = CPU_MASK_ALL;
-#else
 cpumask_t cpu_possible_map;
-#endif
 EXPORT_SYMBOL(cpu_possible_map);
 static cpumask_t smp_commenced_mask;
 
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 6ff3e52..ac687d0 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -294,3 +294,19 @@
 	.long sys_inotify_add_watch
 	.long sys_inotify_rm_watch
 	.long sys_migrate_pages
+	.long sys_openat		/* 295 */
+	.long sys_mkdirat
+	.long sys_mknodat
+	.long sys_fchownat
+	.long sys_futimesat
+	.long sys_fstatat64		/* 300 */
+	.long sys_unlinkat
+	.long sys_renameat
+	.long sys_linkat
+	.long sys_symlinkat
+	.long sys_readlinkat		/* 305 */
+	.long sys_fchmodat
+	.long sys_faccessat
+	.long sys_pselect6
+	.long sys_ppoll
+	.long sys_unshare		/* 310 */
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 591a642..a7f5a2a 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -45,6 +45,15 @@
 static unsigned long long monotonic_base;
 static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
 
+/* Avoid compensating for lost ticks before TSCs are synched */
+static int detect_lost_ticks;
+static int __init start_lost_tick_compensation(void)
+{
+	detect_lost_ticks = 1;
+	return 0;
+}
+late_initcall(start_lost_tick_compensation);
+
 /* convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
  *		ns = cycles / (freq / ns_per_sec)
@@ -196,7 +205,8 @@
 
 	/* lost tick compensation */
 	offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
-	if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) {
+	if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))
+					&& detect_lost_ticks) {
 		int lost_ticks = (offset - hpet_last) / hpet_tick;
 		jiffies_64 += lost_ticks;
 	}
@@ -426,7 +436,7 @@
 	delta += delay_at_last_interrupt;
 	lost = delta/(1000000/HZ);
 	delay = delta%(1000000/HZ);
-	if (lost >= 2) {
+	if (lost >= 2 && detect_lost_ticks) {
 		jiffies_64 += lost-1;
 
 		/* sanity check to ensure we're not always losing ticks */
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 0aaebf3..b814dbd 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -166,7 +166,8 @@
 		stack = (unsigned long*)context->previous_esp;
 		if (!stack)
 			break;
-		printk(KERN_EMERG " =======================\n");
+		printk(log_lvl);
+		printk(" =======================\n");
 	}
 }
 
@@ -239,9 +240,11 @@
 	}
 	print_modules();
 	printk(KERN_EMERG "CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\n"
-			"EFLAGS: %08lx   (%s) \n",
+			"EFLAGS: %08lx   (%s %.*s) \n",
 		smp_processor_id(), 0xffff & regs->xcs, regs->eip,
-		print_tainted(), regs->eflags, system_utsname.release);
+		print_tainted(), regs->eflags, system_utsname.release,
+		(int)strcspn(system_utsname.version, " "),
+		system_utsname.version);
 	print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip);
 	printk(KERN_EMERG "eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
 		regs->eax, regs->ebx, regs->ecx, regs->edx);
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 72a1b9c..6e4c3ba 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -240,7 +240,7 @@
 cpumask_t cpu_callin_map = CPU_MASK_NONE;
 cpumask_t cpu_callout_map = CPU_MASK_NONE;
 EXPORT_SYMBOL(cpu_callout_map);
-cpumask_t cpu_possible_map = CPU_MASK_ALL;
+cpumask_t cpu_possible_map = CPU_MASK_NONE;
 EXPORT_SYMBOL(cpu_possible_map);
 
 /* The per processor IRQ masks (these are usually kept in sync) */
diff --git a/arch/i386/oprofile/backtrace.c b/arch/i386/oprofile/backtrace.c
index 21654be..acc1813 100644
--- a/arch/i386/oprofile/backtrace.c
+++ b/arch/i386/oprofile/backtrace.c
@@ -49,7 +49,9 @@
  * |    stack    |
  * --------------- saved regs->ebp value if valid (frame_head address)
  * .             .
- * --------------- struct pt_regs stored on stack (struct pt_regs *)
+ * --------------- saved regs->rsp value if x86_64
+ * |             |
+ * --------------- struct pt_regs * stored on stack if 32-bit
  * |             |
  * .             .
  * |             |
@@ -57,13 +59,26 @@
  * |             |
  * |             | \/ Lower addresses
  *
- * Thus, &pt_regs <-> stack base restricts the valid(ish) ebp values
+ * Thus, regs (or regs->rsp for x86_64) <-> stack base restricts the
+ * valid(ish) ebp values. Note: (1) for x86_64, NMI and several other
+ * exceptions use special stacks, maintained by the interrupt stack table
+ * (IST). These stacks are set up in trap_init() in
+ * arch/x86_64/kernel/traps.c. Thus, for x86_64, regs now does not point
+ * to the kernel stack; instead, it points to some location on the NMI
+ * stack. On the other hand, regs->rsp is the stack pointer saved when the
+ * NMI occurred. (2) For 32-bit, regs->esp is not valid because the
+ * processor does not save %esp on the kernel stack when interrupts occur
+ * in the kernel mode.
  */
 #ifdef CONFIG_FRAME_POINTER
 static int valid_kernel_stack(struct frame_head * head, struct pt_regs * regs)
 {
 	unsigned long headaddr = (unsigned long)head;
+#ifdef CONFIG_X86_64
+	unsigned long stack = (unsigned long)regs->rsp;
+#else
 	unsigned long stack = (unsigned long)regs;
+#endif
 	unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;
 
 	return headaddr > stack && headaddr < stack_base;
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index e715aa9..3ca59ca 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -539,6 +539,11 @@
 		case PCI_DEVICE_ID_INTEL_ICH7_30:
 		case PCI_DEVICE_ID_INTEL_ICH7_31:
 		case PCI_DEVICE_ID_INTEL_ESB2_0:
+		case PCI_DEVICE_ID_INTEL_ICH8_0:
+		case PCI_DEVICE_ID_INTEL_ICH8_1:
+		case PCI_DEVICE_ID_INTEL_ICH8_2:
+		case PCI_DEVICE_ID_INTEL_ICH8_3:
+		case PCI_DEVICE_ID_INTEL_ICH8_4:
 			r->name = "PIIX/ICH";
 			r->get = pirq_piix_get;
 			r->set = pirq_piix_set;
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 4bb4d4b..0ee8a98 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -36,8 +36,7 @@
 	while (1) {
 		++cfg_num;
 		if (cfg_num >= pci_mmcfg_config_num) {
-			/* Not found - fallback to type 1 */
-			return 0;
+			break;
 		}
 		cfg = &pci_mmcfg_config[cfg_num];
 		if (cfg->pci_segment_group_number != seg)
@@ -46,6 +45,18 @@
 		    (cfg->end_bus_number >= bus))
 			return cfg->base_address;
 	}
+
+	/* Handle more broken MCFG tables on Asus etc.
+	   They only contain a single entry for bus 0-0. Assume
+ 	   this applies to all busses. */
+	cfg = &pci_mmcfg_config[0];
+	if (pci_mmcfg_config_num == 1 &&
+		cfg->pci_segment_group_number == 0 &&
+		(cfg->start_bus_number | cfg->end_bus_number) == 0)
+		return cfg->base_address;
+
+	/* Fall back to type 0 */
+	return 0;
 }
 
 static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 199eeaf..845cd09 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -194,7 +194,6 @@
 	default "7" if MCKINLEY
 	default "6" if ITANIUM
 
-# align cache-sensitive data to 64 bytes
 config IA64_CYCLONE
 	bool "Cyclone (EXA) Time Source support"
 	help
@@ -374,6 +373,9 @@
 	  To use this option, you have to ensure that the "/proc file system
 	  support" (CONFIG_PROC_FS) is enabled, too.
 
+config SGI_SN
+	def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
+
 source "drivers/firmware/Kconfig"
 
 source "fs/Kconfig.binfmt"
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index 1d07d80..991c07b 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -557,6 +557,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index b1e8f09..6859119 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -565,6 +565,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index 0856ca6..53899dc 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -548,6 +548,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 275a26c..dcbc78a 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -565,6 +565,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/ia64/dig/setup.c b/arch/ia64/dig/setup.c
index d58003f..c9104bf 100644
--- a/arch/ia64/dig/setup.c
+++ b/arch/ia64/dig/setup.c
@@ -25,16 +25,6 @@
 #include <asm/machvec.h>
 #include <asm/system.h>
 
-/*
- * This is here so we can use the CMOS detection in ide-probe.c to
- * determine what drives are present.  In theory, we don't need this
- * as the auto-detection could be done via ide-probe.c:do_probe() but
- * in practice that would be much slower, which is painful when
- * running in the simulator.  Note that passing zeroes in DRIVE_INFO
- * is sufficient (the IDE driver will autodetect the drive geometry).
- */
-char drive_info[4*16];
-
 void __init
 dig_setup (char **cmdline_p)
 {
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index 5856510..b3355a9 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -515,6 +515,7 @@
 
 	sigact_set_handler(&new_sa, handler, 0);
 	new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;
+	sigemptyset(&new_sa.sa.sa_mask);
 
 	ret = do_sigaction(sig, &new_sa, &old_sa);
 
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 3945d37..70dba1f 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -52,9 +52,9 @@
 #include <linux/compat.h>
 #include <linux/vfs.h>
 #include <linux/mman.h>
+#include <linux/mutex.h>
 
 #include <asm/intrinsics.h>
-#include <asm/semaphore.h>
 #include <asm/types.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -86,7 +86,7 @@
  * while doing so.
  */
 /* XXX make per-mm: */
-static DECLARE_MUTEX(ia32_mmap_sem);
+static DEFINE_MUTEX(ia32_mmap_mutex);
 
 asmlinkage long
 sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp,
@@ -895,11 +895,11 @@
 	prot = get_prot32(prot);
 
 #if PAGE_SHIFT > IA32_PAGE_SHIFT
-	down(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
 	{
 		addr = emulate_mmap(file, addr, len, prot, flags, offset);
 	}
-	up(&ia32_mmap_sem);
+	mutex_unlock(&ia32_mmap_mutex);
 #else
 	down_write(&current->mm->mmap_sem);
 	{
@@ -1000,11 +1000,9 @@
 	if (start >= end)
 		return 0;
 
-	down(&ia32_mmap_sem);
-	{
-		ret = sys_munmap(start, end - start);
-	}
-	up(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
+	ret = sys_munmap(start, end - start);
+	mutex_unlock(&ia32_mmap_mutex);
 #endif
 	return ret;
 }
@@ -1056,7 +1054,7 @@
 	if (retval < 0)
 		return retval;
 
-	down(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
 	{
 		if (offset_in_page(start)) {
 			/* start address is 4KB aligned but not page aligned. */
@@ -1080,7 +1078,7 @@
 		retval = sys_mprotect(start, end - start, prot);
 	}
   out:
-	up(&ia32_mmap_sem);
+	mutex_unlock(&ia32_mmap_mutex);
 	return retval;
 #endif
 }
@@ -1124,11 +1122,9 @@
 	old_len = PAGE_ALIGN(old_end) - addr;
 	new_len = PAGE_ALIGN(new_end) - addr;
 
-	down(&ia32_mmap_sem);
-	{
-		ret = sys_mremap(addr, old_len, new_len, flags, new_addr);
-	}
-	up(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
+	ret = sys_mremap(addr, old_len, new_len, flags, new_addr);
+	mutex_unlock(&ia32_mmap_mutex);
 
 	if ((ret >= 0) && (old_len < new_len)) {
 		/* mremap expanded successfully */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 307514f..09a0dbc 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -13,6 +13,11 @@
 obj-$(CONFIG_IA64_GENERIC)	+= acpi-ext.o
 obj-$(CONFIG_IA64_HP_ZX1)	+= acpi-ext.o
 obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o
+
+ifneq ($(CONFIG_ACPI_PROCESSOR),)
+obj-y				+= acpi-processor.o
+endif
+
 obj-$(CONFIG_IA64_PALINFO)	+= palinfo.o
 obj-$(CONFIG_IOSAPIC)		+= iosapic.o
 obj-$(CONFIG_MODULES)		+= module.o
diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
index 13a5b3b..4a5574f 100644
--- a/arch/ia64/kernel/acpi-ext.c
+++ b/arch/ia64/kernel/acpi-ext.c
@@ -33,33 +33,33 @@
 	struct acpi_vendor_info *info = (struct acpi_vendor_info *)context;
 	struct acpi_resource_vendor *vendor;
 	struct acpi_vendor_descriptor *descriptor;
-	u32 length;
+	u32 byte_length;
 
-	if (resource->id != ACPI_RSTYPE_VENDOR)
+	if (resource->type != ACPI_RESOURCE_TYPE_VENDOR)
 		return AE_OK;
 
 	vendor = (struct acpi_resource_vendor *)&resource->data;
-	descriptor = (struct acpi_vendor_descriptor *)vendor->reserved;
-	if (vendor->length <= sizeof(*info->descriptor) ||
+	descriptor = (struct acpi_vendor_descriptor *)vendor->byte_data;
+	if (vendor->byte_length <= sizeof(*info->descriptor) ||
 	    descriptor->guid_id != info->descriptor->guid_id ||
 	    efi_guidcmp(descriptor->guid, info->descriptor->guid))
 		return AE_OK;
 
-	length = vendor->length - sizeof(struct acpi_vendor_descriptor);
-	info->data = acpi_os_allocate(length);
+	byte_length = vendor->byte_length - sizeof(struct acpi_vendor_descriptor);
+	info->data = acpi_os_allocate(byte_length);
 	if (!info->data)
 		return AE_NO_MEMORY;
 
 	memcpy(info->data,
-	       vendor->reserved + sizeof(struct acpi_vendor_descriptor),
-	       length);
-	info->length = length;
+	       vendor->byte_data + sizeof(struct acpi_vendor_descriptor),
+	       byte_length);
+	info->length = byte_length;
 	return AE_CTRL_TERMINATE;
 }
 
 acpi_status
 acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor * id,
-			  u8 ** data, u32 * length)
+			  u8 ** data, u32 * byte_length)
 {
 	struct acpi_vendor_info info;
 
@@ -72,7 +72,7 @@
 		return AE_NOT_FOUND;
 
 	*data = info.data;
-	*length = info.length;
+	*byte_length = info.length;
 	return AE_OK;
 }
 
diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c
new file mode 100644
index 0000000..e683630
--- /dev/null
+++ b/arch/ia64/kernel/acpi-processor.c
@@ -0,0 +1,67 @@
+/*
+ * arch/ia64/kernel/cpufreq/processor.c
+ *
+ * Copyright (C) 2005 Intel Corporation
+ * 	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * 	- Added _PDC for platforms with Intel CPUs
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+
+#include <acpi/processor.h>
+#include <asm/acpi.h>
+
+static void init_intel_pdc(struct acpi_processor *pr)
+{
+	struct acpi_object_list *obj_list;
+	union acpi_object *obj;
+	u32 *buf;
+
+	/* allocate and initialize pdc. It will be used later. */
+	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
+	if (!obj_list) {
+		printk(KERN_ERR "Memory allocation error\n");
+		return;
+	}
+
+	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+	if (!obj) {
+		printk(KERN_ERR "Memory allocation error\n");
+		kfree(obj_list);
+		return;
+	}
+
+	buf = kmalloc(12, GFP_KERNEL);
+	if (!buf) {
+		printk(KERN_ERR "Memory allocation error\n");
+		kfree(obj);
+		kfree(obj_list);
+		return;
+	}
+
+	buf[0] = ACPI_PDC_REVISION_ID;
+	buf[1] = 1;
+	buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
+
+	obj->type = ACPI_TYPE_BUFFER;
+	obj->buffer.length = 12;
+	obj->buffer.pointer = (u8 *) buf;
+	obj_list->count = 1;
+	obj_list->pointer = obj;
+	pr->pdc = obj_list;
+
+	return;
+}
+
+/* Initialize _PDC data based on the CPU vendor */
+void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
+{
+	pr->pdc = NULL;
+	init_intel_pdc(pr);
+	return;
+}
+
+EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 9ad94dd..d2702c4 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -567,16 +567,16 @@
  * success: return IRQ number (>=0)
  * failure: return < 0
  */
-int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
+int acpi_register_gsi(u32 gsi, int triggering, int polarity)
 {
 	if (has_8259 && gsi < 16)
 		return isa_irq_to_vector(gsi);
 
 	return iosapic_register_intr(gsi,
-				     (active_high_low ==
+				     (polarity ==
 				      ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH :
 				     IOSAPIC_POL_LOW,
-				     (edge_level ==
+				     (triggering ==
 				      ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE :
 				     IOSAPIC_LEVEL);
 }
diff --git a/arch/ia64/kernel/cpufreq/Makefile b/arch/ia64/kernel/cpufreq/Makefile
index f748d34..4838f2a 100644
--- a/arch/ia64/kernel/cpufreq/Makefile
+++ b/arch/ia64/kernel/cpufreq/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_IA64_ACPI_CPUFREQ)		+= acpi-cpufreq.o
+
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
index da4d5cf..5a1bf81 100644
--- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
+++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
@@ -269,48 +269,6 @@
 }
 
 
-/*
- * processor_init_pdc - let BIOS know about the SMP capabilities
- * of this driver
- * @perf: processor-specific acpi_io_data struct
- * @cpu: CPU being initialized
- *
- * To avoid issues with legacy OSes, some BIOSes require to be informed of
- * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC
- * accordingly. Actual call to _PDC is done in driver/acpi/processor.c
- */
-static void
-processor_init_pdc (
-		struct acpi_processor_performance *perf,
-		unsigned int cpu,
-		struct acpi_object_list *obj_list
-		)
-{
-	union acpi_object *obj;
-	u32 *buf;
-
-	dprintk("processor_init_pdc\n");
-
-	perf->pdc = NULL;
-	/* Initialize pdc. It will be used later. */
-	if (!obj_list)
-		return;
-
-	if (!(obj_list->count && obj_list->pointer))
-		return;
-
-	obj = obj_list->pointer;
-	if ((obj->buffer.length == 12) && obj->buffer.pointer) {
-		buf = (u32 *)obj->buffer.pointer;
-       		buf[0] = ACPI_PDC_REVISION_ID;
-       		buf[1] = 1;
-       		buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
-		perf->pdc = obj_list;
-	}
-	return;
-}
-
-
 static int
 acpi_cpufreq_cpu_init (
 	struct cpufreq_policy   *policy)
@@ -320,14 +278,7 @@
 	struct cpufreq_acpi_io	*data;
 	unsigned int		result = 0;
 
-	union acpi_object		arg0 = {ACPI_TYPE_BUFFER};
-	u32				arg0_buf[3];
-	struct acpi_object_list 	arg_list = {1, &arg0};
-
 	dprintk("acpi_cpufreq_cpu_init\n");
-	/* setup arg_list for _PDC settings */
-        arg0.buffer.length = 12;
-        arg0.buffer.pointer = (u8 *) arg0_buf;
 
 	data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
 	if (!data)
@@ -337,9 +288,7 @@
 
 	acpi_io_data[cpu] = data;
 
-	processor_init_pdc(&data->acpi_data, cpu, &arg_list);
 	result = acpi_processor_register_performance(&data->acpi_data, cpu);
-	data->acpi_data.pdc = NULL;
 
 	if (result)
 		goto err_free;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index c485a3b..9990320 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -410,24 +410,16 @@
 	efi_config_table_t *config_tables;
 	efi_char16_t *c16;
 	u64 efi_desc_size;
-	char *cp, *end, vendor[100] = "unknown";
+	char *cp, vendor[100] = "unknown";
 	extern char saved_command_line[];
 	int i;
 
 	/* it's too early to be able to use the standard kernel command line support... */
 	for (cp = saved_command_line; *cp; ) {
 		if (memcmp(cp, "mem=", 4) == 0) {
-			cp += 4;
-			mem_limit = memparse(cp, &end);
-			if (end != cp)
-				break;
-			cp = end;
+			mem_limit = memparse(cp + 4, &cp);
 		} else if (memcmp(cp, "max_addr=", 9) == 0) {
-			cp += 9;
-			max_addr = GRANULEROUNDDOWN(memparse(cp, &end));
-			if (end != cp)
-				break;
-			cp = end;
+			max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp));
 		} else {
 			while (*cp != ' ' && *cp)
 				++cp;
@@ -458,7 +450,7 @@
 	/* Show what we know for posterity */
 	c16 = __va(efi.systab->fw_vendor);
 	if (c16) {
-		for (i = 0;i < (int) sizeof(vendor) && *c16; ++i)
+		for (i = 0;i < (int) sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = *c16++;
 		vendor[i] = '\0';
 	}
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 7a6ffd6..27b222c 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1601,5 +1601,21 @@
 	data8 sys_inotify_add_watch
 	data8 sys_inotify_rm_watch
 	data8 sys_migrate_pages			// 1280
+	data8 sys_openat
+	data8 sys_mkdirat
+	data8 sys_mknodat
+	data8 sys_fchownat
+	data8 sys_futimesat			// 1285
+	data8 sys_newfstatat
+	data8 sys_unlinkat
+	data8 sys_renameat
+	data8 sys_linkat
+	data8 sys_symlinkat			// 1290
+	data8 sys_readlinkat
+	data8 sys_fchmodat
+	data8 sys_faccessat
+	data8 sys_ni_syscall			// reserved for pselect
+	data8 sys_ni_syscall			// 1295 reserved for ppoll
+	data8 sys_unshare
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index ce42391..ac6055c 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -878,31 +878,8 @@
 	data8 0				// timer_delete
 	data8 0				// clock_settime
 	data8 fsys_clock_gettime	// clock_gettime
-	data8 0				// clock_getres		// 1255
-	data8 0				// clock_nanosleep
-	data8 0				// fstatfs64
-	data8 0				// statfs64
-	data8 0
-	data8 0							// 1260
-	data8 0
-	data8 0				// mq_open
-	data8 0				// mq_unlink
-	data8 0				// mq_timedsend
-	data8 0				// mq_timedreceive	// 1265
-	data8 0				// mq_notify
-	data8 0				// mq_getsetattr
-	data8 0				// kexec_load
-	data8 0
-	data8 0							// 1270
-	data8 0
-	data8 0
-	data8 0
-	data8 0
-	data8 0							// 1275
-	data8 0
-	data8 0
-	data8 0
-	data8 0
-	data8 0							// 1280
+	#define __NR_syscall_last	1255
+
+	.space 8*(NR_syscalls + 1024 - __NR_syscall_last), 0
 
 	.org fsyscall_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index fbc7ea3..f1778a8 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -352,6 +352,7 @@
 	mov ar.rsc=0		// place RSE in enforced lazy mode
 	;;
 	loadrs			// clear the dirty partition
+	mov IA64_KR(PER_CPU_DATA)=r0	// clear physical per-CPU base
 	;;
 	mov ar.bspstore=r2	// establish the new RSE stack
 	;;
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 403a80a..60a464b 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -512,7 +512,7 @@
 	st8 [temp1]=r12		// os_status, default is cold boot
 	mov r6=IA64_MCA_SAME_CONTEXT
 	;;
-	st8 [temp1]=r6		// context, default is same context
+	st8 [temp2]=r6		// context, default is same context
 
 	// Save the pt_regs data that is not in minstate.  The previous code
 	// left regs at sos.
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 3492e32..8fd93af 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -437,6 +437,9 @@
 	 *    the process not have any locks of kernel.
 	 */
 
+	/* Is minstate valid? */
+	if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
+		return 0;
 	psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
 
 	/*
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 2ea4b39..9c5194b 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -40,6 +40,7 @@
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/rcupdate.h>
+#include <linux/completion.h>
 
 #include <asm/errno.h>
 #include <asm/intrinsics.h>
@@ -286,7 +287,7 @@
 
 	unsigned long		ctx_ovfl_regs[4];	/* which registers overflowed (notification) */
 
-	struct semaphore	ctx_restart_sem;   	/* use for blocking notification mode */
+	struct completion	ctx_restart_done;  	/* use for blocking notification mode */
 
 	unsigned long		ctx_used_pmds[4];	/* bitmask of PMD used            */
 	unsigned long		ctx_all_pmds[4];	/* bitmask of all accessible PMDs */
@@ -1991,7 +1992,7 @@
 		/*
 		 * force task to wake up from MASKED state
 		 */
-		up(&ctx->ctx_restart_sem);
+		complete(&ctx->ctx_restart_done);
 
 		DPRINT(("waking up ctx_state=%d\n", state));
 
@@ -2706,7 +2707,7 @@
 	/*
 	 * init restart semaphore to locked
 	 */
-	sema_init(&ctx->ctx_restart_sem, 0);
+	init_completion(&ctx->ctx_restart_done);
 
 	/*
 	 * activation is used in SMP only
@@ -3687,7 +3688,7 @@
 	 */
 	if (CTX_OVFL_NOBLOCK(ctx) == 0 && state == PFM_CTX_MASKED) {
 		DPRINT(("unblocking [%d] \n", task->pid));
-		up(&ctx->ctx_restart_sem);
+		complete(&ctx->ctx_restart_done);
 	} else {
 		DPRINT(("[%d] armed exit trap\n", task->pid));
 
@@ -5089,7 +5090,7 @@
 	 * may go through without blocking on SMP systems
 	 * if restart has been received already by the time we call down()
 	 */
-	ret = down_interruptible(&ctx->ctx_restart_sem);
+	ret = wait_for_completion_interruptible(&ctx->ctx_restart_done);
 
 	DPRINT(("after block sleeping ret=%d\n", ret));
 
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
index acc0f13..056f7a6 100644
--- a/arch/ia64/kernel/sal.c
+++ b/arch/ia64/kernel/sal.c
@@ -14,6 +14,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
+#include <asm/delay.h>
 #include <asm/page.h>
 #include <asm/sal.h>
 #include <asm/pal.h>
@@ -214,6 +215,78 @@
 static void __init sal_desc_ap_wakeup(void *p) { }
 #endif
 
+/*
+ * HP rx5670 firmware polls for interrupts during SAL_CACHE_FLUSH by reading
+ * cr.ivr, but it never writes cr.eoi.  This leaves any interrupt marked as
+ * "in-service" and masks other interrupts of equal or lower priority.
+ *
+ * HP internal defect reports: F1859, F2775, F3031.
+ */
+static int sal_cache_flush_drops_interrupts;
+
+static void __init
+check_sal_cache_flush (void)
+{
+	unsigned long flags, itv;
+	int cpu;
+	u64 vector;
+
+	cpu = get_cpu();
+	local_irq_save(flags);
+
+	/*
+	 * Schedule a timer interrupt, wait until it's reported, and see if
+	 * SAL_CACHE_FLUSH drops it.
+	 */
+	itv = ia64_get_itv();
+	BUG_ON((itv & (1 << 16)) == 0);
+
+	ia64_set_itv(IA64_TIMER_VECTOR);
+	ia64_set_itm(ia64_get_itc() + 1000);
+
+	while (!ia64_get_irr(IA64_TIMER_VECTOR))
+		cpu_relax();
+
+	ia64_sal_cache_flush(3);
+
+	if (ia64_get_irr(IA64_TIMER_VECTOR)) {
+		vector = ia64_get_ivr();
+		ia64_eoi();
+		WARN_ON(vector != IA64_TIMER_VECTOR);
+	} else {
+		sal_cache_flush_drops_interrupts = 1;
+		printk(KERN_ERR "SAL: SAL_CACHE_FLUSH drops interrupts; "
+			"PAL_CACHE_FLUSH will be used instead\n");
+		ia64_eoi();
+	}
+
+	ia64_set_itv(itv);
+	local_irq_restore(flags);
+	put_cpu();
+}
+
+s64
+ia64_sal_cache_flush (u64 cache_type)
+{
+	struct ia64_sal_retval isrv;
+
+	if (sal_cache_flush_drops_interrupts) {
+		unsigned long flags;
+		u64 progress;
+		s64 rc;
+
+		progress = 0;
+		local_irq_save(flags);
+		rc = ia64_pal_cache_flush(cache_type,
+			PAL_CACHE_FLUSH_INVALIDATE, &progress, NULL);
+		local_irq_restore(flags);
+		return rc;
+	}
+
+	SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0);
+	return isrv.status;
+}
+
 void __init
 ia64_sal_init (struct ia64_sal_systab *systab)
 {
@@ -262,6 +335,8 @@
 		}
 		p += SAL_DESC_SIZE(*p);
 	}
+
+	check_sal_cache_flush();
 }
 
 int
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index c076657..35f7835 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -71,6 +71,8 @@
 EXPORT_SYMBOL(__per_cpu_offset);
 #endif
 
+extern void ia64_setup_printk_clock(void);
+
 DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info);
 DEFINE_PER_CPU(unsigned long, local_per_cpu_offset);
 DEFINE_PER_CPU(unsigned long, ia64_phys_stacked_size_p8);
@@ -445,6 +447,8 @@
 	/* process SAL system table: */
 	ia64_sal_init(efi.sal_systab);
 
+	ia64_setup_printk_clock();
+
 #ifdef CONFIG_SMP
 	cpu_physical_id(0) = hard_smp_processor_id();
 
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 028a2b9..a094ec4 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -278,3 +278,30 @@
 	}
 }
 EXPORT_SYMBOL(udelay);
+
+static unsigned long long ia64_itc_printk_clock(void)
+{
+	if (ia64_get_kr(IA64_KR_PER_CPU_DATA))
+		return sched_clock();
+	return 0;
+}
+
+static unsigned long long ia64_default_printk_clock(void)
+{
+	return (unsigned long long)(jiffies_64 - INITIAL_JIFFIES) *
+		(1000000000/HZ);
+}
+
+unsigned long long (*ia64_printk_clock)(void) = &ia64_default_printk_clock;
+
+unsigned long long printk_clock(void)
+{
+	return ia64_printk_clock();
+}
+
+void __init
+ia64_setup_printk_clock(void)
+{
+	if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT))
+		ia64_printk_clock = ia64_itc_printk_clock;
+}
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index 706b773..6e5eea1 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -71,31 +71,33 @@
 	int i, err = 0;
 
 #ifdef CONFIG_NUMA
-	sysfs_nodes = kmalloc(sizeof(struct node) * MAX_NUMNODES, GFP_KERNEL);
+	sysfs_nodes = kzalloc(sizeof(struct node) * MAX_NUMNODES, GFP_KERNEL);
 	if (!sysfs_nodes) {
 		err = -ENOMEM;
 		goto out;
 	}
-	memset(sysfs_nodes, 0, sizeof(struct node) * MAX_NUMNODES);
 
-	/* MCD - Do we want to register all ONLINE nodes, or all POSSIBLE nodes? */
-	for_each_online_node(i)
+	/*
+	 * MCD - Do we want to register all ONLINE nodes, or all POSSIBLE nodes?
+	 */
+	for_each_online_node(i) {
 		if ((err = register_node(&sysfs_nodes[i], i, 0)))
 			goto out;
+	}
 #endif
 
-	sysfs_cpus = kmalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL);
+	sysfs_cpus = kzalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL);
 	if (!sysfs_cpus) {
 		err = -ENOMEM;
 		goto out;
 	}
-	memset(sysfs_cpus, 0, sizeof(struct ia64_cpu) * NR_CPUS);
 
-	for_each_present_cpu(i)
+	for_each_present_cpu(i) {
 		if((err = arch_register_cpu(i)))
 			goto out;
+	}
 out:
 	return err;
 }
 
-__initcall(topology_init);
+subsys_initcall(topology_init);
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index 43b45b6..f9e0ae9 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -1283,8 +1283,9 @@
 
 	if (jiffies - last_time > 5*HZ)
 		count = 0;
-	if (++count < 5) {
+	if (count < 5) {
 		last_time = jiffies;
+		count++;
 		return 1;
 	}
 	return 0;
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index b631cf8..fcd2bad 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -210,6 +210,7 @@
 
 	dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
 
+	touch_softlockup_watchdog();
 	memset((char *)start, 0, length);
 
 	node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index d27ecdc..0b30ca0 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -193,12 +193,12 @@
 		goto free_resource;
 	}
 
-	min = addr->min_address_range;
+	min = addr->minimum;
 	max = min + addr->address_length - 1;
-	if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION)
+	if (addr->info.io.translation_type == ACPI_SPARSE_TRANSLATION)
 		sparse = 1;
 
-	space_nr = new_space(addr->address_translation_offset, sparse);
+	space_nr = new_space(addr->translation_offset, sparse);
 	if (space_nr == ~0)
 		goto free_name;
 
@@ -285,7 +285,7 @@
 	if (addr.resource_type == ACPI_MEMORY_RANGE) {
 		flags = IORESOURCE_MEM;
 		root = &iomem_resource;
-		offset = addr.address_translation_offset;
+		offset = addr.translation_offset;
 	} else if (addr.resource_type == ACPI_IO_RANGE) {
 		flags = IORESOURCE_IO;
 		root = &ioport_resource;
@@ -298,7 +298,7 @@
 	window = &info->controller->window[info->controller->windows++];
 	window->resource.name = info->name;
 	window->resource.flags = flags;
-	window->resource.start = addr.min_address_range + offset;
+	window->resource.start = addr.minimum + offset;
 	window->resource.end = window->resource.start + addr.address_length - 1;
 	window->resource.child = NULL;
 	window->offset = offset;
diff --git a/arch/ia64/sn/Makefile b/arch/ia64/sn/Makefile
index a269f6d..79a7df0 100644
--- a/arch/ia64/sn/Makefile
+++ b/arch/ia64/sn/Makefile
@@ -9,6 +9,4 @@
 # Makefile for the sn ia64 subplatform
 #
 
-CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
-
 obj-y += kernel/ pci/
diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h
index 7c88e9a..8182583 100644
--- a/arch/ia64/sn/include/xtalk/hubdev.h
+++ b/arch/ia64/sn/include/xtalk/hubdev.h
@@ -51,6 +51,15 @@
 	struct sn_flush_device_common *common;
 };
 
+/* 01/16/06 This struct is the old PROM/kernel struct and needs to be included
+ * for older official PROMs to function on the new kernel base.  This struct
+ * will be removed when the next official PROM release occurs. */
+
+struct sn_flush_device_war {
+	struct sn_flush_device_common common;
+	u32 filler; /* older PROMs expect the default size of a spinlock_t */
+};
+
 /*
  * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel.
  */
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
index 4351c4f..3e9b4ee 100644
--- a/arch/ia64/sn/kernel/Makefile
+++ b/arch/ia64/sn/kernel/Makefile
@@ -7,6 +7,8 @@
 # Copyright (C) 1999,2001-2005 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
+CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
+
 obj-y				+= setup.o bte.o bte_error.o irq.o mca.o idle.o \
 				   huberror.o io_init.o iomv.o klconflib.o sn2/
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index dd73c0c..1f11db4 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/config.h>
@@ -186,18 +186,13 @@
 
 	/* Initialize the notification to a known value. */
 	*bte->most_rcnt_na = BTE_WORD_BUSY;
-	notif_phys_addr = TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na));
+	notif_phys_addr = (u64)bte->most_rcnt_na;
 
-	if (is_shub2()) {
-		src = SH2_TIO_PHYS_TO_DMA(src);
-		dest = SH2_TIO_PHYS_TO_DMA(dest);
-		notif_phys_addr = SH2_TIO_PHYS_TO_DMA(notif_phys_addr);
-	}
 	/* Set the source and destination registers */
-	BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src))));
-	BTE_SRC_STORE(bte, TO_PHYS(src));
-	BTE_PRINTKV(("IBDA = 0x%lx)\n", (TO_PHYS(dest))));
-	BTE_DEST_STORE(bte, TO_PHYS(dest));
+	BTE_PRINTKV(("IBSA = 0x%lx)\n", src));
+	BTE_SRC_STORE(bte, src);
+	BTE_PRINTKV(("IBDA = 0x%lx)\n", dest));
+	BTE_DEST_STORE(bte, dest);
 
 	/* Set the notification register */
 	BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr));
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 233d551..3437c23 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -10,6 +10,7 @@
 #include <linux/nodemask.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/sn_feature_sets.h>
 #include <asm/sn/geo.h>
 #include <asm/sn/io.h>
 #include <asm/sn/pcibr_provider.h>
@@ -165,11 +166,49 @@
 	return NULL;
 }
 
+/* Older PROM flush WAR
+ *
+ * 01/16/06 -- This war will be in place until a new official PROM is released.
+ * Additionally note that the struct sn_flush_device_war also has to be
+ * removed from arch/ia64/sn/include/xtalk/hubdev.h
+ */
+static u8 war_implemented = 0;
+
+static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
+			       struct sn_flush_device_common *common)
+{
+	struct sn_flush_device_war *war_list;
+	struct sn_flush_device_war *dev_entry;
+	struct ia64_sal_retval isrv = {0,0,0,0};
+
+	if (!war_implemented) {
+		printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
+		       "PROM flush WAR\n");
+		war_implemented = 1;
+	}
+
+	war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
+	if (!war_list)
+		BUG();
+
+	SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
+			nasid, widget, __pa(war_list), 0, 0, 0 ,0);
+	if (isrv.status)
+		panic("sn_device_fixup_war failed: %s\n",
+		      ia64_sal_strerror(isrv.status));
+
+	dev_entry = war_list + device;
+	memcpy(common,dev_entry, sizeof(*common));
+	kfree(war_list);
+
+	return isrv.status;
+}
+
 /*
- * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for 
+ * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
  *	each node in the system.
  */
-static void sn_fixup_ionodes(void)
+static void __init sn_fixup_ionodes(void)
 {
 	struct sn_flush_device_kernel *sn_flush_device_kernel;
 	struct sn_flush_device_kernel *dev_entry;
@@ -242,12 +281,21 @@
 				memset(dev_entry->common, 0x0, sizeof(struct
 					     	       sn_flush_device_common));
 
-				status = sal_get_device_dmaflush_list(nasid,
-									widget,
-								       	device,
+				if (sn_prom_feature_available(
+						       PRF_DEVICE_FLUSH_LIST))
+					status = sal_get_device_dmaflush_list(
+									  nasid,
+									 widget,
+								       	 device,
 						      (u64)(dev_entry->common));
-				if (status)
-					BUG();
+				else
+					status = sn_device_fixup_war(nasid,
+								     widget,
+							    	     device,
+							     dev_entry->common);
+				if (status != SALRET_OK)
+					panic("SAL call failed: %s\n",
+					      ia64_sal_strerror(status));
 
 				spin_lock_init(&dev_entry->sfdl_flush_lock);
 			}
@@ -419,6 +467,13 @@
 		pcidev_info->pdi_sn_irq_info = NULL;
 		kfree(sn_irq_info);
 	}
+
+	/*
+	 * MSI currently not supported on altix.  Remove this when
+	 * the MSI abstraction patches are integrated into the kernel
+	 * (sometime after 2.6.16 releases)
+	 */
+	dev->no_msi = 1;
 }
 
 /*
@@ -562,15 +617,15 @@
 void sn_bus_free_sysdata(void)
 {
 	struct sysdata_el *element;
-	struct list_head *list;
+	struct list_head *list, *safe;
 
-sn_sysdata_free_start:
-	list_for_each(list, &sn_sysdata_list) {
+	list_for_each_safe(list, safe, &sn_sysdata_list) {
 		element = list_entry(list, struct sysdata_el, entry);
 		list_del(&element->entry);
+		list_del(&(((struct pcidev_info *)
+			     (element->sysdata))->pdi_list));
 		kfree(element->sysdata);
 		kfree(element);
-		goto sn_sysdata_free_start;
 	}
 	return;
 }
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index ec37084..c373113 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -5,11 +5,12 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/irq.h>
 #include <linux/spinlock.h>
+#include <linux/init.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/intr.h>
@@ -76,17 +77,15 @@
 
 static void sn_ack_irq(unsigned int irq)
 {
-	u64 event_occurred, mask = 0;
+	u64 event_occurred, mask;
 
 	irq = irq & 0xff;
-	event_occurred =
-	    HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
+	event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
 	mask = event_occurred & SH_ALL_INT_MASK;
-	HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS),
-	      mask);
+	HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
 	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
 
-	move_irq(irq);
+	move_native_irq(irq);
 }
 
 static void sn_end_irq(unsigned int irq)
@@ -219,9 +218,8 @@
 		pdacpu(cpu)->sn_last_irq = irq;
 	}
 
-	if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) {
+	if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq)
 		pdacpu(cpu)->sn_first_irq = irq;
-	}
 }
 
 static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
@@ -289,7 +287,7 @@
 	list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
 	spin_unlock(&sn_irq_info_lock);
 
-	(void)register_intr_pda(sn_irq_info);
+	register_intr_pda(sn_irq_info);
 }
 
 void sn_irq_unfixup(struct pci_dev *pci_dev)
@@ -301,7 +299,9 @@
 		return;
 
 	sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info;
-	if (!sn_irq_info || !sn_irq_info->irq_irq) {
+	if (!sn_irq_info)
+		return;
+	if (!sn_irq_info->irq_irq) {
 		kfree(sn_irq_info);
 		return;
 	}
@@ -419,7 +419,7 @@
 	rcu_read_unlock();
 }
 
-void sn_irq_lh_init(void)
+void __init sn_irq_lh_init(void)
 {
 	int i;
 
@@ -434,5 +434,4 @@
 
 		INIT_LIST_HEAD(sn_irq_lh[i]);
 	}
-
 }
diff --git a/arch/ia64/sn/kernel/klconflib.c b/arch/ia64/sn/kernel/klconflib.c
index 0f11a32..87682b4 100644
--- a/arch/ia64/sn/kernel/klconflib.c
+++ b/arch/ia64/sn/kernel/klconflib.c
@@ -78,31 +78,30 @@
 	position = MODULE_GET_BPOS(m);
 
 	if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) {
-	    /* Brief module number format, eg. 002c15 */
+		/* Brief module number format, eg. 002c15 */
 
-	    /* Decompress the rack number */
-	    *buffer++ = '0' + RACK_GET_CLASS(rack);
-	    *buffer++ = '0' + RACK_GET_GROUP(rack);
-	    *buffer++ = '0' + RACK_GET_NUM(rack);
+		/* Decompress the rack number */
+		*buffer++ = '0' + RACK_GET_CLASS(rack);
+		*buffer++ = '0' + RACK_GET_GROUP(rack);
+		*buffer++ = '0' + RACK_GET_NUM(rack);
 
-	    /* Add the brick type */
-	    *buffer++ = brickchar;
+		/* Add the brick type */
+		*buffer++ = brickchar;
 	}
 	else if (fmt == MODULE_FORMAT_LONG) {
-	    /* Fuller hwgraph format, eg. rack/002/bay/15 */
+		/* Fuller hwgraph format, eg. rack/002/bay/15 */
 
-	    strcpy(buffer, "rack" "/");  buffer += strlen(buffer);
+		strcpy(buffer, "rack" "/");  buffer += strlen(buffer);
 
-	    *buffer++ = '0' + RACK_GET_CLASS(rack);
-	    *buffer++ = '0' + RACK_GET_GROUP(rack);
-	    *buffer++ = '0' + RACK_GET_NUM(rack);
+		*buffer++ = '0' + RACK_GET_CLASS(rack);
+		*buffer++ = '0' + RACK_GET_GROUP(rack);
+		*buffer++ = '0' + RACK_GET_NUM(rack);
 
-	    strcpy(buffer, "/" "bay" "/");  buffer += strlen(buffer);
+		strcpy(buffer, "/" "bay" "/");  buffer += strlen(buffer);
 	}
 
 	/* Add the bay position, using at least two digits */
 	if (position < 10)
-	    *buffer++ = '0';
+		*buffer++ = '0';
 	sprintf(buffer, "%d", position);
-
 }
diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c
index 6546db6..3db62f2 100644
--- a/arch/ia64/sn/kernel/mca.c
+++ b/arch/ia64/sn/kernel/mca.c
@@ -3,13 +3,14 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
 #include <linux/vmalloc.h>
+#include <linux/mutex.h>
 #include <asm/mca.h>
 #include <asm/sal.h>
 #include <asm/sn/sn_sal.h>
@@ -27,7 +28,7 @@
 /* Printing oemdata from mca uses data that is not passed through SAL, it is
  * global.  Only one user at a time.
  */
-static DECLARE_MUTEX(sn_oemdata_mutex);
+static DEFINE_MUTEX(sn_oemdata_mutex);
 static u8 **sn_oemdata;
 static u64 *sn_oemdata_size, sn_oemdata_bufsize;
 
@@ -89,7 +90,7 @@
 sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
 				    u64 * oemdata_size)
 {
-	down(&sn_oemdata_mutex);
+	mutex_lock(&sn_oemdata_mutex);
 	sn_oemdata = oemdata;
 	sn_oemdata_size = oemdata_size;
 	sn_oemdata_bufsize = 0;
@@ -107,7 +108,7 @@
 		*sn_oemdata_size = 0;
 		ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
 	}
-	up(&sn_oemdata_mutex);
+	mutex_unlock(&sn_oemdata_mutex);
 	return 0;
 }
 
@@ -136,7 +137,8 @@
 
 static int __init sn_salinfo_init(void)
 {
-	salinfo_platform_oemdata = &sn_salinfo_platform_oemdata;
+	if (ia64_platform_is("sn2"))
+		salinfo_platform_oemdata = &sn_salinfo_platform_oemdata;
 	return 0;
 }
 
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index e510dce..48645ac 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -67,6 +67,7 @@
 extern void (*ia64_mark_idle) (int);
 extern void snidle(int);
 extern unsigned char acpi_kbd_controller_present;
+extern unsigned long long (*ia64_printk_clock)(void);
 
 unsigned long sn_rtc_cycles_per_second;
 EXPORT_SYMBOL(sn_rtc_cycles_per_second);
@@ -125,20 +126,6 @@
 };
 
 /*
- * This is here so we can use the CMOS detection in ide-probe.c to
- * determine what drives are present.  In theory, we don't need this
- * as the auto-detection could be done via ide-probe.c:do_probe() but
- * in practice that would be much slower, which is painful when
- * running in the simulator.  Note that passing zeroes in DRIVE_INFO
- * is sufficient (the IDE driver will autodetect the drive geometry).
- */
-#ifdef CONFIG_IA64_GENERIC
-extern char drive_info[4 * 16];
-#else
-char drive_info[4 * 16];
-#endif
-
-/*
  * This routine can only be used during init, since
  * smp_boot_data is an init data structure.
  * We have to use smp_boot_data.cpu_phys_id to find
@@ -209,7 +196,7 @@
 }
 
 extern int platform_intr_list[];
-static int __initdata shub_1_1_found = 0;
+static int __initdata shub_1_1_found;
 
 /*
  * sn_check_for_wars
@@ -372,6 +359,16 @@
 	}
 }
 
+static unsigned long sn2_rtc_initial;
+
+static unsigned long long ia64_sn2_printk_clock(void)
+{
+	unsigned long rtc_now = rtc_time();
+
+	return (rtc_now - sn2_rtc_initial) *
+		(1000000000 / sn_rtc_cycles_per_second);
+}
+
 /**
  * sn_setup - SN platform setup routine
  * @cmdline_p: kernel command line
@@ -386,6 +383,7 @@
 	u32 version = sn_sal_rev();
 	extern void sn_cpu_init(void);
 
+	sn2_rtc_initial = rtc_time();
 	ia64_sn_plat_set_error_handling_features();	// obsolete
 	ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV);
 	ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES);
@@ -437,19 +435,6 @@
 	 */
 	build_cnode_tables();
 
-	/*
-	 * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard
-	 * support here so we don't have to listen to failed keyboard probe
-	 * messages.
-	 */
-	if (version <= 0x0209 && acpi_kbd_controller_present) {
-		printk(KERN_INFO "Disabling legacy keyboard support as prom "
-		       "is too old and doesn't provide FADT\n");
-		acpi_kbd_controller_present = 0;
-	}
-
-	printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
-
 	status =
 	    ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
 			       &drift);
@@ -463,6 +448,21 @@
 
 	platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR;
 
+	ia64_printk_clock = ia64_sn2_printk_clock;
+
+	/*
+	 * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard
+	 * support here so we don't have to listen to failed keyboard probe
+	 * messages.
+	 */
+	if (version <= 0x0209 && acpi_kbd_controller_present) {
+		printk(KERN_INFO "Disabling legacy keyboard support as prom "
+		       "is too old and doesn't provide FADT\n");
+		acpi_kbd_controller_present = 0;
+	}
+
+	printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
+
 	/*
 	 * we set the default root device to /dev/hda
 	 * to make simulation easy
@@ -578,13 +578,17 @@
 			sn_prom_type = 2;
 		else
 			sn_prom_type = 1;
-		printk("Running on medusa with %s PROM\n", (sn_prom_type == 1) ? "real" : "fake");
+		printk(KERN_INFO "Running on medusa with %s PROM\n",
+		       (sn_prom_type == 1) ? "real" : "fake");
 	}
 
 	memset(pda, 0, sizeof(pda));
-	if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift,
-				&sn_system_size, &sn_sharing_domain_size, &sn_partition_id,
-				&sn_coherency_id, &sn_region_size))
+	if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2,
+				&sn_hub_info->nasid_bitmask,
+				&sn_hub_info->nasid_shift,
+				&sn_system_size, &sn_sharing_domain_size,
+				&sn_partition_id, &sn_coherency_id,
+				&sn_region_size))
 		BUG();
 	sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2;
 
@@ -716,7 +720,8 @@
 	for_each_online_node(node) {
 		kl_config_hdr_t *klgraph_header;
 		nasid = cnodeid_to_nasid(node);
-		if ((klgraph_header = ia64_sn_get_klconfig_addr(nasid)) == NULL)
+		klgraph_header = ia64_sn_get_klconfig_addr(nasid);
+		if (klgraph_header == NULL)
 			BUG();
 		brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info);
 		while (brd) {
@@ -734,7 +739,7 @@
 {
 	long cpu;
 
-	for (cpu=0; cpu < NR_CPUS; cpu++)
+	for (cpu = 0; cpu < NR_CPUS; cpu++)
 		if (cpuid_to_nasid(cpu) == nasid &&
 					cpuid_to_slice(cpu) == slice)
 			return cpu;
diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
index 170bde4..99e1776 100644
--- a/arch/ia64/sn/kernel/sn2/Makefile
+++ b/arch/ia64/sn/kernel/sn2/Makefile
@@ -9,5 +9,7 @@
 # sn2 specific kernel files
 #
 
+CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
+
 obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
 	 prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 471bbaa..f153a4c 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -46,104 +46,28 @@
 
 static  __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock);
 
-void sn2_ptc_deadlock_recovery(short *, short, int, volatile unsigned long *, unsigned long data0,
-	volatile unsigned long *, unsigned long data1);
+void sn2_ptc_deadlock_recovery(short *, short, short, int, volatile unsigned long *, unsigned long,
+	volatile unsigned long *, unsigned long);
 
-#ifdef DEBUG_PTC
 /*
- * ptctest:
- *
- * 	xyz - 3 digit hex number:
- * 		x - Force PTC purges to use shub:
- * 			0 - no force
- * 			1 - force
- * 		y - interupt enable
- * 			0 - disable interrupts
- * 			1 - leave interuupts enabled
- * 		z - type of lock:
- * 			0 - global lock
- * 			1 - node local lock
- * 			2 - no lock
- *
- *   	Note: on shub1, only ptctest == 0 is supported. Don't try other values!
+ * Note: some is the following is captured here to make degugging easier
+ * (the macros make more sense if you see the debug patch - not posted)
  */
-
-static unsigned int sn2_ptctest = 0;
-
-static int __init ptc_test(char *str)
-{
-	get_option(&str, &sn2_ptctest);
-	return 1;
-}
-__setup("ptctest=", ptc_test);
-
-static inline int ptc_lock(unsigned long *flagp)
-{
-	unsigned long opt = sn2_ptctest & 255;
-
-	switch (opt) {
-	case 0x00:
-		spin_lock_irqsave(&sn2_global_ptc_lock, *flagp);
-		break;
-	case 0x01:
-		spin_lock_irqsave(&sn_nodepda->ptc_lock, *flagp);
-		break;
-	case 0x02:
-		local_irq_save(*flagp);
-		break;
-	case 0x10:
-		spin_lock(&sn2_global_ptc_lock);
-		break;
-	case 0x11:
-		spin_lock(&sn_nodepda->ptc_lock);
-		break;
-	case 0x12:
-		break;
-	default:
-		BUG();
-	}
-	return opt;
-}
-
-static inline void ptc_unlock(unsigned long flags, int opt)
-{
-	switch (opt) {
-	case 0x00:
-		spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
-		break;
-	case 0x01:
-		spin_unlock_irqrestore(&sn_nodepda->ptc_lock, flags);
-		break;
-	case 0x02:
-		local_irq_restore(flags);
-		break;
-	case 0x10:
-		spin_unlock(&sn2_global_ptc_lock);
-		break;
-	case 0x11:
-		spin_unlock(&sn_nodepda->ptc_lock);
-		break;
-	case 0x12:
-		break;
-	default:
-		BUG();
-	}
-}
-#else
-
 #define sn2_ptctest	0
+#define local_node_uses_ptc_ga(sh1)	((sh1) ? 1 : 0)
+#define max_active_pio(sh1)		((sh1) ? 32 : 7)
+#define reset_max_active_on_deadlock()	1
+#define PTC_LOCK(sh1)			((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock)
 
-static inline int ptc_lock(unsigned long *flagp)
+static inline void ptc_lock(int sh1, unsigned long *flagp)
 {
-	spin_lock_irqsave(&sn2_global_ptc_lock, *flagp);
-	return 0;
+	spin_lock_irqsave(PTC_LOCK(sh1), *flagp);
 }
 
-static inline void ptc_unlock(unsigned long flags, int opt)
+static inline void ptc_unlock(int sh1, unsigned long flags)
 {
-	spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
+	spin_unlock_irqrestore(PTC_LOCK(sh1), flags);
 }
-#endif
 
 struct ptc_stats {
 	unsigned long ptc_l;
@@ -151,27 +75,30 @@
 	unsigned long shub_ptc_flushes;
 	unsigned long nodes_flushed;
 	unsigned long deadlocks;
+	unsigned long deadlocks2;
 	unsigned long lock_itc_clocks;
 	unsigned long shub_itc_clocks;
 	unsigned long shub_itc_clocks_max;
+	unsigned long shub_ptc_flushes_not_my_mm;
 };
 
 static inline unsigned long wait_piowc(void)
 {
-	volatile unsigned long *piows, zeroval;
-	unsigned long ws;
+	volatile unsigned long *piows;
+	unsigned long zeroval, ws;
 
 	piows = pda->pio_write_status_addr;
 	zeroval = pda->pio_write_status_val;
 	do {
 		cpu_relax();
 	} while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval);
-	return ws;
+	return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0;
 }
 
 void sn_tlb_migrate_finish(struct mm_struct *mm)
 {
-	if (mm == current->mm)
+	/* flush_tlb_mm is inefficient if more than 1 users of mm */
+	if (mm == current->mm && mm && atomic_read(&mm->mm_users) == 1)
 		flush_tlb_mm(mm);
 }
 
@@ -201,12 +128,14 @@
 sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
 		     unsigned long end, unsigned long nbits)
 {
-	int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0;
-	int mymm = (mm == current->active_mm && current->mm);
+	int i, ibegin, shub1, cnode, mynasid, cpu, lcpu = 0, nasid;
+	int mymm = (mm == current->active_mm && mm == current->mm);
+	int use_cpu_ptcga;
 	volatile unsigned long *ptc0, *ptc1;
-	unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value;
+	unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0;
 	short nasids[MAX_NUMNODES], nix;
 	nodemask_t nodes_flushed;
+	int active, max_active, deadlock;
 
 	nodes_clear(nodes_flushed);
 	i = 0;
@@ -267,41 +196,56 @@
 	
 
 	mynasid = get_nasid();
+	use_cpu_ptcga = local_node_uses_ptc_ga(shub1);
+	max_active = max_active_pio(shub1);
 
 	itc = ia64_get_itc();
-	opt = ptc_lock(&flags);
+	ptc_lock(shub1, &flags);
 	itc2 = ia64_get_itc();
+
 	__get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc;
 	__get_cpu_var(ptcstats).shub_ptc_flushes++;
 	__get_cpu_var(ptcstats).nodes_flushed += nix;
+	if (!mymm)
+		 __get_cpu_var(ptcstats).shub_ptc_flushes_not_my_mm++;
 
+	if (use_cpu_ptcga && !mymm) {
+		old_rr = ia64_get_rr(start);
+		ia64_set_rr(start, (old_rr & 0xff) | (rr_value << 8));
+		ia64_srlz_d();
+	}
+
+	wait_piowc();
 	do {
 		if (shub1)
 			data1 = start | (1UL << SH1_PTC_1_START_SHFT);
 		else
 			data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
-		for (i = 0; i < nix; i++) {
+		deadlock = 0;
+		active = 0;
+		for (ibegin = 0, i = 0; i < nix; i++) {
 			nasid = nasids[i];
-			if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid && mymm)) {
+			if (use_cpu_ptcga && unlikely(nasid == mynasid)) {
 				ia64_ptcga(start, nbits << 2);
 				ia64_srlz_i();
 			} else {
 				ptc0 = CHANGE_NASID(nasid, ptc0);
 				if (ptc1)
 					ptc1 = CHANGE_NASID(nasid, ptc1);
-				pio_atomic_phys_write_mmrs(ptc0, data0, ptc1,
-							   data1);
-				flushed = 1;
+				pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1);
+				active++;
+			}
+			if (active >= max_active || i == (nix - 1)) {
+				if ((deadlock = wait_piowc())) {
+					sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1);
+					if (reset_max_active_on_deadlock())
+						max_active = 1;
+				}
+				active = 0;
+				ibegin = i + 1;
 			}
 		}
-		if (flushed
-		    && (wait_piowc() &
-				(SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK))) {
-			sn2_ptc_deadlock_recovery(nasids, nix, mynasid, ptc0, data0, ptc1, data1);
-		}
-
 		start += (1UL << nbits);
-
 	} while (start < end);
 
 	itc2 = ia64_get_itc() - itc2;
@@ -309,7 +253,12 @@
 	if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max)
 		__get_cpu_var(ptcstats).shub_itc_clocks_max = itc2;
 
-	ptc_unlock(flags, opt);
+	if (old_rr) {
+		ia64_set_rr(start, old_rr);
+		ia64_srlz_d();
+	}
+
+	ptc_unlock(shub1, flags);
 
 	preempt_enable();
 }
@@ -321,27 +270,30 @@
  * TLB flush transaction.  The recovery sequence is somewhat tricky & is
  * coded in assembly language.
  */
-void sn2_ptc_deadlock_recovery(short *nasids, short nix, int mynasid, volatile unsigned long *ptc0, unsigned long data0,
+void sn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid, volatile unsigned long *ptc0, unsigned long data0,
 	volatile unsigned long *ptc1, unsigned long data1)
 {
-	extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
+	extern unsigned long sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
 	        volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long);
 	short nasid, i;
-	unsigned long *piows, zeroval;
+	unsigned long *piows, zeroval, n;
 
 	__get_cpu_var(ptcstats).deadlocks++;
 
 	piows = (unsigned long *) pda->pio_write_status_addr;
 	zeroval = pda->pio_write_status_val;
 
-	for (i=0; i < nix; i++) {
+
+	for (i=ib; i <= ie; i++) {
 		nasid = nasids[i];
-		if (!(sn2_ptctest & 3) && nasid == mynasid)
+		if (local_node_uses_ptc_ga(is_shub1()) && nasid == mynasid)
 			continue;
 		ptc0 = CHANGE_NASID(nasid, ptc0);
 		if (ptc1)
 			ptc1 = CHANGE_NASID(nasid, ptc1);
-		sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);
+
+		n = sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);
+		__get_cpu_var(ptcstats).deadlocks2 += n;
 	}
 
 }
@@ -452,20 +404,22 @@
 	cpu = *(loff_t *) data;
 
 	if (!cpu) {
-		seq_printf(file, "# ptc_l change_rid shub_ptc_flushes shub_nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max\n");
+		seq_printf(file,
+			   "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n");
 		seq_printf(file, "# ptctest %d\n", sn2_ptctest);
 	}
 
 	if (cpu < NR_CPUS && cpu_online(cpu)) {
 		stat = &per_cpu(ptcstats, cpu);
-		seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
+		seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
 				stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,
 				stat->deadlocks,
 				1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
 				1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
-				1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec);
+				1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec,
+				stat->shub_ptc_flushes_not_my_mm,
+				stat->deadlocks2);
 	}
-
 	return 0;
 }
 
@@ -476,7 +430,7 @@
 	.show = sn2_ptc_seq_show
 };
 
-int sn2_ptc_proc_open(struct inode *inode, struct file *file)
+static int sn2_ptc_proc_open(struct inode *inode, struct file *file)
 {
 	return seq_open(file, &sn2_ptc_seq_ops);
 }
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 19b54fb..70db21f 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved.
  *
  * SGI Altix topology and hardware performance monitoring API.
  * Mark Goodwin <markgw@sgi.com>. 
@@ -973,6 +973,9 @@
 {
 	int e;
 
+	if (!ia64_platform_is("sn2"))
+		return 0;
+
 	sn_hwperf_init();
 
 	/*
diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c
index 3be52a3..b7ea466 100644
--- a/arch/ia64/sn/kernel/xp_main.c
+++ b/arch/ia64/sn/kernel/xp_main.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/xp.h>
@@ -136,13 +137,13 @@
 
 	registration = &xpc_registrations[ch_number];
 
-	if (down_interruptible(&registration->sema) != 0) {
+	if (mutex_lock_interruptible(&registration->mutex) != 0) {
 		return xpcInterrupted;
 	}
 
 	/* if XPC_CHANNEL_REGISTERED(ch_number) */
 	if (registration->func != NULL) {
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return xpcAlreadyRegistered;
 	}
 
@@ -154,7 +155,7 @@
 	registration->key = key;
 	registration->func = func;
 
-	up(&registration->sema);
+	mutex_unlock(&registration->mutex);
 
 	xpc_interface.connect(ch_number);
 
@@ -190,11 +191,11 @@
 	 * figured XPC's users will just turn around and call xpc_disconnect()
 	 * again anyways, so we might as well wait, if need be.
 	 */
-	down(&registration->sema);
+	mutex_lock(&registration->mutex);
 
 	/* if !XPC_CHANNEL_REGISTERED(ch_number) */
 	if (registration->func == NULL) {
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return;
 	}
 
@@ -208,7 +209,7 @@
 
 	xpc_interface.disconnect(ch_number);
 
-	up(&registration->sema);
+	mutex_unlock(&registration->mutex);
 
 	return;
 }
@@ -250,9 +251,9 @@
 		xp_nofault_PIOR_target = SH1_IPI_ACCESS;
 	}
 
-	/* initialize the connection registration semaphores */
+	/* initialize the connection registration mutex */
 	for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
-		sema_init(&xpc_registrations[ch_number].sema, 1);  /* mutex */
+		mutex_init(&xpc_registrations[ch_number].mutex);
 	}
 
 	return 0;
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index 0c0a689..36e5437 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -22,6 +22,8 @@
 #include <linux/cache.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/xpc.h>
@@ -56,8 +58,8 @@
 		atomic_set(&ch->n_to_notify, 0);
 
 		spin_lock_init(&ch->lock);
-		sema_init(&ch->msg_to_pull_sema, 1);	/* mutex */
-		sema_init(&ch->wdisconnect_sema, 0);	/* event wait */
+		mutex_init(&ch->msg_to_pull_mutex);
+		init_completion(&ch->wdisconnect_wait);
 
 		atomic_set(&ch->n_on_msg_allocate_wq, 0);
 		init_waitqueue_head(&ch->msg_allocate_wq);
@@ -445,7 +447,7 @@
 
 		nbytes = nentries * ch->msg_size;
 		ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
-						(GFP_KERNEL | GFP_DMA),
+						GFP_KERNEL,
 						&ch->local_msgqueue_base);
 		if (ch->local_msgqueue == NULL) {
 			continue;
@@ -453,7 +455,7 @@
 		memset(ch->local_msgqueue, 0, nbytes);
 
 		nbytes = nentries * sizeof(struct xpc_notify);
-		ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA));
+		ch->notify_queue = kmalloc(nbytes, GFP_KERNEL);
 		if (ch->notify_queue == NULL) {
 			kfree(ch->local_msgqueue_base);
 			ch->local_msgqueue = NULL;
@@ -500,7 +502,7 @@
 
 		nbytes = nentries * ch->msg_size;
 		ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
-						(GFP_KERNEL | GFP_DMA),
+						GFP_KERNEL,
 						&ch->remote_msgqueue_base);
 		if (ch->remote_msgqueue == NULL) {
 			continue;
@@ -534,7 +536,6 @@
 xpc_allocate_msgqueues(struct xpc_channel *ch)
 {
 	unsigned long irq_flags;
-	int i;
 	enum xpc_retval ret;
 
 
@@ -552,11 +553,6 @@
 		return ret;
 	}
 
-	for (i = 0; i < ch->local_nentries; i++) {
-		/* use a semaphore as an event wait queue */
-		sema_init(&ch->notify_queue[i].sema, 0);
-	}
-
 	spin_lock_irqsave(&ch->lock, irq_flags);
 	ch->flags |= XPC_C_SETUP;
 	spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -799,10 +795,8 @@
 	}
 
 	if (ch->flags & XPC_C_WDISCONNECT) {
-		spin_unlock_irqrestore(&ch->lock, *irq_flags);
-		up(&ch->wdisconnect_sema);
-		spin_lock_irqsave(&ch->lock, *irq_flags);
-
+		/* we won't lose the CPU since we're holding ch->lock */
+		complete(&ch->wdisconnect_wait);
 	} else if (ch->delayed_IPI_flags) {
 		if (part->act_state != XPC_P_DEACTIVATING) {
 			/* time to take action on any delayed IPI flags */
@@ -1092,12 +1086,12 @@
 	struct xpc_registration *registration = &xpc_registrations[ch->number];
 
 
-	if (down_trylock(&registration->sema) != 0) {
+	if (mutex_trylock(&registration->mutex) == 0) {
 		return xpcRetry;
 	}
 
 	if (!XPC_CHANNEL_REGISTERED(ch->number)) {
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return xpcUnregistered;
 	}
 
@@ -1108,7 +1102,7 @@
 
 	if (ch->flags & XPC_C_DISCONNECTING) {
 		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return ch->reason;
 	}
 
@@ -1140,7 +1134,7 @@
 			 * channel lock be locked and will unlock and relock
 			 * the channel lock as needed.
 			 */
-			up(&registration->sema);
+			mutex_unlock(&registration->mutex);
 			XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
 								&irq_flags);
 			spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -1155,7 +1149,7 @@
 		atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
 	}
 
-	up(&registration->sema);
+	mutex_unlock(&registration->mutex);
 
 
 	/* initiate the connection */
@@ -2089,7 +2083,7 @@
 	enum xpc_retval ret;
 
 
-	if (down_interruptible(&ch->msg_to_pull_sema) != 0) {
+	if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) {
 		/* we were interrupted by a signal */
 		return NULL;
 	}
@@ -2125,7 +2119,7 @@
 
 			XPC_DEACTIVATE_PARTITION(part, ret);
 
-			up(&ch->msg_to_pull_sema);
+			mutex_unlock(&ch->msg_to_pull_mutex);
 			return NULL;
 		}
 
@@ -2134,7 +2128,7 @@
 		ch->next_msg_to_pull += nmsgs;
 	}
 
-	up(&ch->msg_to_pull_sema);
+	mutex_unlock(&ch->msg_to_pull_mutex);
 
 	/* return the message we were looking for */
 	msg_offset = (get % ch->remote_nentries) * ch->msg_size;
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index 8930586e..9cd460d 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -55,6 +55,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
+#include <linux/completion.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/kdebug.h>
@@ -177,10 +178,10 @@
 static unsigned long xpc_hb_check_timeout;
 
 /* notification that the xpc_hb_checker thread has exited */
-static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited);
+static DECLARE_COMPLETION(xpc_hb_checker_exited);
 
 /* notification that the xpc_discovery thread has exited */
-static DECLARE_MUTEX_LOCKED(xpc_discovery_exited);
+static DECLARE_COMPLETION(xpc_discovery_exited);
 
 
 static struct timer_list xpc_hb_timer;
@@ -321,7 +322,7 @@
 
 
 	/* mark this thread as having exited */
-	up(&xpc_hb_checker_exited);
+	complete(&xpc_hb_checker_exited);
 	return 0;
 }
 
@@ -341,7 +342,7 @@
 	dev_dbg(xpc_part, "discovery thread is exiting\n");
 
 	/* mark this thread as having exited */
-	up(&xpc_discovery_exited);
+	complete(&xpc_discovery_exited);
 	return 0;
 }
 
@@ -574,18 +575,21 @@
 
 	spin_lock_irqsave(&part->act_lock, irq_flags);
 
-	pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0);
-
 	DBUG_ON(part->act_state != XPC_P_INACTIVE);
 
-	if (pid > 0) {
-		part->act_state = XPC_P_ACTIVATION_REQ;
-		XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
-	} else {
-		XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
-	}
+	part->act_state = XPC_P_ACTIVATION_REQ;
+	XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
 
 	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+
+	pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0);
+
+	if (unlikely(pid <= 0)) {
+		spin_lock_irqsave(&part->act_lock, irq_flags);
+		part->act_state = XPC_P_INACTIVE;
+		XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
+		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+	}
 }
 
 
@@ -893,7 +897,7 @@
 			continue;
 		}
 
-		(void) down(&ch->wdisconnect_sema);
+		wait_for_completion(&ch->wdisconnect_wait);
 
 		spin_lock_irqsave(&ch->lock, irq_flags);
 		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
@@ -946,10 +950,10 @@
 	free_irq(SGI_XPC_ACTIVATE, NULL);
 
 	/* wait for the discovery thread to exit */
-	down(&xpc_discovery_exited);
+	wait_for_completion(&xpc_discovery_exited);
 
 	/* wait for the heartbeat checker thread to exit */
-	down(&xpc_hb_checker_exited);
+	wait_for_completion(&xpc_hb_checker_exited);
 
 
 	/* sleep for a 1/3 of a second or so */
@@ -1367,7 +1371,7 @@
 		dev_err(xpc_part, "failed while forking discovery thread\n");
 
 		/* mark this new thread as a non-starter */
-		up(&xpc_discovery_exited);
+		complete(&xpc_discovery_exited);
 
 		xpc_do_exit(xpcUnloading);
 		return -EBUSY;
diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile
index 321576b..c694678 100644
--- a/arch/ia64/sn/pci/Makefile
+++ b/arch/ia64/sn/pci/Makefile
@@ -7,4 +7,6 @@
 #
 # Makefile for the sn pci general routines.
 
+CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
+
 obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index 9bf9f23..5a36292 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -90,14 +90,14 @@
 	 */
 	node = pcibus_to_node(pdev->bus);
 	if (likely(node >=0)) {
-		struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size));
+		struct page *p = alloc_pages_node(node, flags, get_order(size));
 
 		if (likely(p))
 			cpuaddr = page_address(p);
 		else
 			return NULL;
 	} else
-		cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
+		cpuaddr = (void *)__get_free_pages(flags, get_order(size));
 
 	if (unlikely(!cpuaddr))
 		return NULL;
diff --git a/arch/ia64/sn/pci/pcibr/Makefile b/arch/ia64/sn/pci/pcibr/Makefile
index 1850c4a..3b403ea 100644
--- a/arch/ia64/sn/pci/pcibr/Makefile
+++ b/arch/ia64/sn/pci/pcibr/Makefile
@@ -7,5 +7,7 @@
 #
 # Makefile for the sn2 io routines.
 
+CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
+
 obj-y				+=  pcibr_dma.o pcibr_reg.o \
 				    pcibr_ate.o pcibr_provider.o
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 77a1262..2fac270 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -24,13 +24,15 @@
 {
 	struct ia64_sal_retval ret_stuff;
 	u64 busnum;
+	u64 segment;
 
 	ret_stuff.status = 0;
 	ret_stuff.v0 = 0;
 
+	segment = soft->pbi_buscommon.bs_persist_segment;
 	busnum = soft->pbi_buscommon.bs_persist_busnum;
-	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, (u64) busnum,
-			(u64) device, (u64) resp, 0, 0, 0, 0);
+	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment,
+			busnum, (u64) device, (u64) resp, 0, 0, 0);
 
 	return (int)ret_stuff.v0;
 }
@@ -41,14 +43,16 @@
 {
 	struct ia64_sal_retval ret_stuff;
 	u64 busnum;
+	u64 segment;
 
 	ret_stuff.status = 0;
 	ret_stuff.v0 = 0;
 
+	segment = soft->pbi_buscommon.bs_persist_segment;
 	busnum = soft->pbi_buscommon.bs_persist_busnum;
 	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE,
-			(u64) busnum, (u64) device, (u64) action,
-			(u64) resp, 0, 0, 0);
+			segment, busnum, (u64) device, (u64) action,
+			(u64) resp, 0, 0);
 
 	return (int)ret_stuff.v0;
 }
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
index dbc8a39..be8b711 100644
--- a/arch/m32r/kernel/m32r_ksyms.c
+++ b/arch/m32r/kernel/m32r_ksyms.c
@@ -18,11 +18,6 @@
 #include <asm/irq.h>
 #include <asm/tlbflush.h>
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
-extern struct drive_info_struct drive_info;
-EXPORT_SYMBOL(drive_info);
-#endif
-
 /* platform dependent support */
 EXPORT_SYMBOL(boot_cpu_data);
 EXPORT_SYMBOL(dump_fpu);
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index c2e4dcc..d742037 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -37,12 +37,6 @@
 extern void init_mmu(void);
 #endif
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)	\
-	|| defined(CONFIG_BLK_DEV_IDE_MODULE)			\
-	|| defined(CONFIG_BLK_DEV_HD_MODULE)
-struct drive_info_struct { char dummy[32]; } drive_info;
-#endif
-
 extern char _end[];
 
 /*
diff --git a/arch/m68k/fpsp040/bindec.S b/arch/m68k/fpsp040/bindec.S
index 3ba446a..72f1159 100644
--- a/arch/m68k/fpsp040/bindec.S
+++ b/arch/m68k/fpsp040/bindec.S
@@ -131,9 +131,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |BINDEC    idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/binstr.S b/arch/m68k/fpsp040/binstr.S
index d53555c..8a05ba9 100644
--- a/arch/m68k/fpsp040/binstr.S
+++ b/arch/m68k/fpsp040/binstr.S
@@ -60,9 +60,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |BINSTR    idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/bugfix.S b/arch/m68k/fpsp040/bugfix.S
index 942c4f6..3bb9c84 100644
--- a/arch/m68k/fpsp040/bugfix.S
+++ b/arch/m68k/fpsp040/bugfix.S
@@ -152,9 +152,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |BUGFIX    idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/decbin.S b/arch/m68k/fpsp040/decbin.S
index 2160609..16ed796 100644
--- a/arch/m68k/fpsp040/decbin.S
+++ b/arch/m68k/fpsp040/decbin.S
@@ -69,9 +69,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |DECBIN    idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/do_func.S b/arch/m68k/fpsp040/do_func.S
index 81f6a98..3eff99a 100644
--- a/arch/m68k/fpsp040/do_func.S
+++ b/arch/m68k/fpsp040/do_func.S
@@ -22,9 +22,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 DO_FUNC:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/fpsp.h b/arch/m68k/fpsp040/fpsp.h
index 984a4eb..5df4cd7 100644
--- a/arch/m68k/fpsp040/fpsp.h
+++ b/arch/m68k/fpsp040/fpsp.h
@@ -5,9 +5,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |	fpsp.h --- stack frame offsets during FPSP exception handling
 |
diff --git a/arch/m68k/fpsp040/gen_except.S b/arch/m68k/fpsp040/gen_except.S
index 401d06f..3642cb7 100644
--- a/arch/m68k/fpsp040/gen_except.S
+++ b/arch/m68k/fpsp040/gen_except.S
@@ -29,9 +29,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 GEN_EXCEPT:    |idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/get_op.S b/arch/m68k/fpsp040/get_op.S
index c7c2f37..64c36d7 100644
--- a/arch/m68k/fpsp040/get_op.S
+++ b/arch/m68k/fpsp040/get_op.S
@@ -54,9 +54,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 GET_OP:    |idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/kernel_ex.S b/arch/m68k/fpsp040/kernel_ex.S
index 476b711..45bcf34 100644
--- a/arch/m68k/fpsp040/kernel_ex.S
+++ b/arch/m68k/fpsp040/kernel_ex.S
@@ -12,9 +12,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 KERNEL_EX:    |idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/res_func.S b/arch/m68k/fpsp040/res_func.S
index 8f6b952..d9cdf43 100644
--- a/arch/m68k/fpsp040/res_func.S
+++ b/arch/m68k/fpsp040/res_func.S
@@ -16,9 +16,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 RES_FUNC:    |idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/round.S b/arch/m68k/fpsp040/round.S
index 00f9806..f84ae0d 100644
--- a/arch/m68k/fpsp040/round.S
+++ b/arch/m68k/fpsp040/round.S
@@ -8,9 +8,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |ROUND	idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/sacos.S b/arch/m68k/fpsp040/sacos.S
index 83b00ab..513c7cc 100644
--- a/arch/m68k/fpsp040/sacos.S
+++ b/arch/m68k/fpsp040/sacos.S
@@ -38,9 +38,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SACOS	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/sasin.S b/arch/m68k/fpsp040/sasin.S
index 5647a60..2a269a58 100644
--- a/arch/m68k/fpsp040/sasin.S
+++ b/arch/m68k/fpsp040/sasin.S
@@ -38,9 +38,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SASIN	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/satan.S b/arch/m68k/fpsp040/satan.S
index 20dae22..c8a6649 100644
--- a/arch/m68k/fpsp040/satan.S
+++ b/arch/m68k/fpsp040/satan.S
@@ -43,9 +43,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |satan	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/satanh.S b/arch/m68k/fpsp040/satanh.S
index 20f0781..ba91f77 100644
--- a/arch/m68k/fpsp040/satanh.S
+++ b/arch/m68k/fpsp040/satanh.S
@@ -45,9 +45,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |satanh	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/scale.S b/arch/m68k/fpsp040/scale.S
index 5c9b805..04829dd 100644
--- a/arch/m68k/fpsp040/scale.S
+++ b/arch/m68k/fpsp040/scale.S
@@ -21,9 +21,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SCALE    idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/scosh.S b/arch/m68k/fpsp040/scosh.S
index e81edbb..07d3a4d 100644
--- a/arch/m68k/fpsp040/scosh.S
+++ b/arch/m68k/fpsp040/scosh.S
@@ -49,9 +49,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SCOSH	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/setox.S b/arch/m68k/fpsp040/setox.S
index 0aa75f9..145af54 100644
--- a/arch/m68k/fpsp040/setox.S
+++ b/arch/m68k/fpsp040/setox.S
@@ -331,9 +331,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |setox	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/sgetem.S b/arch/m68k/fpsp040/sgetem.S
index 0fcbd04..d9234f4 100644
--- a/arch/m68k/fpsp040/sgetem.S
+++ b/arch/m68k/fpsp040/sgetem.S
@@ -24,9 +24,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SGETEM	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/sint.S b/arch/m68k/fpsp040/sint.S
index 0f9bd28..0e92d4e 100644
--- a/arch/m68k/fpsp040/sint.S
+++ b/arch/m68k/fpsp040/sint.S
@@ -51,9 +51,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SINT    idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S
index a162919..a8f4161 100644
--- a/arch/m68k/fpsp040/skeleton.S
+++ b/arch/m68k/fpsp040/skeleton.S
@@ -30,9 +30,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |
 |	Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
diff --git a/arch/m68k/fpsp040/slog2.S b/arch/m68k/fpsp040/slog2.S
index 517fa45..fac2c73 100644
--- a/arch/m68k/fpsp040/slog2.S
+++ b/arch/m68k/fpsp040/slog2.S
@@ -96,9 +96,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SLOG2    idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/slogn.S b/arch/m68k/fpsp040/slogn.S
index 2aaa072..d98eaf6 100644
--- a/arch/m68k/fpsp040/slogn.S
+++ b/arch/m68k/fpsp040/slogn.S
@@ -63,9 +63,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |slogn	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/smovecr.S b/arch/m68k/fpsp040/smovecr.S
index a0127fa..73c3651 100644
--- a/arch/m68k/fpsp040/smovecr.S
+++ b/arch/m68k/fpsp040/smovecr.S
@@ -15,9 +15,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SMOVECR	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/srem_mod.S b/arch/m68k/fpsp040/srem_mod.S
index 8c8d7f5..a27e70c 100644
--- a/arch/m68k/fpsp040/srem_mod.S
+++ b/arch/m68k/fpsp040/srem_mod.S
@@ -66,9 +66,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 SREM_MOD:    |idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/ssin.S b/arch/m68k/fpsp040/ssin.S
index 043c91c..a1ef8e0 100644
--- a/arch/m68k/fpsp040/ssin.S
+++ b/arch/m68k/fpsp040/ssin.S
@@ -83,9 +83,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SSIN	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/ssinh.S b/arch/m68k/fpsp040/ssinh.S
index c8b3308..8a560ed 100644
--- a/arch/m68k/fpsp040/ssinh.S
+++ b/arch/m68k/fpsp040/ssinh.S
@@ -49,9 +49,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |SSINH	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/stan.S b/arch/m68k/fpsp040/stan.S
index b5c2a19..f8553aa 100644
--- a/arch/m68k/fpsp040/stan.S
+++ b/arch/m68k/fpsp040/stan.S
@@ -50,9 +50,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |STAN	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/stanh.S b/arch/m68k/fpsp040/stanh.S
index 33b0098..7e12e59 100644
--- a/arch/m68k/fpsp040/stanh.S
+++ b/arch/m68k/fpsp040/stanh.S
@@ -49,9 +49,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |STANH	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/sto_res.S b/arch/m68k/fpsp040/sto_res.S
index 0cdca3b..484b47d 100644
--- a/arch/m68k/fpsp040/sto_res.S
+++ b/arch/m68k/fpsp040/sto_res.S
@@ -19,9 +19,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 STO_RES:	|idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/stwotox.S b/arch/m68k/fpsp040/stwotox.S
index 4e3c140..0d5e6a1 100644
--- a/arch/m68k/fpsp040/stwotox.S
+++ b/arch/m68k/fpsp040/stwotox.S
@@ -76,9 +76,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |STWOTOX	idnt	2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/tbldo.S b/arch/m68k/fpsp040/tbldo.S
index fe60cf4..fd5c37a 100644
--- a/arch/m68k/fpsp040/tbldo.S
+++ b/arch/m68k/fpsp040/tbldo.S
@@ -17,9 +17,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |TBLDO	idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/util.S b/arch/m68k/fpsp040/util.S
index 452f3d6..65b26fa 100644
--- a/arch/m68k/fpsp040/util.S
+++ b/arch/m68k/fpsp040/util.S
@@ -16,9 +16,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 |UTIL	idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/x_bsun.S b/arch/m68k/fpsp040/x_bsun.S
index 039247b..d5a576b 100644
--- a/arch/m68k/fpsp040/x_bsun.S
+++ b/arch/m68k/fpsp040/x_bsun.S
@@ -13,9 +13,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 X_BSUN:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/x_fline.S b/arch/m68k/fpsp040/x_fline.S
index 3917710..264e126 100644
--- a/arch/m68k/fpsp040/x_fline.S
+++ b/arch/m68k/fpsp040/x_fline.S
@@ -13,9 +13,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 X_FLINE:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/x_operr.S b/arch/m68k/fpsp040/x_operr.S
index b0f54bc..e2c371c 100644
--- a/arch/m68k/fpsp040/x_operr.S
+++ b/arch/m68k/fpsp040/x_operr.S
@@ -43,9 +43,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 X_OPERR:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/x_ovfl.S b/arch/m68k/fpsp040/x_ovfl.S
index 22cb8b4..6fe4989 100644
--- a/arch/m68k/fpsp040/x_ovfl.S
+++ b/arch/m68k/fpsp040/x_ovfl.S
@@ -35,9 +35,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 X_OVFL:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/x_snan.S b/arch/m68k/fpsp040/x_snan.S
index 039af57..4ed7664 100644
--- a/arch/m68k/fpsp040/x_snan.S
+++ b/arch/m68k/fpsp040/x_snan.S
@@ -22,9 +22,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 X_SNAN:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/x_store.S b/arch/m68k/fpsp040/x_store.S
index 4282fa6..402dc0c 100644
--- a/arch/m68k/fpsp040/x_store.S
+++ b/arch/m68k/fpsp040/x_store.S
@@ -11,9 +11,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 X_STORE:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/x_unfl.S b/arch/m68k/fpsp040/x_unfl.S
index 077fcc2..eb772ff 100644
--- a/arch/m68k/fpsp040/x_unfl.S
+++ b/arch/m68k/fpsp040/x_unfl.S
@@ -21,9 +21,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 X_UNFL:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/x_unimp.S b/arch/m68k/fpsp040/x_unimp.S
index 920cb94..6f382b2 100644
--- a/arch/m68k/fpsp040/x_unimp.S
+++ b/arch/m68k/fpsp040/x_unimp.S
@@ -22,9 +22,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 X_UNIMP:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68k/fpsp040/x_unsupp.S b/arch/m68k/fpsp040/x_unsupp.S
index 4ec5728..d7cf462 100644
--- a/arch/m68k/fpsp040/x_unsupp.S
+++ b/arch/m68k/fpsp040/x_unsupp.S
@@ -23,9 +23,8 @@
 |		Copyright (C) Motorola, Inc. 1990
 |			All Rights Reserved
 |
-|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
-|	The copyright notice above does not evidence any
-|	actual or intended publication of such source code.
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
 
 X_UNSUPP:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index 99bf438..63c117d 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -39,6 +39,14 @@
 
 asmlinkage void ret_from_fork(void);
 
+/*
+ * The following aren't currently used.
+ */
+void (*pm_idle)(void);
+EXPORT_SYMBOL(pm_idle);
+
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
 
 /*
  * The idle loop on an m68knommu..
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c3e852e..767de84 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -595,6 +595,7 @@
 	select SYS_HAS_CPU_R5000
 	select SYS_HAS_CPU_R10000 if BROKEN
 	select SYS_HAS_CPU_RM7000
+	select SYS_HAS_CPU_NEVADA
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	help
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 2a9f2ef..6a57407 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -53,14 +53,17 @@
 endif
 
 CHECKFLAGS-y				+= -D__linux__ -D__mips__ \
+					   -D_MIPS_SZINT=32 \
 					   -D_ABIO32=1 \
 					   -D_ABIN32=2 \
 					   -D_ABI64=3
 CHECKFLAGS-$(CONFIG_32BIT)		+= -D_MIPS_SIM=_ABIO32 \
 					   -D_MIPS_SZLONG=32 \
+					   -D_MIPS_SZPTR=32 \
 					   -D__PTRDIFF_TYPE__=int
 CHECKFLAGS-$(CONFIG_64BIT)		+= -m64 -D_MIPS_SIM=_ABI64 \
 					   -D_MIPS_SZLONG=64 \
+					   -D_MIPS_SZPTR=64 \
 					   -D__PTRDIFF_TYPE__="long int"
 CHECKFLAGS-$(CONFIG_CPU_BIG_ENDIAN)	+= -D__MIPSEB__
 CHECKFLAGS-$(CONFIG_CPU_LITTLE_ENDIAN)	+= -D__MIPSEL__
@@ -166,79 +169,97 @@
 #
 cflags-$(CONFIG_CPU_R3000)	+= \
 			$(call set_gccflags,r3000,mips1,r3000,mips1,mips1)
+CHECKFLAGS-$(CONFIG_CPU_R3000)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS1
 
 cflags-$(CONFIG_CPU_TX39XX)	+= \
 			$(call set_gccflags,r3900,mips1,r3000,mips1,mips1)
+CHECKFLAGS-$(CONFIG_CPU_TX39XX)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS1
 
 cflags-$(CONFIG_CPU_R6000)	+= \
 			$(call set_gccflags,r6000,mips2,r6000,mips2,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_R6000)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS2
 
 cflags-$(CONFIG_CPU_R4300)	+= \
 			$(call set_gccflags,r4300,mips3,r4300,mips3,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_R4300)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS3
 
 cflags-$(CONFIG_CPU_VR41XX)	+= \
 			$(call set_gccflags,r4100,mips3,r4600,mips3,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_VR41XX)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS3
 
 cflags-$(CONFIG_CPU_R4X00)	+= \
 			$(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_R4X00)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS3
 
 cflags-$(CONFIG_CPU_TX49XX)	+= \
 			$(call set_gccflags,r4600,mips3,r4600,mips3,mips2)  \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_TX49XX)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS3
 
 cflags-$(CONFIG_CPU_MIPS32_R1)	+= \
 			$(call set_gccflags,mips32,mips32,r4600,mips3,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_MIPS32_R1)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS32
 
 cflags-$(CONFIG_CPU_MIPS32_R2)	+= \
 			$(call set_gccflags,mips32r2,mips32r2,r4600,mips3,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_MIPS32_R2)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS32
 
 cflags-$(CONFIG_CPU_MIPS64_R1)	+= \
 			$(call set_gccflags,mips64,mips64,r4600,mips3,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_MIPS64_R1)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS64
 
 cflags-$(CONFIG_CPU_MIPS64_R2)	+= \
 			$(call set_gccflags,mips64r2,mips64r2,r4600,mips3,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_MIPS64_R2)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS64
 
 cflags-$(CONFIG_CPU_R5000)	+= \
 			$(call set_gccflags,r5000,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_R5000)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS4
 
 cflags-$(CONFIG_CPU_R5432)	+= \
 			$(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_R5432)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS4
 
 cflags-$(CONFIG_CPU_NEVADA)	+= \
 			$(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
-#			$(call cc-option,-mmad)
+CHECKFLAGS-$(CONFIG_CPU_NEVADA)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS4
 
 cflags-$(CONFIG_CPU_RM7000)	+= \
 			$(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_RM7000)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS4
 
 cflags-$(CONFIG_CPU_RM9000)	+= \
 			$(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_RM9000)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS4
 
 
 cflags-$(CONFIG_CPU_SB1)	+= \
 			$(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_SB1)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS64
 
 cflags-$(CONFIG_CPU_R8000)	+= \
 			$(call set_gccflags,r8000,mips4,r8000,mips4,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_R8000)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS4
 
 cflags-$(CONFIG_CPU_R10000)	+= \
 			$(call set_gccflags,r10000,mips4,r8000,mips4,mips2) \
 			-Wa,--trap
+CHECKFLAGS-$(CONFIG_CPU_R10000)	+= -D_MIPS_ISA=_MIPS_ISA_MIPS4
 
 ifdef CONFIG_CPU_SB1
 ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
@@ -369,7 +390,7 @@
 # Cobalt Server
 #
 core-$(CONFIG_MIPS_COBALT)	+= arch/mips/cobalt/
-cflags-$(CONFIG_MIPS_COBALT)	+= -Iinclude/asm-mips/cobalt
+cflags-$(CONFIG_MIPS_COBALT)	+= -Iinclude/asm-mips/mach-cobalt
 load-$(CONFIG_MIPS_COBALT)	+= 0xffffffff80080000
 
 #
diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c
index 65b84db..4ffcced 100644
--- a/arch/mips/au1000/common/reset.c
+++ b/arch/mips/au1000/common/reset.c
@@ -151,7 +151,7 @@
 	}
 
 	set_c0_status(ST0_BEV | ST0_ERL);
-	set_c0_config(CONF_CM_UNCACHED);
+	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
 	flush_cache_all();
 	write_c0_wired(0);
 
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index 08c8c85..eb155c0 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -33,6 +33,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/pm.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -125,7 +126,7 @@
 #endif
 	_machine_restart = au1000_restart;
 	_machine_halt = au1000_halt;
-	_machine_power_off = au1000_power_off;
+	pm_power_off = au1000_power_off;
 	board_time_init = au1xxx_time_init;
 	board_timer_setup = au1xxx_timer_setup;
 
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
index f92608e..e75d5e3 100644
--- a/arch/mips/cobalt/int-handler.S
+++ b/arch/mips/cobalt/int-handler.S
@@ -8,7 +8,7 @@
  */
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
-#include <asm/cobalt/cobalt.h>
+#include <asm/mach-cobalt/cobalt.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index 0d90851..f9a1088 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -18,7 +18,7 @@
 #include <asm/gt64120.h>
 #include <asm/ptrace.h>
 
-#include <asm/cobalt/cobalt.h>
+#include <asm/mach-cobalt/cobalt.h>
 
 extern void cobalt_handle_int(void);
 
diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c
index 805a0e8..753dfcc 100644
--- a/arch/mips/cobalt/reset.c
+++ b/arch/mips/cobalt/reset.c
@@ -16,7 +16,7 @@
 #include <asm/reboot.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
-#include <asm/cobalt/cobalt.h>
+#include <asm/mach-cobalt/cobalt.h>
 
 void cobalt_machine_halt(void)
 {
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index d358a11..b9713a7 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 1996, 1997, 2004, 05 by Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
  *
  */
@@ -13,6 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/pm.h>
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 
@@ -25,7 +26,7 @@
 #include <asm/gt64120.h>
 #include <asm/serial.h>
 
-#include <asm/cobalt/cobalt.h>
+#include <asm/mach-cobalt/cobalt.h>
 
 extern void cobalt_machine_restart(char *command);
 extern void cobalt_machine_halt(void);
@@ -99,7 +100,7 @@
 
 	_machine_restart = cobalt_machine_restart;
 	_machine_halt = cobalt_machine_halt;
-	_machine_power_off = cobalt_machine_power_off;
+	pm_power_off = cobalt_machine_power_off;
 
 	board_timer_setup = cobalt_timer_setup;
 
@@ -139,7 +140,7 @@
 		uart.type	= PORT_UNKNOWN;
 		uart.uartclk	= 18432000;
 		uart.irq	= COBALT_SERIAL_IRQ;
-		uart.flags	= STD_COM_FLAGS;
+		uart.flags	= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 		uart.iobase	= 0xc800000;
 		uart.iotype	= UPIO_PORT;
 
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 967e7ac..a34db6e 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -102,6 +102,7 @@
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_HAS_CPU_NEVADA=y
 CONFIG_SYS_HAS_CPU_RM7000=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index dee4460..c02beca 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-rc2
-# Thu Nov 24 01:07:00 2005
+# Linux kernel version: 2.6.16-rc2
+# Fri Feb  3 17:14:27 2006
 #
 CONFIG_MIPS=y
 
@@ -147,26 +147,27 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_SYSCTL is not set
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 # CONFIG_BUG is not set
+CONFIG_ELF_CORE=y
 # CONFIG_BASE_FULL is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SHMEM is not set
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=1
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -266,11 +267,7 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_CRYPT_TKIP=y
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -323,7 +320,7 @@
 #
 # SCSI device support
 #
-CONFIG_RAID_ATTRS=y
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -366,24 +363,16 @@
 #
 # PHY device support
 #
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
+# CONFIG_MII is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_DM9000 is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
@@ -479,6 +468,7 @@
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -518,6 +508,12 @@
 # CONFIG_I2C is not set
 
 #
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -592,11 +588,14 @@
 #
 
 #
+# EDAC - error detection and reporting (RAS)
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
@@ -677,6 +676,7 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
@@ -690,31 +690,7 @@
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
 
 #
 # Hardware crypto devices
@@ -724,8 +700,6 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c
index 11535be..91456b0 100644
--- a/arch/mips/ddb5xxx/ddb5074/setup.c
+++ b/arch/mips/ddb5xxx/ddb5074/setup.c
@@ -14,6 +14,7 @@
 #include <linux/ide.h>
 #include <linux/ioport.h>
 #include <linux/irq.h>
+#include <linux/pm.h>
 
 #include <asm/addrspace.h>
 #include <asm/bcache.h>
@@ -95,7 +96,7 @@
 
 	_machine_restart = ddb_machine_restart;
 	_machine_halt = ddb_machine_halt;
-	_machine_power_off = ddb_machine_power_off;
+	pm_power_off = ddb_machine_power_off;
 
 	ddb_out32(DDB_BAR0, 0);
 
diff --git a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c
index f4e480a..c902ade 100644
--- a/arch/mips/ddb5xxx/ddb5476/setup.c
+++ b/arch/mips/ddb5xxx/ddb5476/setup.c
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/pci.h>
+#include <linux/pm.h>
 
 #include <asm/addrspace.h>
 #include <asm/bcache.h>
@@ -133,7 +134,7 @@
 
 	_machine_restart = ddb_machine_restart;
 	_machine_halt = ddb_machine_halt;
-	_machine_power_off = ddb_machine_power_off;
+	pm_power_off = ddb_machine_power_off;
 
 	/* request io port/mem resources  */
 	if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
diff --git a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c
index 8116335..2f56603 100644
--- a/arch/mips/ddb5xxx/ddb5477/setup.c
+++ b/arch/mips/ddb5xxx/ddb5477/setup.c
@@ -26,6 +26,7 @@
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
+#include <linux/pm.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -182,7 +183,7 @@
 
 	_machine_restart = ddb_machine_restart;
 	_machine_halt = ddb_machine_halt;
-	_machine_power_off = ddb_machine_power_off;
+	pm_power_off = ddb_machine_power_off;
 
 	/* setup resource limits */
 	ioport_resource.end = DDB_PCI0_IO_SIZE + DDB_PCI1_IO_SIZE - 1;
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 9ef54fe..7c1ca8f 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
+#include <linux/pm.h>
 
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
@@ -158,7 +159,7 @@
 
 	_machine_restart = dec_machine_restart;
 	_machine_halt = dec_machine_halt;
-	_machine_power_off = dec_machine_power_off;
+	pm_power_off = dec_machine_power_off;
 
 	ioport_resource.start = ~0UL;
 	ioport_resource.end = 0UL;
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
index 98b5a96..6d859d1 100644
--- a/arch/mips/gt64120/ev64120/setup.c
+++ b/arch/mips/gt64120/ev64120/setup.c
@@ -34,6 +34,8 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/timex.h>
+#include <linux/pm.h>
+
 #include <asm/bootinfo.h>
 #include <asm/page.h>
 #include <asm/io.h>
@@ -73,7 +75,7 @@
 {
 	_machine_restart = galileo_machine_restart;
 	_machine_halt = galileo_machine_halt;
-	_machine_power_off = galileo_machine_power_off;
+	pm_power_off = galileo_machine_power_off;
 
 	board_time_init = gt64120_time_init;
 	set_io_port_base(KSEG1);
diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c
index 0d07c33..20b65d3 100644
--- a/arch/mips/gt64120/momenco_ocelot/setup.c
+++ b/arch/mips/gt64120/momenco_ocelot/setup.c
@@ -4,7 +4,7 @@
  * BRIEF MODULE DESCRIPTION
  * Momentum Computer Ocelot (CP7000) - board dependent boot routines
  *
- * Copyright (C) 1996, 1997, 2001  Ralf Baechle
+ * Copyright (C) 1996, 1997, 2001, 06  Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2000 RidgeRun, Inc.
  * Copyright (C) 2001 Red Hat, Inc.
  * Copyright (C) 2002 Momentum Computer
@@ -47,6 +47,8 @@
 #include <linux/pci.h>
 #include <linux/timex.h>
 #include <linux/vmalloc.h>
+#include <linux/pm.h>
+
 #include <asm/time.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
@@ -159,7 +161,7 @@
 
 	_machine_restart = momenco_ocelot_restart;
 	_machine_halt = momenco_ocelot_halt;
-	_machine_power_off = momenco_ocelot_power_off;
+	pm_power_off = momenco_ocelot_power_off;
 
 	/*
 	 * initrd_start = (ulong)ocelot_initrd_start;
diff --git a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c
index 062429d..fc73c8d 100644
--- a/arch/mips/ite-boards/generic/it8172_setup.c
+++ b/arch/mips/ite-boards/generic/it8172_setup.c
@@ -34,6 +34,7 @@
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
+#include <linux/pm.h>
 
 #include <asm/cpu.h>
 #include <asm/time.h>
@@ -125,7 +126,7 @@
 
 	_machine_restart = it8172_restart;
 	_machine_halt = it8172_halt;
-	_machine_power_off = it8172_power_off;
+	pm_power_off = it8172_power_off;
 
 	/*
 	 * IO/MEM resources.
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index 044df9d..4036dc4 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -19,6 +19,8 @@
 #include <linux/console.h>
 #include <linux/fb.h>
 #include <linux/ide.h>
+#include <linux/pm.h>
+
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/jazz.h>
@@ -79,7 +81,7 @@
 
 	_machine_restart = jazz_machine_restart;
 	_machine_halt = jazz_machine_halt;
-	_machine_power_off = jazz_machine_power_off;
+	pm_power_off = jazz_machine_power_off;
 
 #warning "Somebody should check if screen_info is ok for Jazz."
 
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
index 4763957..9359cc4 100644
--- a/arch/mips/jmr3927/rbhma3100/setup.c
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -44,6 +44,7 @@
 #include <linux/ioport.h>
 #include <linux/param.h>	/* for HZ */
 #include <linux/delay.h>
+#include <linux/pm.h>
 #ifdef CONFIG_SERIAL_TXX9
 #include <linux/tty.h>
 #include <linux/serial.h>
@@ -211,7 +212,7 @@
 
 	_machine_restart = jmr3927_machine_restart;
 	_machine_halt = jmr3927_machine_halt;
-	_machine_power_off = jmr3927_machine_power_off;
+	pm_power_off = jmr3927_machine_power_off;
 
 	/*
 	 * IO/MEM resources.
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index fac48ad..292f8b2 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -2,8 +2,8 @@
  * Processor capabilities determination functions.
  *
  * Copyright (C) xxxx  the Anonymous
+ * Copyright (C) 1994 - 2006 Ralf Baechle
  * Copyright (C) 2003, 2004  Maciej W. Rozycki
- * Copyright (C) 1994 - 2003 Ralf Baechle
  * Copyright (C) 2001, 2004  MIPS Inc.
  *
  * This program is free software; you can redistribute it and/or
@@ -641,10 +641,9 @@
 	switch (c->processor_id & 0xff00) {
 	case PRID_IMP_SB1:
 		c->cputype = CPU_SB1;
-#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
 		/* FPU in pass1 is known to have issues. */
-		c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
-#endif
+		if ((c->processor_id & 0xff) < 0x20)
+			c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
 		break;
 	case PRID_IMP_SB1A:
 		c->cputype = CPU_SB1A;
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index 96d18c4..d4f88e0 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -178,7 +178,7 @@
  */
 static DEFINE_SPINLOCK(kgdb_lock);
 static raw_spinlock_t kgdb_cpulock[NR_CPUS] = {
-	[0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED;
+	[0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED,
 };
 
 /*
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index aa18a8b..13f22d1 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -233,11 +233,11 @@
 NESTED(nmi_handler, PT_SIZE, sp)
 	.set	push
 	.set	noat
-	.set	mips3
 	SAVE_ALL
  	move	a0, sp
 	jal	nmi_exception_handler
 	RESTORE_ALL
+	.set	mips3
 	eret
 	.set	pop
 	END(nmi_handler)
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index fa98f10..5232fc7 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -4,6 +4,7 @@
  * for more details.
  *
  * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others.
+ * Copyright (C) 2005, 2006 by Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  * Copyright (C) 2004 Thiemo Seufer
  */
@@ -58,8 +59,8 @@
 	}
 }
 
-extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
-extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
+extern void do_signal(struct pt_regs *regs);
+extern void do_signal32(struct pt_regs *regs);
 
 /*
  * Native o32 and N64 ABI without DSP ASE
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 0c82b25..0d5cf97 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -88,7 +88,7 @@
 		ret = -EIO;
 		if (copied != sizeof(tmp))
 			break;
-		ret = put_user(tmp, (unsigned int *) (unsigned long) data);
+		ret = put_user(tmp, (unsigned int __user *) (unsigned long) data);
 		break;
 	}
 
@@ -174,8 +174,10 @@
 		case FPC_EIR: {	/* implementation / version register */
 			unsigned int flags;
 
-			if (!cpu_has_fpu)
+			if (!cpu_has_fpu) {
+				tmp = 0;
 				break;
+			}
 
 			preempt_disable();
 			if (cpu_has_mipsmt) {
@@ -194,15 +196,18 @@
 			preempt_enable();
 			break;
 		}
-		case DSP_BASE ... DSP_BASE + 5:
+		case DSP_BASE ... DSP_BASE + 5: {
+			dspreg_t *dregs;
+
 			if (!cpu_has_dsp) {
 				tmp = 0;
 				ret = -EIO;
 				goto out_tsk;
 			}
-			dspreg_t *dregs = __get_dsp_regs(child);
+			dregs = __get_dsp_regs(child);
 			tmp = (unsigned long) (dregs[addr - DSP_BASE]);
 			break;
+		}
 		case DSP_CONTROL:
 			if (!cpu_has_dsp) {
 				tmp = 0;
@@ -216,7 +221,7 @@
 			ret = -EIO;
 			goto out_tsk;
 		}
-		ret = put_user(tmp, (unsigned *) (unsigned long) data);
+		ret = put_user(tmp, (unsigned __user *) (unsigned long) data);
 		break;
 	}
 
@@ -304,15 +309,18 @@
 			else
 				child->thread.fpu.soft.fcr31 = data;
 			break;
-		case DSP_BASE ... DSP_BASE + 5:
+		case DSP_BASE ... DSP_BASE + 5: {
+			dspreg_t *dregs;
+
 			if (!cpu_has_dsp) {
 				ret = -EIO;
 				break;
 			}
 
-			dspreg_t *dregs = __get_dsp_regs(child);
+			dregs = __get_dsp_regs(child);
 			dregs[addr - DSP_BASE] = data;
 			break;
+		}
 		case DSP_CONTROL:
 			if (!cpu_has_dsp) {
 				ret = -EIO;
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
index 5e37df3..621037d 100644
--- a/arch/mips/kernel/reset.c
+++ b/arch/mips/kernel/reset.c
@@ -3,17 +3,16 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 by Ralf Baechle
+ * Copyright (C) 2001, 06 by Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2001 MIPS Technologies, Inc.
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/pm.h>
 #include <linux/types.h>
 #include <linux/reboot.h>
-#include <asm/reboot.h>
 
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
+#include <asm/reboot.h>
 
 /*
  * Urgs ...  Too many MIPS machines to handle this in a generic way.
@@ -22,23 +21,22 @@
  */
 void (*_machine_restart)(char *command);
 void (*_machine_halt)(void);
-void (*_machine_power_off)(void);
+void (*pm_power_off)(void);
 
 void machine_restart(char *command)
 {
-	_machine_restart(command);
+	if (_machine_restart)
+		_machine_restart(command);
 }
 
 void machine_halt(void)
 {
-	_machine_halt();
+	if (_machine_halt)
+		_machine_halt();
 }
 
 void machine_power_off(void)
 {
 	if (pm_power_off)
 		pm_power_off();
-
-	_machine_power_off();
 }
-
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 1d85511..986a9cf 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2005, 06 Ralf Baechle (ralf@linux-mips.org)
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -20,9 +21,12 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
+
 #include <asm/mipsmtregs.h>
 #include <asm/bitops.h>
 #include <asm/cpu.h>
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index a42e0e8..d83e033 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -617,6 +617,23 @@
 	sys	sys_inotify_init	0
 	sys	sys_inotify_add_watch	3	/* 4285 */
 	sys	sys_inotify_rm_watch	2
+	sys	sys_migrate_pages	4
+	sys	sys_openat		4
+	sys	sys_mkdirat		3
+	sys	sys_mknodat		4	/* 4290 */
+	sys	sys_fchownat		5
+	sys	sys_futimesat		3
+	sys	sys_fstatat64		4
+	sys	sys_unlinkat		3
+	sys	sys_renameat		4	/* 4295 */
+	sys	sys_linkat		4
+	sys	sys_symlinkat		3
+	sys	sys_readlinkat		4
+	sys	sys_fchmodat		3
+	sys	sys_faccessat		3	/* 4300 */
+	sys	sys_pselect6		6
+	sys	sys_ppoll		5
+	sys	sys_unshare		1
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 47bfbd4..98bf25d 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -443,3 +443,20 @@
 	PTR	sys_inotify_init
 	PTR	sys_inotify_add_watch
 	PTR	sys_inotify_rm_watch		/* 5245 */
+	PTR	sys_migrate_pages
+	PTR	sys_openat
+	PTR	sys_mkdirat
+	PTR	sys_mknodat
+	PTR	sys_fchownat			/* 5250 */
+	PTR	sys_futimesat
+	PTR	sys_newfstatat
+	PTR	sys_unlinkat
+	PTR	sys_renameat
+	PTR	sys_linkat			/* 5255 */
+	PTR	sys_symlinkat
+	PTR	sys_readlinkat
+	PTR	sys_fchmodat
+	PTR	sys_faccessat
+	PTR	sys_pselect6			/* 5260 */
+	PTR	sys_ppoll
+	PTR	sys_unshare
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index b465ced..bc4980c 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -369,3 +369,20 @@
 	PTR	sys_inotify_init
 	PTR	sys_inotify_add_watch
 	PTR	sys_inotify_rm_watch
+	PTR	sys_migrate_pages		/* 6250 */
+	PTR	sys_openat
+	PTR	sys_mkdirat
+	PTR	sys_mknodat
+	PTR	sys_fchownat
+	PTR	sys_futimesat			/* 6255 */
+	PTR	sys_newfstatat
+	PTR	sys_unlinkat
+	PTR	sys_renameat
+	PTR	sys_linkat
+	PTR	sys_symlinkat			/* 6260 */
+	PTR	sys_readlinkat
+	PTR	sys_fchmodat
+	PTR	sys_faccessat
+	PTR	sys_pselect6
+	PTR	sys_ppoll			/* 6265 */
+	PTR	sys_unshare
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 3d338ca..5b04140 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -491,4 +491,21 @@
 	PTR	sys_inotify_init
 	PTR	sys_inotify_add_watch		/* 4285 */
 	PTR	sys_inotify_rm_watch
+	PTR	sys_migrate_pages
+	PTR	compat_sys_openat
+	PTR	sys_mkdirat
+	PTR	sys_mknodat			/* 4290 */
+	PTR	sys_fchownat
+	PTR	compat_sys_futimesat
+	PTR	compat_sys_newfstatat
+	PTR	sys_unlinkat
+	PTR	sys_renameat			/* 4295 */
+	PTR	sys_linkat
+	PTR	sys_symlinkat
+	PTR	sys_readlinkat
+	PTR	sys_fchmodat
+	PTR	sys_faccessat			/* 4300 */
+	PTR	sys_pselect6
+	PTR	sys_ppoll
+	PTR	sys_unshare
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index 0f66ae58..0fbc492 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -11,7 +11,7 @@
 #include <linux/config.h>
 
 static inline int
-setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 {
 	int err = 0;
 
@@ -82,7 +82,7 @@
 }
 
 static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 {
 	unsigned int used_math;
 	unsigned long treg;
@@ -157,7 +157,7 @@
 /*
  * Determine which stack to use..
  */
-static inline void *
+static inline void __user *
 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 {
 	unsigned long sp;
@@ -176,7 +176,7 @@
 	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
-	return (void *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK));
+	return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK));
 }
 
 static inline int install_sigtramp(unsigned int __user *tramp,
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 7d1800f..c974cc9 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -39,8 +39,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-int do_signal(sigset_t *oldset, struct pt_regs *regs);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -50,7 +48,7 @@
 __attribute_used__ noinline static int
 _sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
-	sigset_t saveset, newset;
+	sigset_t newset;
 	sigset_t __user *uset;
 
 	uset = (sigset_t __user *) regs.regs[4];
@@ -59,19 +57,15 @@
 	sigdelsetmask(&newset, ~_BLOCKABLE);
 
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	current->blocked = newset;
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs.regs[2] = EINTR;
-	regs.regs[7] = 1;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, &regs))
-			return -EINTR;
-	}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
 }
 #endif
 
@@ -79,7 +73,7 @@
 __attribute_used__ noinline static int
 _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
-	sigset_t saveset, newset;
+	sigset_t newset;
 	sigset_t __user *unewset;
 	size_t sigsetsize;
 
@@ -94,19 +88,15 @@
 	sigdelsetmask(&newset, ~_BLOCKABLE);
 
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	current->blocked = newset;
         recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs.regs[2] = EINTR;
-	regs.regs[7] = 1;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, &regs))
-			return -EINTR;
-	}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
 }
 
 #ifdef CONFIG_TRAD_SIGNALS
@@ -199,10 +189,10 @@
 __attribute_used__ noinline static void
 _sys_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
-	struct sigframe *frame;
+	struct sigframe __user *frame;
 	sigset_t blocked;
 
-	frame = (struct sigframe *) regs.regs[29];
+	frame = (struct sigframe __user *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
@@ -236,11 +226,11 @@
 __attribute_used__ noinline static void
 _sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
-	struct rt_sigframe *frame;
+	struct rt_sigframe __user *frame;
 	sigset_t set;
 	stack_t st;
 
-	frame = (struct rt_sigframe *) regs.regs[29];
+	frame = (struct rt_sigframe __user *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
@@ -259,7 +249,7 @@
 		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, regs.regs[29]);
+	do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
 
 	/*
 	 * Don't let your children do this ...
@@ -279,7 +269,7 @@
 int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set)
 {
-	struct sigframe *frame;
+	struct sigframe __user *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -315,18 +305,18 @@
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, frame->regs[31]);
 #endif
-        return 1;
+        return 0;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
-	return 0;
+	return -EFAULT;
 }
 #endif
 
 int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set, siginfo_t *info)
 {
-	struct rt_sigframe *frame;
+	struct rt_sigframe __user *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -340,7 +330,7 @@
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->rs_uc.uc_flags);
-	err |= __put_user(0, &frame->rs_uc.uc_link);
+	err |= __put_user(NULL, &frame->rs_uc.uc_link);
 	err |= __put_user((void *)current->sas_ss_sp,
 	                  &frame->rs_uc.uc_stack.ss_sp);
 	err |= __put_user(sas_ss_flags(regs->regs[29]),
@@ -375,11 +365,11 @@
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
 #endif
-	return 1;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
-	return 0;
+	return -EFAULT;
 }
 
 static inline int handle_signal(unsigned long sig, siginfo_t *info,
@@ -393,7 +383,7 @@
 		regs->regs[2] = EINTR;
 		break;
 	case ERESTARTSYS:
-		if(!(ka->sa.sa_flags & SA_RESTART)) {
+		if (!(ka->sa.sa_flags & SA_RESTART)) {
 			regs->regs[2] = EINTR;
 			break;
 		}
@@ -420,9 +410,10 @@
 	return ret;
 }
 
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
+void do_signal(struct pt_regs *regs)
 {
 	struct k_sigaction ka;
+	sigset_t *oldset;
 	siginfo_t info;
 	int signr;
 
@@ -432,17 +423,31 @@
 	 * if so.
 	 */
 	if (!user_mode(regs))
-		return 1;
+		return;
 
 	if (try_to_freeze())
 		goto no_signal;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
+
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0)
-		return handle_signal(signr, &info, &ka, oldset, regs);
+	if (signr > 0) {
+		/* Whee!  Actually deliver the signal.  */
+		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+			/*
+			 * A signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag.
+			 */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+	}
 
 no_signal:
 	/*
@@ -463,18 +468,25 @@
 			regs->cp0_epc -= 4;
 		}
 	}
-	return 0;
+
+	/*
+	 * If there's no signal to deliver, we just put the saved sigmask
+	 * back
+	 */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
 
 /*
  * notification of userspace execution resumption
- * - triggered by current->work.notify_resume
+ * - triggered by the TIF_WORK_MASK flags
  */
-asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
+asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 	__u32 thread_info_flags)
 {
 	/* deal with pending signal delivery */
-	if (thread_info_flags & _TIF_SIGPENDING) {
-		current->thread.abi->do_signal(oldset, regs);
-	}
+	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+		current->thread.abi->do_signal(regs);
 }
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 98b185b..da3271e 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -144,7 +144,7 @@
 extern void __put_sigset_unknown_nsig(void);
 extern void __get_sigset_unknown_nsig(void);
 
-static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t *ubuf)
+static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
 {
 	int err = 0;
 
@@ -269,7 +269,7 @@
 		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
 			return -EFAULT;
 		err |= __get_user(handler, &act->sa_handler);
-		new_ka.sa.sa_handler = (void*)(s64)handler;
+		new_ka.sa.sa_handler = (void __user *)(s64)handler;
 		err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		err |= __get_user(mask, &act->sa_mask.sig[0]);
 		if (err)
@@ -299,8 +299,8 @@
 
 asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
 {
-	const stack32_t *uss = (const stack32_t *) regs.regs[4];
-	stack32_t *uoss = (stack32_t *) regs.regs[5];
+	const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
+	stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
 	unsigned long usp = regs.regs[29];
 	stack_t kss, koss;
 	int ret, err = 0;
@@ -319,7 +319,8 @@
 	}
 
 	set_fs (KERNEL_DS);
-	ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp);
+	ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
+			     uoss ? (stack_t __user *)&koss : NULL, usp);
 	set_fs (old_fs);
 
 	if (!ret && uoss) {
@@ -335,7 +336,7 @@
 	return ret;
 }
 
-static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
+static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc)
 {
 	u32 used_math;
 	int err = 0;
@@ -420,7 +421,7 @@
 #endif
 };
 
-int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
 	int err;
 
@@ -455,7 +456,7 @@
 			err |= __put_user(from->si_uid, &to->si_uid);
 			break;
 		case __SI_FAULT >> 16:
-			err |= __put_user((long)from->si_addr, &to->si_addr);
+			err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
 			break;
 		case __SI_POLL >> 16:
 			err |= __put_user(from->si_band, &to->si_band);
@@ -476,10 +477,10 @@
 __attribute_used__ noinline static void
 _sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
-	struct sigframe *frame;
+	struct sigframe __user *frame;
 	sigset_t blocked;
 
-	frame = (struct sigframe *) regs.regs[29];
+	frame = (struct sigframe __user *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
@@ -512,13 +513,13 @@
 __attribute_used__ noinline static void
 _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
-	struct rt_sigframe32 *frame;
+	struct rt_sigframe32 __user *frame;
 	mm_segment_t old_fs;
 	sigset_t set;
 	stack_t st;
 	s32 sp;
 
-	frame = (struct rt_sigframe32 *) regs.regs[29];
+	frame = (struct rt_sigframe32 __user *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
@@ -546,7 +547,7 @@
 	   call it and ignore errors.  */
 	old_fs = get_fs();
 	set_fs (KERNEL_DS);
-	do_sigaltstack(&st, NULL, regs.regs[29]);
+	do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
 	set_fs (old_fs);
 
 	/*
@@ -564,7 +565,7 @@
 }
 
 static inline int setup_sigcontext32(struct pt_regs *regs,
-				     struct sigcontext32 *sc)
+				     struct sigcontext32 __user *sc)
 {
 	int err = 0;
 
@@ -623,8 +624,9 @@
 /*
  * Determine which stack to use..
  */
-static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-				 size_t frame_size)
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+					struct pt_regs *regs,
+					size_t frame_size)
 {
 	unsigned long sp;
 
@@ -642,13 +644,13 @@
 	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
-	return (void *)((sp - frame_size) & ALMASK);
+	return (void __user *)((sp - frame_size) & ALMASK);
 }
 
 int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set)
 {
-	struct sigframe *frame;
+	struct sigframe __user *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -692,17 +694,17 @@
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, frame->sf_code);
 #endif
-	return 1;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
-	return 0;
+	return -EFAULT;
 }
 
 int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set, siginfo_t *info)
 {
-	struct rt_sigframe32 *frame;
+	struct rt_sigframe32 __user *frame;
 	int err = 0;
 	s32 sp;
 
@@ -763,11 +765,11 @@
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, frame->rs_code);
 #endif
-	return 1;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
-	return 0;
+	return -EFAULT;
 }
 
 static inline int handle_signal(unsigned long sig, siginfo_t *info,
@@ -855,7 +857,7 @@
 }
 
 asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
-				  struct sigaction32 *oact,
+				  struct sigaction32 __user *oact,
 				  unsigned int sigsetsize)
 {
 	struct k_sigaction new_sa, old_sa;
@@ -872,7 +874,7 @@
 		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
 			return -EFAULT;
 		err |= __get_user(handler, &act->sa_handler);
-		new_sa.sa.sa_handler = (void*)(s64)handler;
+		new_sa.sa.sa_handler = (void __user *)(s64)handler;
 		err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
 		err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
 		if (err)
@@ -899,7 +901,7 @@
 }
 
 asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set,
-	compat_sigset_t *oset, unsigned int sigsetsize)
+	compat_sigset_t __user *oset, unsigned int sigsetsize)
 {
 	sigset_t old_set, new_set;
 	int ret;
@@ -909,8 +911,9 @@
 		return -EFAULT;
 
 	set_fs (KERNEL_DS);
-	ret = sys_rt_sigprocmask(how, set ? &new_set : NULL,
-				 oset ? &old_set : NULL, sigsetsize);
+	ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
+				 oset ? (sigset_t __user *)&old_set : NULL,
+				 sigsetsize);
 	set_fs (old_fs);
 
 	if (!ret && oset && put_sigset(&old_set, oset))
@@ -919,7 +922,7 @@
 	return ret;
 }
 
-asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset,
+asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
 	unsigned int sigsetsize)
 {
 	int ret;
@@ -927,7 +930,7 @@
 	mm_segment_t old_fs = get_fs();
 
 	set_fs (KERNEL_DS);
-	ret = sys_rt_sigpending(&set, sigsetsize);
+	ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
 	set_fs (old_fs);
 
 	if (!ret && put_sigset(&set, uset))
@@ -936,7 +939,7 @@
 	return ret;
 }
 
-asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo)
+asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
 {
 	siginfo_t info;
 	int ret;
@@ -946,7 +949,7 @@
 	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
 		return -EFAULT;
 	set_fs (KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, &info);
+	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
 	set_fs (old_fs);
 	return ret;
 }
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index ec61b26..384fc4a 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -48,6 +48,8 @@
 #define __NR_N32_rt_sigreturn		6211
 #define __NR_N32_restart_syscall	6214
 
+#define DEBUG_SIG 0
+
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 /* IRIX compatible stack_t  */
@@ -83,12 +85,12 @@
 __attribute_used__ noinline static void
 _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
-	struct rt_sigframe_n32 *frame;
+	struct rt_sigframe_n32 __user *frame;
 	sigset_t set;
 	stack_t st;
 	s32 sp;
 
-	frame = (struct rt_sigframe_n32 *) regs.regs[29];
+	frame = (struct rt_sigframe_n32 __user *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
@@ -114,7 +116,7 @@
 
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, regs.regs[29]);
+	do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
 
 	/*
 	 * Don't let your children do this ...
@@ -133,7 +135,7 @@
 int setup_rt_frame_n32(struct k_sigaction * ka,
 	struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
 {
-	struct rt_sigframe_n32 *frame;
+	struct rt_sigframe_n32 __user *frame;
 	int err = 0;
 	s32 sp;
 
@@ -184,9 +186,9 @@
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
 #endif
-	return 1;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
-	return 0;
+	return -EFAULT;
 }
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 3323584..1da2eeb 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -212,12 +212,12 @@
 	int error;
 	char * filename;
 
-	filename = getname((char *) (long)regs.regs[4]);
+	filename = getname((char __user *) (long)regs.regs[4]);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
-	error = do_execve(filename, (char **) (long)regs.regs[5],
-	                  (char **) (long)regs.regs[6], &regs);
+	error = do_execve(filename, (char __user *__user *) (long)regs.regs[5],
+	                  (char __user *__user *) (long)regs.regs[6], &regs);
 	putname(filename);
 
 out:
@@ -227,7 +227,7 @@
 /*
  * Compacrapability ...
  */
-asmlinkage int sys_uname(struct old_utsname * name)
+asmlinkage int sys_uname(struct old_utsname __user * name)
 {
 	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
 		return 0;
@@ -237,7 +237,7 @@
 /*
  * Compacrapability ...
  */
-asmlinkage int sys_olduname(struct oldold_utsname * name)
+asmlinkage int sys_olduname(struct oldold_utsname __user * name)
 {
 	int error;
 
@@ -274,7 +274,7 @@
 asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
 {
 	int	tmp, len;
-	char	*name;
+	char	__user *name;
 
 	switch(cmd) {
 	case SETNAME: {
@@ -283,7 +283,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		name = (char *) arg1;
+		name = (char __user *) arg1;
 
 		len = strncpy_from_user(nodename, name, __NEW_UTS_LEN);
 		if (len < 0)
@@ -324,7 +324,7 @@
  * This is really horribly ugly.
  */
 asmlinkage int sys_ipc (uint call, int first, int second,
-			unsigned long third, void *ptr, long fifth)
+			unsigned long third, void __user *ptr, long fifth)
 {
 	int version, ret;
 
@@ -333,24 +333,25 @@
 
 	switch (call) {
 	case SEMOP:
-		return sys_semtimedop (first, (struct sembuf *)ptr, second,
-		                       NULL);
+		return sys_semtimedop (first, (struct sembuf __user *)ptr,
+		                       second, NULL);
 	case SEMTIMEDOP:
-		return sys_semtimedop (first, (struct sembuf *)ptr, second,
-		                       (const struct timespec __user *)fifth);
+		return sys_semtimedop (first, (struct sembuf __user *)ptr,
+				       second,
+				       (const struct timespec __user *)fifth);
 	case SEMGET:
 		return sys_semget (first, second, third);
 	case SEMCTL: {
 		union semun fourth;
 		if (!ptr)
 			return -EINVAL;
-		if (get_user(fourth.__pad, (void **) ptr))
+		if (get_user(fourth.__pad, (void *__user *) ptr))
 			return -EFAULT;
 		return sys_semctl (first, second, third, fourth);
 	}
 
 	case MSGSND:
-		return sys_msgsnd (first, (struct msgbuf *) ptr,
+		return sys_msgsnd (first, (struct msgbuf __user *) ptr,
 				   second, third);
 	case MSGRCV:
 		switch (version) {
@@ -360,7 +361,7 @@
 				return -EINVAL;
 
 			if (copy_from_user(&tmp,
-					   (struct ipc_kludge *) ptr,
+					   (struct ipc_kludge __user *) ptr,
 					   sizeof (tmp)))
 				return -EFAULT;
 			return sys_msgrcv (first, tmp.msgp, second,
@@ -368,35 +369,38 @@
 		}
 		default:
 			return sys_msgrcv (first,
-					   (struct msgbuf *) ptr,
+					   (struct msgbuf __user *) ptr,
 					   second, fifth, third);
 		}
 	case MSGGET:
 		return sys_msgget ((key_t) first, second);
 	case MSGCTL:
-		return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+		return sys_msgctl (first, second,
+				   (struct msqid_ds __user *) ptr);
 
 	case SHMAT:
 		switch (version) {
 		default: {
 			ulong raddr;
-			ret = do_shmat (first, (char *) ptr, second, &raddr);
+			ret = do_shmat (first, (char __user *) ptr, second,
+					&raddr);
 			if (ret)
 				return ret;
-			return put_user (raddr, (ulong *) third);
+			return put_user (raddr, (ulong __user *) third);
 		}
 		case 1:	/* iBCS2 emulator entry point */
 			if (!segment_eq(get_fs(), get_ds()))
 				return -EINVAL;
-			return do_shmat (first, (char *) ptr, second, (ulong *) third);
+			return do_shmat (first, (char __user *) ptr, second,
+					 (ulong *) third);
 		}
 	case SHMDT:
-		return sys_shmdt ((char *)ptr);
+		return sys_shmdt ((char __user *)ptr);
 	case SHMGET:
 		return sys_shmget (first, second, third);
 	case SHMCTL:
 		return sys_shmctl (first, second,
-				   (struct shmid_ds *) ptr);
+				   (struct shmid_ds __user *) ptr);
 	default:
 		return -ENOSYS;
 	}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 59a1879..c9d2b51 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1168,7 +1168,7 @@
 #endif
 	if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
 		status_set |= ST0_XX;
-	change_c0_status(ST0_CU|ST0_MX|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
+	change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
 			 status_set);
 
 	if (cpu_has_dsp)
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 25cc856..ff699db 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -1,4 +1,5 @@
 #include <linux/config.h>
+#include <asm/asm-offsets.h>
 #include <asm-generic/vmlinux.lds.h>
 
 #undef mips		/* CPP really sucks for this job  */
@@ -64,10 +65,10 @@
      we can shorten the on-disk segment size.  */
   .sdata     : { *(.sdata) }
 
-  . = ALIGN(4096);
+  . = ALIGN(_PAGE_SIZE);
   __nosave_begin = .;
   .data_nosave : { *(.data.nosave) }
-  . = ALIGN(4096);
+  . = ALIGN(_PAGE_SIZE);
   __nosave_end = .;
 
   . = ALIGN(32);
@@ -76,7 +77,7 @@
   _edata =  .;			/* End of data section */
 
   /* will be freed after init */
-  . = ALIGN(4096);		/* Init code and data */
+  . = ALIGN(_PAGE_SIZE);		/* Init code and data */
   __init_begin = .;
   .init.text : {
 	_sinittext = .;
@@ -105,7 +106,7 @@
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
   SECURITY_INIT
-  . = ALIGN(4096);
+  . = ALIGN(_PAGE_SIZE);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
@@ -113,7 +114,7 @@
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
-  . = ALIGN(4096);
+  . = ALIGN(_PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
 
diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c
index 8d7d7a4..181bf68 100644
--- a/arch/mips/lasat/reset.c
+++ b/arch/mips/lasat/reset.c
@@ -19,9 +19,12 @@
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/pm.h>
+
 #include <asm/reboot.h>
 #include <asm/system.h>
 #include <asm/lasat/lasat.h>
+
 #include "picvue.h"
 #include "prom.h"
 
@@ -63,5 +66,5 @@
 {
 	_machine_restart = lasat_machine_restart;
 	_machine_halt = lasat_machine_halt;
-	_machine_power_off = lasat_machine_halt;
+	pm_power_off = lasat_machine_halt;
 }
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
index dcd819d..83eb08b 100644
--- a/arch/mips/lasat/setup.c
+++ b/arch/mips/lasat/setup.c
@@ -134,8 +134,8 @@
 
 	memset(&s, 0, sizeof(s));
 
-	s.flags = STD_COM_FLAGS;
-	s.iotype = SERIAL_IO_MEM;
+	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	s.iotype = UPIO_MEM;
 
 	if (mips_machtype == MACH_LASAT_100) {
 		s.uartclk = LASAT_BASE_BAUD_100 * 16;
diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c
index 46519f4..c49a925 100644
--- a/arch/mips/lib-32/dump_tlb.c
+++ b/arch/mips/lib-32/dump_tlb.c
@@ -158,29 +158,26 @@
 	printk("task->mm             == %8p\n", t->mm);
 	//printk("tasks->mm.pgd        == %08x\n", (unsigned int) t->mm->pgd);
 
-	if (addr > KSEG0)
+	if (addr > KSEG0) {
 		page_dir = pgd_offset_k(0);
-	else if (t->mm) {
-		page_dir = pgd_offset(t->mm, 0);
-		printk("page_dir == %08x\n", (unsigned int) page_dir);
-	} else
-		printk("Current thread has no mm\n");
-
-	if (addr > KSEG0)
 		pgd = pgd_offset_k(addr);
-	else if (t->mm) {
+	} else if (t->mm) {
+		page_dir = pgd_offset(t->mm, 0);
 		pgd = pgd_offset(t->mm, addr);
-		printk("pgd == %08x, ", (unsigned int) pgd);
-		pud = pud_offset(pgd, addr);
-		printk("pud == %08x, ", (unsigned int) pud);
-
-		pmd = pmd_offset(pud, addr);
-		printk("pmd == %08x, ", (unsigned int) pmd);
-
-		pte = pte_offset(pmd, addr);
-		printk("pte == %08x, ", (unsigned int) pte);
-	} else
+	} else {
 		printk("Current thread has no mm\n");
+		return;
+	}
+	printk("page_dir == %08x\n", (unsigned int) page_dir);
+	printk("pgd == %08x, ", (unsigned int) pgd);
+	pud = pud_offset(pgd, addr);
+	printk("pud == %08x, ", (unsigned int) pud);
+
+	pmd = pmd_offset(pud, addr);
+	printk("pmd == %08x, ", (unsigned int) pmd);
+
+	pte = pte_offset(pmd, addr);
+	printk("pte == %08x, ", (unsigned int) pte);
 
 	page = *pte;
 #ifdef CONFIG_64BIT_PHYS_ADDR
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c
index 495c1ac..1c555e6 100644
--- a/arch/mips/math-emu/dp_simple.c
+++ b/arch/mips/math-emu/dp_simple.c
@@ -48,16 +48,22 @@
 	CLEARCX;
 	FLUSHXDP;
 
+	/*
+	 * Invert the sign ALWAYS to prevent an endless recursion on
+	 * pow() in libc.
+	 */
+	/* quick fix up */
+	DPSIGN(x) ^= 1;
+
 	if (xc == IEEE754_CLASS_SNAN) {
+		ieee754dp y = ieee754dp_indef();
 		SETCX(IEEE754_INVALID_OPERATION);
-		return ieee754dp_nanxcpt(ieee754dp_indef(), "neg");
+		DPSIGN(y) = DPSIGN(x);
+		return ieee754dp_nanxcpt(y, "neg");
 	}
 
 	if (ieee754dp_isnan(x))	/* but not infinity */
 		return ieee754dp_nanxcpt(x, "neg", x);
-
-	/* quick fix up */
-	DPSIGN(x) ^= 1;
 	return x;
 }
 
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c
index c809830..770f0f4 100644
--- a/arch/mips/math-emu/sp_simple.c
+++ b/arch/mips/math-emu/sp_simple.c
@@ -48,16 +48,22 @@
 	CLEARCX;
 	FLUSHXSP;
 
+	/*
+	 * Invert the sign ALWAYS to prevent an endless recursion on
+	 * pow() in libc.
+	 */
+	/* quick fix up */
+	SPSIGN(x) ^= 1;
+
 	if (xc == IEEE754_CLASS_SNAN) {
+		ieee754sp y = ieee754sp_indef();
 		SETCX(IEEE754_INVALID_OPERATION);
-		return ieee754sp_nanxcpt(ieee754sp_indef(), "neg");
+		SPSIGN(y) = SPSIGN(x);
+		return ieee754sp_nanxcpt(y, "neg");
 	}
 
 	if (ieee754sp_isnan(x))	/* but not infinity */
 		return ieee754sp_nanxcpt(x, "neg", x);
-
-	/* quick fix up */
-	SPSIGN(x) ^= 1;
 	return x;
 }
 
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index 625843b..873cf31 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -82,8 +82,8 @@
 #endif
 	s.irq = ATLASINT_UART;
 	s.uartclk = ATLAS_BASE_BAUD * 16;
-	s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
-	s.iotype = SERIAL_IO_PORT;
+	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ;
+	s.iotype = UPIO_PORT;
 	s.regshift = 3;
 
 	if (early_serial_setup(&s) != 0) {
diff --git a/arch/mips/mips-boards/generic/reset.c b/arch/mips/mips-boards/generic/reset.c
index 9fdec74..7213c39 100644
--- a/arch/mips/mips-boards/generic/reset.c
+++ b/arch/mips/mips-boards/generic/reset.c
@@ -23,6 +23,7 @@
  *
  */
 #include <linux/config.h>
+#include <linux/pm.h>
 
 #include <asm/io.h>
 #include <asm/reboot.h>
@@ -65,9 +66,9 @@
 	_machine_restart = mips_machine_restart;
 	_machine_halt = mips_machine_halt;
 #if defined(CONFIG_MIPS_ATLAS)
-	_machine_power_off = atlas_machine_power_off;
+	pm_power_off = atlas_machine_power_off;
 #endif
 #if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_SEAD)
-	_machine_power_off = mips_machine_halt;
+	pm_power_off = mips_machine_halt;
 #endif
 }
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c
index f966bc1..4266ce4 100644
--- a/arch/mips/mips-boards/sead/sead_setup.c
+++ b/arch/mips/mips-boards/sead/sead_setup.c
@@ -71,8 +71,8 @@
 #endif
 	s.irq = MIPSCPU_INT_BASE + MIPSCPU_INT_UART0;
 	s.uartclk = SEAD_BASE_BAUD * 16;
-	s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
-	s.iotype = 0;
+	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ;
+	s.iotype = UPIO_PORT;
 	s.regshift = 3;
 
 	if (early_serial_setup(&s) != 0) {
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c
index 485d5a5..a2fd629 100644
--- a/arch/mips/mips-boards/sim/sim_setup.c
+++ b/arch/mips/mips-boards/sim/sim_setup.c
@@ -88,8 +88,8 @@
 	 but poll for now */
 	s.irq =  0;
 	s.uartclk = BASE_BAUD * 16;
-	s.flags = ASYNC_BOOT_AUTOCONF | UPF_SKIP_TEST;
-	s.iotype = SERIAL_IO_PORT | ASYNC_SKIP_TEST;
+	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	s.iotype = UPIO_PORT;
 	s.regshift = 0;
 	s.timeout = 4;
 
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 422b55f..e51c38c 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -464,8 +464,8 @@
 }
 
 struct flush_icache_range_args {
-	unsigned long __user start;
-	unsigned long __user end;
+	unsigned long start;
+	unsigned long end;
 };
 
 static inline void local_r4k_flush_icache_range(void *args)
@@ -528,8 +528,7 @@
 	}
 }
 
-static void r4k_flush_icache_range(unsigned long __user start,
-	unsigned long __user end)
+static void r4k_flush_icache_range(unsigned long start, unsigned long end)
 {
 	struct flush_icache_range_args args;
 
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 314701a..591c22b 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -25,8 +25,7 @@
 	unsigned long end);
 void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
 	unsigned long pfn);
-void (*flush_icache_range)(unsigned long __user start,
-	unsigned long __user end);
+void (*flush_icache_range)(unsigned long start, unsigned long end);
 void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
 
 /* MIPS specific cache operations */
@@ -53,7 +52,7 @@
  * We could optimize the case where the cache argument is not BCACHE but
  * that seems very atypical use ...
  */
-asmlinkage int sys_cacheflush(unsigned long __user addr,
+asmlinkage int sys_cacheflush(unsigned long addr,
 	unsigned long bytes, unsigned int cache)
 {
 	if (bytes == 0)
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 4ee91c9..0ff9a34 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -24,6 +24,7 @@
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/swap.h>
+#include <linux/proc_fs.h>
 
 #include <asm/bootinfo.h>
 #include <asm/cachectl.h>
@@ -200,6 +201,11 @@
 	return 0;
 }
 
+static struct kcore_list kcore_mem, kcore_vmalloc;
+#ifdef CONFIG_64BIT
+static struct kcore_list kcore_kseg0;
+#endif
+
 void __init mem_init(void)
 {
 	unsigned long codesize, reservedpages, datasize, initsize;
@@ -249,6 +255,16 @@
 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
+#ifdef CONFIG_64BIT
+	if ((unsigned long) &_text > (unsigned long) CKSEG0)
+		/* The -4 is a hack so that user tools don't have to handle
+		   the overflow.  */
+		kclist_add(&kcore_kseg0, (void *) CKSEG0, 0x80000000 - 4);
+#endif
+	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
+	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
+		   VMALLOC_END-VMALLOC_START);
+
 	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
 	       "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
 	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
diff --git a/arch/mips/momentum/jaguar_atx/ja-console.c b/arch/mips/momentum/jaguar_atx/ja-console.c
index da6e1ed..2292d0e 100644
--- a/arch/mips/momentum/jaguar_atx/ja-console.c
+++ b/arch/mips/momentum/jaguar_atx/ja-console.c
@@ -93,7 +93,7 @@
 	up.uartclk	= JAGUAR_ATX_UART_CLK;
 	up.regshift	= 2;
 	up.iotype	= UPIO_MEM;
-	up.flags	= ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	up.flags	= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	up.line		= 0;
 
 	if (early_serial_setup(&up))
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index bab192d..301d672 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -50,6 +50,7 @@
 #include <linux/pci.h>
 #include <linux/swap.h>
 #include <linux/ioport.h>
+#include <linux/pm.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
@@ -365,7 +366,7 @@
 
 	_machine_restart = momenco_jaguar_restart;
 	_machine_halt = momenco_jaguar_halt;
-	_machine_power_off = momenco_jaguar_power_off;
+	pm_power_off = momenco_jaguar_power_off;
 
 	/*
 	 * initrd_start = (ulong)jaguar_initrd_start;
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index c9b7ff8..f95677f 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -57,6 +57,8 @@
 #include <linux/timex.h>
 #include <linux/bootmem.h>
 #include <linux/mv643xx.h>
+#include <linux/pm.h>
+
 #include <asm/time.h>
 #include <asm/page.h>
 #include <asm/bootinfo.h>
@@ -321,7 +323,7 @@
 
 	_machine_restart = momenco_ocelot_restart;
 	_machine_halt = momenco_ocelot_halt;
-	_machine_power_off = momenco_ocelot_power_off;
+	pm_power_off = momenco_ocelot_power_off;
 
 	/* Wired TLB entries */
 	setup_wired_tlb_entries();
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
index 2755c15..15998d8 100644
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -51,8 +51,10 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/pm.h>
 #include <linux/timex.h>
 #include <linux/vmalloc.h>
+
 #include <asm/time.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
@@ -236,7 +238,7 @@
 
 	_machine_restart = momenco_ocelot_restart;
 	_machine_halt = momenco_ocelot_halt;
-	_machine_power_off = momenco_ocelot_power_off;
+	pm_power_off = momenco_ocelot_power_off;
 
 	/*
 	 * initrd_start = (ulong)ocelot_initrd_start;
diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
index 6336751..fed4e8e 100644
--- a/arch/mips/momentum/ocelot_g/setup.c
+++ b/arch/mips/momentum/ocelot_g/setup.c
@@ -47,8 +47,10 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/pm.h>
 #include <linux/timex.h>
 #include <linux/vmalloc.h>
+
 #include <asm/time.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
@@ -169,7 +171,7 @@
 
 	_machine_restart = momenco_ocelot_restart;
 	_machine_halt = momenco_ocelot_halt;
-	_machine_power_off = momenco_ocelot_power_off;
+	pm_power_off = momenco_ocelot_power_off;
 
 	/*
 	 * initrd_start = (ulong)ocelot_initrd_start;
diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile
index 354261d..0a50aad 100644
--- a/arch/mips/oprofile/Makefile
+++ b/arch/mips/oprofile/Makefile
@@ -12,4 +12,5 @@
 
 oprofile-$(CONFIG_CPU_MIPS32)		+= op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_MIPS64)		+= op_model_mipsxx.o
+oprofile-$(CONFIG_CPU_SB1)		+= op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_RM9000)		+= op_model_rm9000.o
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index 53f9889..935dd85 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -79,6 +79,9 @@
 	case CPU_20KC:
 	case CPU_24K:
 	case CPU_25KF:
+	case CPU_34K:
+	case CPU_SB1:
+	case CPU_SB1A:
 		lmodel = &op_model_mipsxx;
 		break;
 
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 1d1eee4..95d488c 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -201,10 +201,21 @@
 		op_model_mipsxx.cpu_type = "mips/25K";
 		break;
 
+#ifndef CONFIG_SMP
+	case CPU_34K:
+		op_model_mipsxx.cpu_type = "mips/34K";
+		break;
+#endif
+
 	case CPU_5KC:
 		op_model_mipsxx.cpu_type = "mips/5K";
 		break;
 
+	case CPU_SB1:
+	case CPU_SB1A:
+		op_model_mipsxx.cpu_type = "mips/sb1";
+		break;
+
 	default:
 		printk(KERN_ERR "Profiling unsupported for this CPU\n");
 
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 741e67c..16205b5 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -46,6 +46,7 @@
 obj-$(CONFIG_SGI_IP27)		+= pci-ip27.o
 obj-$(CONFIG_SGI_IP32)		+= fixup-ip32.o ops-mace.o pci-ip32.o
 obj-$(CONFIG_SIBYTE_SB1250)	+= fixup-sb1250.o pci-sb1250.o
+obj-$(CONFIG_SIBYTE_BCM112X)	+= fixup-sb1250.o pci-sb1250.o
 obj-$(CONFIG_SIBYTE_BCM1x80)	+= pci-bcm1480.o pci-bcm1480ht.o
 obj-$(CONFIG_SNI_RM200_PCI)	+= fixup-sni.o ops-sni.o
 obj-$(CONFIG_TANBAC_TB0219)	+= fixup-tb0219.o
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index 909292f..75a01e7 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -17,7 +17,7 @@
 #include <asm/io.h>
 #include <asm/gt64120.h>
 
-#include <asm/cobalt/cobalt.h>
+#include <asm/mach-cobalt/cobalt.h>
 
 extern int cobalt_board_id;
 
@@ -52,7 +52,7 @@
 	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lt);
 	if (lt < 64)
 		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
@@ -69,7 +69,7 @@
 	 * host bridge.
 	 */
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
 
 	/*
 	 * The code described by the comment below has been removed
diff --git a/arch/mips/pci/ops-gt64111.c b/arch/mips/pci/ops-gt64111.c
index c180793..13de459 100644
--- a/arch/mips/pci/ops-gt64111.c
+++ b/arch/mips/pci/ops-gt64111.c
@@ -15,7 +15,7 @@
 #include <asm/io.h>
 #include <asm/gt64120.h>
 
-#include <asm/cobalt/cobalt.h>
+#include <asm/mach-cobalt/cobalt.h>
 
 /*
  * Device 31 on the GT64111 is used to generate PCI special
diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c
index f194b4e..ca975e7 100644
--- a/arch/mips/pci/pci-bcm1480.c
+++ b/arch/mips/pci/pci-bcm1480.c
@@ -234,11 +234,9 @@
 
 	/* turn on ExpMemEn */
 	cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40));
-	printk("PCIFeatureCtrl = %x\n", cmdreg);
 	WRITECFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40),
 			cmdreg | 0x10);
 	cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40));
-	printk("PCIFeatureCtrl = %x\n", cmdreg);
 
 	/*
 	 * Establish mappings in KSEG2 (kernel virtual) to PCI I/O
diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
index 8aa9bd6..a592260f 100644
--- a/arch/mips/philips/pnx8550/common/platform.c
+++ b/arch/mips/philips/pnx8550/common/platform.c
@@ -66,28 +66,28 @@
 	[0] = {
 		.port   = {
 			.type		= PORT_IP3106,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.membase	= (void __iomem *)PNX8550_UART_PORT0,
 			.mapbase	= PNX8550_UART_PORT0,
 			.irq		= PNX8550_UART_INT(0),
 			.uartclk	= 3692300,
 			.fifosize	= 16,
 			.ops		= &ip3106_pops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 	},
 	[1] = {
 		.port   = {
 			.type		= PORT_IP3106,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.membase	= (void __iomem *)PNX8550_UART_PORT1,
 			.mapbase	= PNX8550_UART_PORT1,
 			.irq		= PNX8550_UART_INT(1),
 			.uartclk	= 3692300,
 			.fifosize	= 16,
 			.ops		= &ip3106_pops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 	},
diff --git a/arch/mips/philips/pnx8550/common/setup.c b/arch/mips/philips/pnx8550/common/setup.c
index ee6bf72..0d8a776 100644
--- a/arch/mips/philips/pnx8550/common/setup.c
+++ b/arch/mips/philips/pnx8550/common/setup.c
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/serial_ip3106.h>
+#include <linux/pm.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -90,7 +91,7 @@
 
         _machine_restart = pnx8550_machine_restart;
         _machine_halt = pnx8550_machine_halt;
-        _machine_power_off = pnx8550_machine_power_off;
+        pm_power_off = pnx8550_machine_power_off;
 
 	board_time_init = pnx8550_time_init;
 	board_timer_setup = pnx8550_timer_setup;
diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c
index 555bfacf..165275c 100644
--- a/arch/mips/pmc-sierra/yosemite/prom.c
+++ b/arch/mips/pmc-sierra/yosemite/prom.c
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
+#include <linux/pm.h>
 #include <linux/smp.h>
 
 #include <asm/io.h>
@@ -92,7 +93,7 @@
 	/* Callbacks for halt, restart */
 	_machine_restart = (void (*)(char *)) prom_exit;
 	_machine_halt = prom_halt;
-	_machine_power_off = prom_halt;
+	pm_power_off = prom_halt;
 
 	debug_vectors = cv;
 	arcs_cmdline[0] = '\0';
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index 059755b..8bce711 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -185,7 +185,7 @@
 	up.uartclk      = TITAN_UART_CLK;
 	up.regshift     = 0;
 	up.iotype       = UPIO_MEM;
-	up.flags        = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	up.flags        = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	up.line         = 0;
 
 	if (early_serial_setup(&up))
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 214ffd2..92a3b3c 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -3,8 +3,9 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1997, 1998, 2001, 2003 by Ralf Baechle
+ * Copyright (C) 1997, 1998, 2001, 03, 05, 06 by Ralf Baechle
  */
+#include <linux/linkage.h>
 #include <linux/init.h>
 #include <linux/ds1286.h>
 #include <linux/module.h>
@@ -12,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
+#include <linux/pm.h>
 #include <linux/timer.h>
 
 #include <asm/io.h>
@@ -41,28 +43,10 @@
 
 #define MACHINE_PANICED		1
 #define MACHINE_SHUTTING_DOWN	2
-static int machine_state = 0;
 
-static void sgi_machine_restart(char *command) __attribute__((noreturn));
-static void sgi_machine_halt(void) __attribute__((noreturn));
-static void sgi_machine_power_off(void) __attribute__((noreturn));
+static int machine_state;
 
-static void sgi_machine_restart(char *command)
-{
-	if (machine_state & MACHINE_SHUTTING_DOWN)
-		sgi_machine_power_off();
-	sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;
-	while (1);
-}
-
-static void sgi_machine_halt(void)
-{
-	if (machine_state & MACHINE_SHUTTING_DOWN)
-		sgi_machine_power_off();
-	ArcEnterInteractiveMode();
-}
-
-static void sgi_machine_power_off(void)
+static void ATTRIB_NORET sgi_machine_power_off(void)
 {
 	unsigned int tmp;
 
@@ -84,6 +68,21 @@
 	}
 }
 
+static void ATTRIB_NORET sgi_machine_restart(char *command)
+{
+	if (machine_state & MACHINE_SHUTTING_DOWN)
+		sgi_machine_power_off();
+	sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;
+	while (1);
+}
+
+static void ATTRIB_NORET sgi_machine_halt(void)
+{
+	if (machine_state & MACHINE_SHUTTING_DOWN)
+		sgi_machine_power_off();
+	ArcEnterInteractiveMode();
+}
+
 static void power_timeout(unsigned long data)
 {
 	sgi_machine_power_off();
@@ -95,7 +94,7 @@
 	sgi_ioc_reset ^= (SGIOC_RESET_LC0OFF|SGIOC_RESET_LC1OFF);
 	sgioc->reset = sgi_ioc_reset;
 
-	mod_timer(&blink_timer, jiffies+data);
+	mod_timer(&blink_timer, jiffies + data);
 }
 
 static void debounce(unsigned long data)
@@ -103,7 +102,7 @@
 	del_timer(&debounce_timer);
 	if (sgint->istat1 & SGINT_ISTAT1_PWR) {
 		/* Interrupt still being sent. */
-		debounce_timer.expires = jiffies + 5; /* 0.05s  */
+		debounce_timer.expires = jiffies + (HZ / 20); /* 0.05s  */
 		add_timer(&debounce_timer);
 
 		sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR |
@@ -151,7 +150,7 @@
 		indy_volume_button(1);
 
 	if (sgint->istat1 & SGINT_ISTAT1_PWR) {
-		volume_timer.expires = jiffies + 1;
+		volume_timer.expires = jiffies + (HZ / 100);
 		add_timer(&volume_timer);
 	}
 }
@@ -164,7 +163,7 @@
 		indy_volume_button(-1);
 
 	if (sgint->istat1 & SGINT_ISTAT1_PWR) {
-		volume_timer.expires = jiffies + 1;
+		volume_timer.expires = jiffies + (HZ / 100);
 		add_timer(&volume_timer);
 	}
 }
@@ -199,14 +198,14 @@
 	if (!(buttons & SGIOC_PANEL_VOLUPINTR)) {
 		init_timer(&volume_timer);
 		volume_timer.function = volume_up_button;
-		volume_timer.expires = jiffies + 1;
+		volume_timer.expires = jiffies + (HZ / 100);
 		add_timer(&volume_timer);
 	}
 	/* Volume down button was pressed */
 	if (!(buttons & SGIOC_PANEL_VOLDNINTR)) {
 		init_timer(&volume_timer);
 		volume_timer.function = volume_down_button;
-		volume_timer.expires = jiffies + 1;
+		volume_timer.expires = jiffies + (HZ / 100);
 		add_timer(&volume_timer);
 	}
 
@@ -234,7 +233,7 @@
 {
 	_machine_restart = sgi_machine_restart;
 	_machine_halt = sgi_machine_halt;
-	_machine_power_off = sgi_machine_power_off;
+	pm_power_off = sgi_machine_power_off;
 
 	request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
 	init_timer(&blink_timer);
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index 5e59b4c..7018e18 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -56,6 +56,7 @@
 void __init plat_setup(void)
 {
 	char *ctype;
+	char *cserial;
 
 	board_be_init = ip22_be_init;
 	ip22_time_init();
@@ -81,9 +82,14 @@
 	/* ARCS console environment variable is set to "g?" for
 	 * graphics console, it is set to "d" for the first serial
 	 * line and "d2" for the second serial line.
+	 *
+	 * Need to check if the case is 'g' but no keyboard:
+	 * (ConsoleIn/Out = serial)
 	 */
 	ctype = ArcGetEnvironmentVariable("console");
-	if (ctype && *ctype == 'd') {
+	cserial = ArcGetEnvironmentVariable("ConsoleOut");
+
+	if ((ctype && *ctype == 'd') || (cserial && *cserial == 's')) {
 		static char options[8];
 		char *baud = ArcGetEnvironmentVariable("dbaud");
 		if (baud)
@@ -91,7 +97,7 @@
 		add_preferred_console("ttyS", *(ctype + 1) == '2' ? 1 : 0,
 				      baud ? options : NULL);
 	} else if (!ctype || *ctype != 'g') {
-		/* Use ARC if we don't want serial ('d') or Newport ('g'). */
+		/* Use ARC if we don't want serial ('d') or graphics ('g'). */
 		prom_flags |= PROM_FLAG_USE_AS_CONSOLE;
 		add_preferred_console("arc", 0, NULL);
 	}
diff --git a/arch/mips/sgi-ip27/ip27-reset.c b/arch/mips/sgi-ip27/ip27-reset.c
index 2e16be9..4322db5 100644
--- a/arch/mips/sgi-ip27/ip27-reset.c
+++ b/arch/mips/sgi-ip27/ip27-reset.c
@@ -5,7 +5,7 @@
  *
  * Reset an IP27.
  *
- * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1997, 1998, 1999, 2000, 06 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <linux/config.h>
@@ -15,6 +15,7 @@
 #include <linux/smp.h>
 #include <linux/mmzone.h>
 #include <linux/nodemask.h>
+#include <linux/pm.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -77,5 +78,5 @@
 {
 	_machine_restart = ip27_machine_restart;
 	_machine_halt = ip27_machine_halt;
-	_machine_power_off = ip27_machine_power_off;
+	pm_power_off = ip27_machine_power_off;
 }
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
index 88e1f52..0c94800 100644
--- a/arch/mips/sgi-ip32/ip32-reset.c
+++ b/arch/mips/sgi-ip32/ip32-reset.c
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/ds17287rtc.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 
 #include <asm/addrspace.h>
 #include <asm/irq.h>
@@ -188,7 +189,7 @@
 
 	_machine_restart = ip32_machine_restart;
 	_machine_halt = ip32_machine_halt;
-	_machine_power_off = ip32_machine_power_off;
+	pm_power_off = ip32_machine_power_off;
 
 	init_timer(&blink_timer);
 	blink_timer.function = blink_timeout;
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index d10a269..2c38770 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -66,11 +66,6 @@
 #include <linux/tty.h>
 #include <linux/serial.h>
 #include <linux/serial_core.h>
-extern int early_serial_setup(struct uart_port *port);
-
-#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
-#define BASE_BAUD (1843200 / 16)
-
 #endif /* CONFIG_SERIAL_8250 */
 
 /* An arbitrary time; this can be decreased if reliability looks good */
@@ -110,8 +105,8 @@
 		o2_serial[0].type	= PORT_16550A;
 		o2_serial[0].line	= 0;
 		o2_serial[0].irq	= MACEISA_SERIAL1_IRQ;
-		o2_serial[0].flags	= STD_COM_FLAGS;
-		o2_serial[0].uartclk	= BASE_BAUD * 16;
+		o2_serial[0].flags	= UPF_SKIP_TEST;
+		o2_serial[0].uartclk	= 1843200;
 		o2_serial[0].iotype	= UPIO_MEM;
 		o2_serial[0].membase	= (char *)&mace->isa.serial1;
 		o2_serial[0].fifosize	= 14;
@@ -121,8 +116,8 @@
 		o2_serial[1].type	= PORT_16550A;
 		o2_serial[1].line	= 1;
 		o2_serial[1].irq	= MACEISA_SERIAL2_IRQ;
-		o2_serial[1].flags	= STD_COM_FLAGS;
-		o2_serial[1].uartclk	= BASE_BAUD * 16;
+		o2_serial[1].flags	= UPF_SKIP_TEST;
+		o2_serial[1].uartclk	= 1843200;
 		o2_serial[1].iotype	= UPIO_MEM;
 		o2_serial[1].membase	= (char *)&mace->isa.serial2;
 		o2_serial[1].fifosize	= 14;
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
index 7a2c7a8..ea30802 100644
--- a/arch/mips/sibyte/cfe/setup.c
+++ b/arch/mips/sibyte/cfe/setup.c
@@ -23,6 +23,7 @@
 #include <linux/mm.h>
 #include <linux/blkdev.h>
 #include <linux/bootmem.h>
+#include <linux/pm.h>
 #include <linux/smp.h>
 
 #include <asm/bootinfo.h>
@@ -248,7 +249,7 @@
 
 	_machine_restart   = cfe_linux_restart;
 	_machine_halt      = cfe_linux_halt;
-	_machine_power_off = cfe_linux_halt;
+	pm_power_off = cfe_linux_halt;
 
 	/*
 	 * Check if a loader was used; if NOT, the 4 arguments are
diff --git a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c
index de62ab0..742043f 100644
--- a/arch/mips/sibyte/sb1250/prom.c
+++ b/arch/mips/sibyte/sb1250/prom.c
@@ -24,6 +24,7 @@
 #include <linux/bootmem.h>
 #include <linux/smp.h>
 #include <linux/initrd.h>
+#include <linux/pm.h>
 
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
@@ -79,7 +80,7 @@
 {
 	_machine_restart   = (void (*)(char *))prom_linux_exit;
 	_machine_halt      = prom_linux_exit;
-	_machine_power_off = prom_linux_exit;
+	pm_power_off = prom_linux_exit;
 
 	strcpy(arcs_cmdline, "root=/dev/ram0 ");
 
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index df2e266..fde4751 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 #include <linux/config.h>
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/reboot.h>
 #include <linux/string.h>
@@ -42,7 +43,7 @@
 
 /* Setup code likely to be common to all SiByte platforms */
 
-static inline int sys_rev_decode(void)
+static int __init sys_rev_decode(void)
 {
 	int ret = 0;
 
@@ -74,7 +75,7 @@
 	return ret;
 }
 
-static inline int setup_bcm1250(void)
+static int __init setup_bcm1250(void)
 {
 	int ret = 0;
 
@@ -120,7 +121,7 @@
 	return ret;
 }
 
-static inline int setup_bcm112x(void)
+static int __init setup_bcm112x(void)
 {
 	int ret = 0;
 
@@ -146,7 +147,7 @@
 	return ret;
 }
 
-void sb1250_setup(void)
+void __init sb1250_setup(void)
 {
 	uint64_t sys_rev;
 	int plldiv;
@@ -169,31 +170,42 @@
 		    soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
 	prom_printf("Board type: %s\n", get_system_type());
 
-	switch(war_pass) {
+	switch (war_pass) {
 	case K_SYS_REVISION_BCM1250_PASS1:
 #ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
-		prom_printf("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n");
+		prom_printf("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
+		            "and the kernel doesn't have the proper "
+		            "workarounds compiled in. @@@@\n");
 		bad_config = 1;
 #endif
 		break;
 	case K_SYS_REVISION_BCM1250_PASS2:
 		/* Pass 2 - easiest as default for now - so many numbers */
-#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
-		prom_printf("@@@@ This is a BCM1250 A3-A10 board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n");
+#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \
+    !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
+		prom_printf("@@@@ This is a BCM1250 A3-A10 board, and the "
+		            "kernel doesn't have the proper workarounds "
+		            "compiled in. @@@@\n");
 		bad_config = 1;
 #endif
 #ifdef CONFIG_CPU_HAS_PREFETCH
-		prom_printf("@@@@ Prefetches may be enabled in this kernel, but are buggy on this board.  @@@@\n");
+		prom_printf("@@@@ Prefetches may be enabled in this kernel, "
+		            "but are buggy on this board.  @@@@\n");
 		bad_config = 1;
 #endif
 		break;
 	case K_SYS_REVISION_BCM1250_PASS2_2:
 #ifndef CONFIG_SB1_PASS_2_WORKAROUNDS
-		prom_printf("@@@@ This is a BCM1250 B1/B2. board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n");
+		prom_printf("@@@@ This is a BCM1250 B1/B2. board, and the "
+		            "kernel doesn't have the proper workarounds "
+		            "compiled in. @@@@\n");
 		bad_config = 1;
 #endif
-#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || !defined(CONFIG_CPU_HAS_PREFETCH)
-		prom_printf("@@@@ This is a BCM1250 B1/B2, but the kernel is conservatively configured for an 'A' stepping. @@@@\n");
+#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \
+    !defined(CONFIG_CPU_HAS_PREFETCH)
+		prom_printf("@@@@ This is a BCM1250 B1/B2, but the kernel is "
+		            "conservatively configured for an 'A' stepping. "
+		            "@@@@\n");
 #endif
 		break;
 	default:
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 262c856..1141fcd 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 97, 98, 2000, 03, 04 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
  */
 #include <linux/config.h>
 #include <linux/eisa.h>
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
+#include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/console.h>
 #include <linux/fb.h>
@@ -189,7 +190,7 @@
 
 	_machine_restart = sni_machine_restart;
 	_machine_halt = sni_machine_halt;
-	_machine_power_off = sni_machine_power_off;
+	pm_power_off = sni_machine_power_off;
 
 	sni_display_setup();
 
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c
index e4d095d..e19e2be 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c
@@ -60,7 +60,6 @@
 
 void __init prom_init(void)
 {
-	const char* toshiba_name_list[] = GROUP_TOSHIBA_NAMES;
 	extern int tx4927_get_mem_size(void);
 	extern char* toshiba_name;
 	int msize;
@@ -69,12 +68,13 @@
 
 	mips_machgroup = MACH_GROUP_TOSHIBA;
 
-	if ((read_c0_prid() & 0xff) == PRID_REV_TX4927)
+	if ((read_c0_prid() & 0xff) == PRID_REV_TX4927) {
 		mips_machtype = MACH_TOSHIBA_RBTX4927;
-	else
+ 		toshiba_name  = "TX4927";
+	} else {
 		mips_machtype = MACH_TOSHIBA_RBTX4937;
-
-        toshiba_name = toshiba_name_list[mips_machtype];
+ 		toshiba_name  = "TX4937";
+	}
 
 	msize = tx4927_get_mem_size();
 	add_memory_region(0, msize << 20, BOOT_MEM_RAM);
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index 990fcb2..2ad6401 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -53,6 +53,8 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/timex.h>
+#include <linux/pm.h>
+
 #include <asm/bootinfo.h>
 #include <asm/page.h>
 #include <asm/io.h>
@@ -537,19 +539,10 @@
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
 				       "0x%08lx=mips_io_port_base",
 				       mips_io_port_base);
-
-	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
-				       "setup pci_io_resource  to 0x%08lx 0x%08lx\n",
-				       pci_io_resource.start,
-				       pci_io_resource.end);
-	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
-				       "setup pci_mem_resource to 0x%08lx 0x%08lx\n",
-				       pci_mem_resource.start,
-				       pci_mem_resource.end);
-
 	if (!called) {
 		printk
-		    ("TX4927 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s\n",
+		    ("%s PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s\n",
+		     toshiba_name,
 		     (unsigned short) (tx4927_pcicptr->pciid >> 16),
 		     (unsigned short) (tx4927_pcicptr->pciid & 0xffff),
 		     (unsigned short) (tx4927_pcicptr->pciccrev & 0xff),
@@ -562,21 +555,52 @@
 	       (tx4927_ccfgptr->ccfg & TX4927_CCFG_PCI66) ? " PCI66" : "");
 	if (tx4927_ccfgptr->pcfg & TX4927_PCFG_PCICLKEN_ALL) {
 		int pciclk = 0;
-		switch ((unsigned long) tx4927_ccfgptr->
-			ccfg & TX4927_CCFG_PCIDIVMODE_MASK) {
-		case TX4927_CCFG_PCIDIVMODE_2_5:
-			pciclk = tx4927_cpu_clock * 2 / 5;
-			break;
-		case TX4927_CCFG_PCIDIVMODE_3:
-			pciclk = tx4927_cpu_clock / 3;
-			break;
-		case TX4927_CCFG_PCIDIVMODE_5:
-			pciclk = tx4927_cpu_clock / 5;
-			break;
-		case TX4927_CCFG_PCIDIVMODE_6:
-			pciclk = tx4927_cpu_clock / 6;
-			break;
-		}
+		if (mips_machtype == MACH_TOSHIBA_RBTX4937)
+			switch ((unsigned long) tx4927_ccfgptr->
+				ccfg & TX4937_CCFG_PCIDIVMODE_MASK) {
+			case TX4937_CCFG_PCIDIVMODE_4:
+				pciclk = tx4927_cpu_clock / 4;
+				break;
+			case TX4937_CCFG_PCIDIVMODE_4_5:
+				pciclk = tx4927_cpu_clock * 2 / 9;
+				break;
+			case TX4937_CCFG_PCIDIVMODE_5:
+				pciclk = tx4927_cpu_clock / 5;
+				break;
+			case TX4937_CCFG_PCIDIVMODE_5_5:
+				pciclk = tx4927_cpu_clock * 2 / 11;
+				break;
+			case TX4937_CCFG_PCIDIVMODE_8:
+				pciclk = tx4927_cpu_clock / 8;
+				break;
+			case TX4937_CCFG_PCIDIVMODE_9:
+				pciclk = tx4927_cpu_clock / 9;
+				break;
+			case TX4937_CCFG_PCIDIVMODE_10:
+				pciclk = tx4927_cpu_clock / 10;
+				break;
+			case TX4937_CCFG_PCIDIVMODE_11:
+				pciclk = tx4927_cpu_clock / 11;
+				break;
+			}
+
+		else
+			switch ((unsigned long) tx4927_ccfgptr->
+				ccfg & TX4927_CCFG_PCIDIVMODE_MASK) {
+			case TX4927_CCFG_PCIDIVMODE_2_5:
+				pciclk = tx4927_cpu_clock * 2 / 5;
+				break;
+			case TX4927_CCFG_PCIDIVMODE_3:
+				pciclk = tx4927_cpu_clock / 3;
+				break;
+			case TX4927_CCFG_PCIDIVMODE_5:
+				pciclk = tx4927_cpu_clock / 5;
+				break;
+			case TX4927_CCFG_PCIDIVMODE_6:
+				pciclk = tx4927_cpu_clock / 6;
+				break;
+			}
+
 		printk("Internal(%dMHz)", pciclk / 1000000);
 	} else {
 		int pciclk = 0;
@@ -814,24 +838,40 @@
 				       ":ResetRoutines\n");
 	_machine_restart = toshiba_rbtx4927_restart;
 	_machine_halt = toshiba_rbtx4927_halt;
-	_machine_power_off = toshiba_rbtx4927_power_off;
+	pm_power_off = toshiba_rbtx4927_power_off;
 
 #ifdef CONFIG_PCI
 
 	/* PCIC */
 	/*
 	   * ASSUMPTION: PCIDIVMODE is configured for PCI 33MHz or 66MHz.
-	   * PCIDIVMODE[12:11]'s initial value are given by S9[4:3] (ON:0, OFF:1).
+	   *
+	   * For TX4927:
+	   * PCIDIVMODE[12:11]'s initial value is given by S9[4:3] (ON:0, OFF:1).
 	   * CPU 166MHz: PCI 66MHz : PCIDIVMODE: 00 (1/2.5)
 	   * CPU 200MHz: PCI 66MHz : PCIDIVMODE: 01 (1/3)
 	   * CPU 166MHz: PCI 33MHz : PCIDIVMODE: 10 (1/5)
 	   * CPU 200MHz: PCI 33MHz : PCIDIVMODE: 11 (1/6)
 	   * i.e. S9[3]: ON (83MHz), OFF (100MHz)
+	   *
+	   * For TX4937:
+	   * PCIDIVMODE[12:11]'s initial value is given by S1[5:4] (ON:0, OFF:1)
+	   * PCIDIVMODE[10] is 0.
+	   * CPU 266MHz: PCI 33MHz : PCIDIVMODE: 000 (1/8)
+	   * CPU 266MHz: PCI 66MHz : PCIDIVMODE: 001 (1/4)
+	   * CPU 300MHz: PCI 33MHz : PCIDIVMODE: 010 (1/9)
+	   * CPU 300MHz: PCI 66MHz : PCIDIVMODE: 011 (1/4.5)
+	   * CPU 333MHz: PCI 33MHz : PCIDIVMODE: 100 (1/10)
+	   * CPU 333MHz: PCI 66MHz : PCIDIVMODE: 101 (1/5)
+	   *
 	 */
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1,
-				       "ccfg is %lx, DIV is %x\n",
-				       (unsigned long) tx4927_ccfgptr->
-				       ccfg, TX4927_CCFG_PCIDIVMODE_MASK);
+				       "ccfg is %lx, PCIDIVMODE is %x\n",
+				       (unsigned long) tx4927_ccfgptr->ccfg,
+				       (unsigned long) tx4927_ccfgptr->ccfg &
+				       (mips_machtype == MACH_TOSHIBA_RBTX4937 ?
+					TX4937_CCFG_PCIDIVMODE_MASK :
+					TX4927_CCFG_PCIDIVMODE_MASK));
 
 	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1,
 				       "PCI66 mode is %lx, PCI mode is %lx, pci arb is %lx\n",
@@ -842,20 +882,30 @@
 				       (unsigned long) tx4927_ccfgptr->
 				       ccfg & TX4927_CCFG_PCIXARB);
 
-	TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1,
-				       "PCIDIVMODE is %lx\n",
-				       (unsigned long) tx4927_ccfgptr->
-				       ccfg & TX4927_CCFG_PCIDIVMODE_MASK);
-
-	switch ((unsigned long) tx4927_ccfgptr->
-		ccfg & TX4927_CCFG_PCIDIVMODE_MASK) {
-	case TX4927_CCFG_PCIDIVMODE_2_5:
-	case TX4927_CCFG_PCIDIVMODE_5:
-		tx4927_cpu_clock = 166000000;	/* 166MHz */
-		break;
-	default:
-		tx4927_cpu_clock = 200000000;	/* 200MHz */
-	}
+	if (mips_machtype == MACH_TOSHIBA_RBTX4937)
+		switch ((unsigned long)tx4927_ccfgptr->
+			ccfg & TX4937_CCFG_PCIDIVMODE_MASK) {
+		case TX4937_CCFG_PCIDIVMODE_8:
+		case TX4937_CCFG_PCIDIVMODE_4:
+			tx4927_cpu_clock = 266666666;	/* 266MHz */
+			break;
+		case TX4937_CCFG_PCIDIVMODE_9:
+		case TX4937_CCFG_PCIDIVMODE_4_5:
+			tx4927_cpu_clock = 300000000;	/* 300MHz */
+			break;
+		default:
+			tx4927_cpu_clock = 333333333;	/* 333MHz */
+		}
+	else
+		switch ((unsigned long)tx4927_ccfgptr->
+			ccfg & TX4927_CCFG_PCIDIVMODE_MASK) {
+		case TX4927_CCFG_PCIDIVMODE_2_5:
+		case TX4927_CCFG_PCIDIVMODE_5:
+			tx4927_cpu_clock = 166666666;	/* 166MHz */
+			break;
+		default:
+			tx4927_cpu_clock = 200000000;	/* 200MHz */
+		}
 
 	/* CCFG */
 	/* enable Timeout BusError */
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
index 9f1dcc8..5c7ace9 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -20,6 +20,8 @@
 #include <linux/interrupt.h>
 #include <linux/console.h>
 #include <linux/pci.h>
+#include <linux/pm.h>
+
 #include <asm/wbflush.h>
 #include <asm/reboot.h>
 #include <asm/irq.h>
@@ -1003,7 +1005,7 @@
 
 	_machine_restart = rbtx4938_machine_restart;
 	_machine_halt = rbtx4938_machine_halt;
-	_machine_power_off = rbtx4938_machine_power_off;
+	pm_power_off = rbtx4938_machine_power_off;
 
 	*rbtx4938_led_ptr = 0xff;
 	printk("RBTX4938 --- FPGA(Rev %02x)", *rbtx4938_fpga_rev_ptr);
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c
index 02bf4f7..5e46979 100644
--- a/arch/mips/vr41xx/common/pmu.c
+++ b/arch/mips/vr41xx/common/pmu.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
+#include <linux/pm.h>
 #include <linux/smp.h>
 #include <linux/types.h>
 
@@ -114,7 +115,7 @@
 
 	_machine_restart = vr41xx_restart;
 	_machine_halt = vr41xx_halt;
-	_machine_power_off = vr41xx_power_off;
+	pm_power_off = vr41xx_power_off;
 
 	return 0;
 }
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index e77a06e..7c914a4 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -149,14 +149,20 @@
 	default y if SMP
 	select HOTPLUG
 
+config ARCH_SELECT_MEMORY_MODEL
+	def_bool y
+	depends on 64BIT
+
 config ARCH_DISCONTIGMEM_ENABLE
-	bool "Discontiguous memory support (EXPERIMENTAL)"
-	depends on 64BIT && EXPERIMENTAL
-	help
-	  Say Y to support efficient handling of discontiguous physical memory,
-	  for architectures which are either NUMA (Non-Uniform Memory Access)
-	  or have huge holes in the physical address space for other reasons.
-	  See <file:Documentation/vm/numa> for more.
+	def_bool y
+	depends on 64BIT
+
+config ARCH_FLATMEM_ENABLE
+	def_bool y
+
+config ARCH_DISCONTIGMEM_DEFAULT
+	def_bool y
+	depends on ARCH_DISCONTIGMEM_ENABLE
 
 source "kernel/Kconfig.hz"
 source "mm/Kconfig"
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
index 8caaed1..9166bd1 100644
--- a/arch/parisc/Kconfig.debug
+++ b/arch/parisc/Kconfig.debug
@@ -11,4 +11,14 @@
           too many attempts.  If you suspect a rwlock problem or a kernel
           hacker asks for this option then say Y.  Otherwise say N.
 
+config DEBUG_RODATA
+       bool "Write protect kernel read-only data structures"
+       depends on DEBUG_KERNEL
+       help
+         Mark the kernel read-only data as write-protected in the pagetables,
+         in order to catch accidental (and incorrect) writes to such const
+         data. This option may have a slight performance impact because a
+         portion of the kernel code won't be covered by a TLB anymore.
+         If in doubt, say "N".
+
 endmenu
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index 955ef50..959ad3c 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -602,6 +602,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=m
 CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig
index 8819e7e..37e9824 100644
--- a/arch/parisc/configs/b180_defconfig
+++ b/arch/parisc/configs/b180_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc5-pa1
-# Fri Oct 21 23:06:10 2005
+# Linux kernel version: 2.6.16-rc1-pa0
+# Tue Jan 17 08:21:01 2006
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -29,8 +29,6 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_INITRAMFS_SOURCE=""
@@ -38,8 +36,10 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -48,8 +48,10 @@
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -57,10 +59,28 @@
 CONFIG_MODULES=y
 # CONFIG_MODULE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 # CONFIG_KMOD is not set
 
 #
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 # CONFIG_PA7000 is not set
@@ -77,6 +97,7 @@
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
 # CONFIG_PREEMPT is not set
 # CONFIG_HPUX is not set
 
@@ -84,8 +105,8 @@
 # Bus options (PCI, PCMCIA, EISA, GSC, ISA)
 #
 CONFIG_GSC=y
-# CONFIG_HPPB is not set
-# CONFIG_IOMMU_CCIO is not set
+CONFIG_HPPB=y
+CONFIG_IOMMU_CCIO=y
 CONFIG_GSC_LASI=y
 CONFIG_GSC_WAX=y
 CONFIG_EISA=y
@@ -165,8 +186,11 @@
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+
+#
+# QoS and/or fair queueing
+#
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -205,6 +229,7 @@
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
 # CONFIG_PARPORT_SERIAL is not set
+CONFIG_PARPORT_NOT_PC=y
 CONFIG_PARPORT_GSC=y
 # CONFIG_PARPORT_1284 is not set
 
@@ -230,14 +255,6 @@
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 CONFIG_ATA_OVER_ETH=y
 
 #
@@ -281,6 +298,7 @@
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -313,21 +331,19 @@
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_ZALON is not set
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=40
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_SYM53C416 is not set
@@ -397,7 +413,7 @@
 #
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
-# CONFIG_LASI_82596 is not set
+CONFIG_LASI_82596=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
@@ -464,6 +480,7 @@
 # Wireless 802.11b ISA/PCI cards support
 #
 # CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
 
 #
 # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
@@ -527,7 +544,7 @@
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_HIL_OLD is not set
-# CONFIG_KEYBOARD_HIL is not set
+CONFIG_KEYBOARD_HIL=y
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
@@ -535,7 +552,7 @@
 # CONFIG_MOUSE_LOGIBM is not set
 # CONFIG_MOUSE_PC110PAD is not set
 # CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_MOUSE_HIL is not set
+CONFIG_MOUSE_HIL=y
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
@@ -549,7 +566,8 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_PARKBD is not set
 CONFIG_SERIO_GSCPS2=y
-# CONFIG_HP_SDC is not set
+CONFIG_HP_SDC=y
+CONFIG_HIL_MLC=y
 # CONFIG_SERIO_PCIPS2 is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
@@ -569,6 +587,7 @@
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=13
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -582,11 +601,10 @@
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_MUX is not set
-# CONFIG_PDC_CONSOLE is not set
+CONFIG_SERIAL_MUX=y
+CONFIG_SERIAL_MUX_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -626,6 +644,12 @@
 # CONFIG_I2C is not set
 
 #
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -661,7 +685,6 @@
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
@@ -671,6 +694,7 @@
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 CONFIG_FB_STI=y
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
@@ -683,9 +707,7 @@
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -695,6 +717,7 @@
 CONFIG_DUMMY_CONSOLE_COLUMNS=160
 CONFIG_DUMMY_CONSOLE_ROWS=64
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 CONFIG_STI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
@@ -713,7 +736,85 @@
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+
+#
+# GSC devices
+#
+CONFIG_SND_HARMONY=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
 
 #
 # USB support
@@ -723,6 +824,10 @@
 # CONFIG_USB is not set
 
 #
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -877,18 +982,23 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_IOREMAP is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_RODATA is not set
 
 #
 # Security options
diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig
index 9d86b6b..0b1c8c1 100644
--- a/arch/parisc/configs/c3000_defconfig
+++ b/arch/parisc/configs/c3000_defconfig
@@ -626,6 +626,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=m
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/parisc/hpux/entry_hpux.S b/arch/parisc/hpux/entry_hpux.S
index fa9bf38..31c8ccc 100644
--- a/arch/parisc/hpux/entry_hpux.S
+++ b/arch/parisc/hpux/entry_hpux.S
@@ -22,10 +22,9 @@
 #include <linux/linkage.h>
 #include <asm/unistd.h>
 
-	.text
-
 #define ENTRY_NAME(_name_) .word _name_
 
+	.section .rodata,"a"
 	.align 4
 	.export hpux_call_table
 	.import hpux_unimplemented_wrapper
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index 29b4d61..05273cc 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -468,19 +468,23 @@
 	if ( opcode == 1 ) { /* GETFSIND */	
 		len = strlen_user((char *)arg1);
 		printk(KERN_DEBUG "len of arg1 = %d\n", len);
-
-		fsname = (char *) kmalloc(len+1, GFP_KERNEL);
+		if (len == 0)
+			return 0;
+		fsname = (char *) kmalloc(len, GFP_KERNEL);
 		if ( !fsname ) {
 			printk(KERN_DEBUG "failed to kmalloc fsname\n");
 			return 0;
 		}
 
-		if ( copy_from_user(fsname, (char *)arg1, len+1) ) {
+		if ( copy_from_user(fsname, (char *)arg1, len) ) {
 			printk(KERN_DEBUG "failed to copy_from_user fsname\n");
 			kfree(fsname);
 			return 0;
 		}
 
+		/* String could be altered by userspace after strlen_user() */
+		fsname[len] = '\0';
+
 		printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname);
 		if ( !strcmp(fsname, "hfs") ) {
 			fstype = 0;
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 2d804e2..3d569a4 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -408,11 +408,10 @@
 
 struct parisc_device * create_tree_node(char id, struct device *parent)
 {
-	struct parisc_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	struct parisc_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
 		return NULL;
 
-	memset(dev, 0, sizeof(*dev));
 	dev->hw_path = id;
 	dev->id.hw_type = HPHW_FAULTY;
 
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index f40a777..1d00c36 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -48,9 +48,6 @@
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strpbrk);
 
-#include <linux/pm.h>
-EXPORT_SYMBOL(pm_power_off);
-
 #include <asm/atomic.h>
 EXPORT_SYMBOL(__xchg8);
 EXPORT_SYMBOL(__xchg32);
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index 88cba49..79c7db2 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -47,18 +47,17 @@
  * this makes the boot time much longer than necessary.
  * 20ms seems to work for all the HP PCI implementations to date.
  *
- * XXX: turn into a #defined constant in <asm/pci.h> ?
+ * #define pci_post_reset_delay 50
  */
-int pci_post_reset_delay = 50;
 
-struct pci_port_ops *pci_port;
-struct pci_bios_ops *pci_bios;
+struct pci_port_ops *pci_port __read_mostly;
+struct pci_bios_ops *pci_bios __read_mostly;
 
-int pci_hba_count = 0;
+static int pci_hba_count __read_mostly;
 
 /* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data.  */
 #define PCI_HBA_MAX 32
-struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX];
+static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX] __read_mostly;
 
 
 /********************************************************************
@@ -259,8 +258,10 @@
 void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 			      struct pci_bus_region *region)
 {
+#ifdef CONFIG_64BIT
 	struct pci_bus *bus = dev->bus;
 	struct pci_hba_data *hba = HBA_DATA(bus->bridge->platform_data);
+#endif
 
 	if (res->flags & IORESOURCE_MEM) {
 		res->start = PCI_HOST_ADDR(hba, region->start);
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index 11d406c..53f861c 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -68,20 +68,20 @@
 };
 
 static int perf_processor_interface __read_mostly = UNKNOWN_INTF;
-static int perf_enabled __read_mostly = 0;
+static int perf_enabled __read_mostly;
 static spinlock_t perf_lock;
-struct parisc_device *cpu_device __read_mostly = NULL;
+struct parisc_device *cpu_device __read_mostly;
 
 /* RDRs to write for PCX-W */
-static int perf_rdrs_W[] = 
+static const int perf_rdrs_W[] =
 	{ 0, 1, 4, 5, 6, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
 
 /* RDRs to write for PCX-U */
-static int perf_rdrs_U[] =
+static const int perf_rdrs_U[] =
 	{ 0, 1, 4, 5, 6, 7, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
 
 /* RDR register descriptions for PCX-W */
-static struct rdr_tbl_ent perf_rdr_tbl_W[] = {
+static const struct rdr_tbl_ent perf_rdr_tbl_W[] = {
 	{ 19,	1,	8 },   /* RDR 0 */
 	{ 16,	1,	16 },  /* RDR 1 */
 	{ 72,	2,	0 },   /* RDR 2 */
@@ -117,7 +117,7 @@
 };
 
 /* RDR register descriptions for PCX-U */
-static struct rdr_tbl_ent perf_rdr_tbl_U[] = {
+static const struct rdr_tbl_ent perf_rdr_tbl_U[] = {
 	{ 19,	1,	8 },              /* RDR 0 */
 	{ 32,	1,	16 },             /* RDR 1 */
 	{ 20,	1,	0 },              /* RDR 2 */
@@ -156,7 +156,7 @@
  * A non-zero write_control in the above tables is a byte offset into
  * this array.
  */
-static uint64_t perf_bitmasks[] = {
+static const uint64_t perf_bitmasks[] = {
 	0x0000000000000000ul,     /* first dbl word must be zero */
 	0xfdffe00000000000ul,     /* RDR0 bitmask */
 	0x003f000000000000ul,     /* RDR1 bitmask */
@@ -173,7 +173,7 @@
  * Write control bitmasks for Pa-8700 processor given
  * somethings have changed slightly.
  */
-static uint64_t perf_bitmasks_piranha[] = {
+static const uint64_t perf_bitmasks_piranha[] = {
 	0x0000000000000000ul,     /* first dbl word must be zero */
 	0xfdffe00000000000ul,     /* RDR0 bitmask */
 	0x003f000000000000ul,     /* RDR1 bitmask */
@@ -186,7 +186,7 @@
 	0xfffc000000000000ul
 };
 
-static uint64_t *bitmask_array;   /* array of bitmasks to use */
+static const uint64_t *bitmask_array;   /* array of bitmasks to use */
 
 /******************************************************************************
  * Function Prototypes
@@ -200,7 +200,7 @@
 static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 static void perf_start_counters(void);
 static int perf_stop_counters(uint32_t *raddr);
-static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num);
+static const struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num);
 static int perf_rdr_read_ubuf(uint32_t	rdr_num, uint64_t *buffer);
 static int perf_rdr_clear(uint32_t rdr_num);
 static int perf_write_image(uint64_t *memaddr);
@@ -444,7 +444,6 @@
 	uint32_t raddr[4];
 	int error = 0;
 
-	lock_kernel();
 	switch (cmd) {
 
 	    case PA_PERF_ON:
@@ -477,8 +476,6 @@
   	 		error = -ENOTTY;
 	}
 
-	unlock_kernel();
-
 	return error;
 }
 
@@ -655,7 +652,7 @@
  * Retrieve a pointer to the description of what this
  * RDR contains.
  */
-static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num)
+static const struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num)
 {
 	if (perf_processor_interface == ONYX_INTF) {
 		return &perf_rdr_tbl_U[rdr_num];
@@ -673,7 +670,7 @@
 {
 	uint64_t	data, data_mask = 0;
 	uint32_t	width, xbits, i;
-	struct rdr_tbl_ent *tentry;
+	const struct rdr_tbl_ent *tentry;
 
 	tentry = perf_rdr_get_entry(rdr_num);
 	if ((width = tentry->width) == 0)
@@ -721,7 +718,7 @@
  */
 static int perf_rdr_clear(uint32_t	rdr_num)
 {
-	struct rdr_tbl_ent *tentry;
+	const struct rdr_tbl_ent *tentry;
 	int32_t		i;
 
 	tentry = perf_rdr_get_entry(rdr_num);
@@ -753,10 +750,11 @@
 	uint64_t buffer[MAX_RDR_WORDS];
 	uint64_t *bptr;
 	uint32_t dwords;
-	uint32_t *intrigue_rdr;
-	uint64_t *intrigue_bitmask, tmp64;
+	const uint32_t *intrigue_rdr;
+	const uint64_t *intrigue_bitmask;
+	uint64_t tmp64;
 	void __iomem *runway;
-	struct rdr_tbl_ent *tentry;
+	const struct rdr_tbl_ent *tentry;
 	int i;
 
 	/* Clear out counters */
@@ -830,7 +828,7 @@
  */
 static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer)
 {
-	struct rdr_tbl_ent *tentry;
+	const struct rdr_tbl_ent *tentry;
 	int32_t		i;
 
 printk("perf_rdr_write\n");
diff --git a/arch/parisc/kernel/perf_images.h b/arch/parisc/kernel/perf_images.h
index d9562fe..7fef964 100644
--- a/arch/parisc/kernel/perf_images.h
+++ b/arch/parisc/kernel/perf_images.h
@@ -25,7 +25,7 @@
 
 #define PCXU_IMAGE_SIZE 584
 
-static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] = {
+static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] __read_mostly = {
 /*
  * CPI:
  *
@@ -2093,7 +2093,7 @@
 };
 #define PCXW_IMAGE_SIZE 576
 
-static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] = {
+static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] __read_mostly = {
 /*
  * CPI:     FROM CPI.IDF (Image 0)
  *
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 5da4167..e8dea41 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -54,27 +54,6 @@
 #include <asm/uaccess.h>
 #include <asm/unwind.h>
 
-static int hlt_counter __read_mostly;
-
-/*
- * Power off function, if any
- */ 
-void (*pm_power_off)(void);
-
-void disable_hlt(void)
-{
-	hlt_counter++;
-}
-
-EXPORT_SYMBOL(disable_hlt);
-
-void enable_hlt(void)
-{
-	hlt_counter--;
-}
-
-EXPORT_SYMBOL(enable_hlt);
-
 void default_idle(void)
 {
 	barrier();
@@ -102,12 +81,7 @@
 }
 
 
-#ifdef __LP64__
-#define COMMAND_GLOBAL  0xfffffffffffe0030UL
-#else
-#define COMMAND_GLOBAL  0xfffe0030
-#endif
-
+#define COMMAND_GLOBAL  F_EXTEND(0xfffe0030)
 #define CMD_RESET       5       /* reset any module */
 
 /*
@@ -162,6 +136,7 @@
 	*/
 }
 
+void (*chassis_power_off)(void);
 
 /*
  * This routine is called from sys_reboot to actually turn off the
@@ -170,8 +145,8 @@
 void machine_power_off(void)
 {
 	/* If there is a registered power off handler, call it. */
-	if(pm_power_off)
-		pm_power_off();
+	if (chassis_power_off)
+		chassis_power_off();
 
 	/* Put the soft power button back under hardware control.
 	 * If the user had already pressed the power button, the
@@ -187,6 +162,8 @@
 	       KERN_EMERG "Please power this system off now.");
 }
 
+void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
 
 /*
  * Create a kernel thread
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 27160e8..413292f 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -91,7 +91,7 @@
 		int copied;
 
 #ifdef __LP64__
-		if (is_compat_task(child)) {
+		if (personality(child->personality) == PER_LINUX32) {
 			unsigned int tmp;
 
 			addr &= 0xffffffffL;
@@ -123,7 +123,7 @@
 	case PTRACE_POKEDATA:
 		ret = 0;
 #ifdef __LP64__
-		if (is_compat_task(child)) {
+		if (personality(child->personality) == PER_LINUX32) {
 			unsigned int tmp = (unsigned int)data;
 			DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
 				request == PTRACE_POKETEXT ? "TEXT" : "DATA",
@@ -146,7 +146,7 @@
 	case PTRACE_PEEKUSR: {
 		ret = -EIO;
 #ifdef __LP64__
-		if (is_compat_task(child)) {
+		if (personality(child->personality) == PER_LINUX32) {
 			unsigned int tmp;
 
 			if (addr & (sizeof(int)-1))
@@ -205,7 +205,7 @@
 			goto out_tsk;
 		}
 #ifdef __LP64__
-		if (is_compat_task(child)) {
+		if (personality(child->personality) == PER_LINUX32) {
 			if (addr & (sizeof(int)-1))
 				goto out_tsk;
 			if ((addr = translate_usr_offset(addr)) < 0)
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 3a25a7b..05767e8 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -317,7 +317,7 @@
 	
 	if(personality(current->personality) == PER_LINUX32) {
 		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
-		err |= compat_copy_siginfo_to_user(&compat_frame->info, info);
+		err |= copy_siginfo_to_user32(&compat_frame->info, info);
 		DBG(1,"SETUP_RT_FRAME: 1\n");
 		compat_val = (compat_int_t)current->sas_ss_sp;
 		err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
index 0792e20..a6b4231 100644
--- a/arch/parisc/kernel/signal32.c
+++ b/arch/parisc/kernel/signal32.c
@@ -31,7 +31,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 
-#include <asm/compat_signal.h>
 #include <asm/uaccess.h>
 
 #include "signal32.h"
@@ -398,3 +397,104 @@
 
 	return err;
 }
+
+int
+copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
+{
+	unsigned long tmp;
+	int err;
+
+	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
+		return -EFAULT;
+
+	err = __get_user(to->si_signo, &from->si_signo);
+	err |= __get_user(to->si_errno, &from->si_errno);
+	err |= __get_user(to->si_code, &from->si_code);
+
+	if (to->si_code < 0)
+		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+	else {
+		switch (to->si_code >> 16) {
+		      case __SI_CHLD >> 16:
+			err |= __get_user(to->si_utime, &from->si_utime);
+			err |= __get_user(to->si_stime, &from->si_stime);
+			err |= __get_user(to->si_status, &from->si_status);
+		      default:
+			err |= __get_user(to->si_pid, &from->si_pid);
+			err |= __get_user(to->si_uid, &from->si_uid);
+			break;
+		      case __SI_FAULT >> 16:
+			err |= __get_user(tmp, &from->si_addr);
+			to->si_addr = (void __user *) tmp;
+			break;
+		      case __SI_POLL >> 16:
+			err |= __get_user(to->si_band, &from->si_band);
+			err |= __get_user(to->si_fd, &from->si_fd);
+			break;
+		      case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
+		      case __SI_MESGQ >> 16:
+			err |= __get_user(to->si_pid, &from->si_pid);
+			err |= __get_user(to->si_uid, &from->si_uid);
+			err |= __get_user(to->si_int, &from->si_int);
+			break;
+		}
+	}
+	return err;
+}
+
+int
+copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
+{
+	unsigned int addr;
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
+		return -EFAULT;
+
+	/* If you change siginfo_t structure, please be sure
+	   this code is fixed accordingly.
+	   It should never copy any pad contained in the structure
+	   to avoid security leaks, but must copy the generic
+	   3 ints plus the relevant union member.
+	   This routine must convert siginfo from 64bit to 32bit as well
+	   at the same time.  */
+	err = __put_user(from->si_signo, &to->si_signo);
+	err |= __put_user(from->si_errno, &to->si_errno);
+	err |= __put_user((short)from->si_code, &to->si_code);
+	if (from->si_code < 0)
+		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+	else {
+		switch (from->si_code >> 16) {
+		case __SI_CHLD >> 16:
+			err |= __put_user(from->si_utime, &to->si_utime);
+			err |= __put_user(from->si_stime, &to->si_stime);
+			err |= __put_user(from->si_status, &to->si_status);
+		default:
+			err |= __put_user(from->si_pid, &to->si_pid);
+			err |= __put_user(from->si_uid, &to->si_uid);
+			break;
+		case __SI_FAULT >> 16:
+			/* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */
+			err |= __put_user(from->_sifields._pad[0], &to->si_addr);
+			break;
+		case __SI_POLL >> 16:
+			err |= __put_user(from->si_band, &to->si_band);
+			err |= __put_user(from->si_fd, &to->si_fd);
+			break;
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_overrun, &to->si_overrun);
+			addr = (unsigned long) from->si_ptr;
+			err |= __put_user(addr, &to->si_ptr);
+			break;
+		case __SI_RT >> 16:	/* Not generated by the kernel as of now.  */
+		case __SI_MESGQ >> 16:
+			err |= __put_user(from->si_uid, &to->si_uid);
+			err |= __put_user(from->si_pid, &to->si_pid);
+			addr = (unsigned long) from->si_ptr;
+			err |= __put_user(addr, &to->si_ptr);
+			break;
+		}
+	}
+	return err;
+}
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h
index 4d1569e..e39b38a 100644
--- a/arch/parisc/kernel/signal32.h
+++ b/arch/parisc/kernel/signal32.h
@@ -20,8 +20,34 @@
 #define _PARISC64_KERNEL_SIGNAL32_H
 
 #include <linux/compat.h>
-#include <asm/compat_signal.h>
-#include <asm/compat_rt_sigframe.h>
+
+typedef compat_uptr_t compat_sighandler_t;
+
+typedef struct compat_sigaltstack {
+        compat_uptr_t ss_sp;
+        compat_int_t ss_flags;
+        compat_size_t ss_size;
+} compat_stack_t;
+
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+struct compat_sigaction {
+        compat_sighandler_t sa_handler;
+        compat_uint_t sa_flags;
+        compat_sigset_t sa_mask;               /* mask last for extensibility */
+};
+
+/* 32-bit ucontext as seen from an 64-bit kernel */
+struct compat_ucontext {
+        compat_uint_t uc_flags;
+        compat_uptr_t uc_link;
+        compat_stack_t uc_stack;        /* struct compat_sigaltstack (12 bytes)*/
+        /* FIXME: Pad out to get uc_mcontext to start at an 8-byte aligned boundary */
+        compat_uint_t pad[1];
+        struct compat_sigcontext uc_mcontext;
+        compat_sigset_t uc_sigmask;     /* mask last for extensibility */
+};
 
 /* ELF32 signal handling */
 
@@ -29,6 +55,103 @@
 	struct compat_sigaction sa;
 };
 
+typedef struct compat_siginfo {
+        int si_signo;
+        int si_errno;
+        int si_code;
+
+        union {
+                int _pad[((128/sizeof(int)) - 3)];
+
+                /* kill() */
+                struct {
+                        unsigned int _pid;      /* sender's pid */
+                        unsigned int _uid;      /* sender's uid */
+                } _kill;
+
+                /* POSIX.1b timers */
+                struct {
+                        compat_timer_t _tid;            /* timer id */
+                        int _overrun;           /* overrun count */
+                        char _pad[sizeof(unsigned int) - sizeof(int)];
+                        compat_sigval_t _sigval;        /* same as below */
+                        int _sys_private;       /* not to be passed to user */
+                } _timer;
+
+                /* POSIX.1b signals */
+                struct {
+                        unsigned int _pid;      /* sender's pid */
+                        unsigned int _uid;      /* sender's uid */
+                        compat_sigval_t _sigval;
+                } _rt;
+
+                /* SIGCHLD */
+                struct {
+                        unsigned int _pid;      /* which child */
+                        unsigned int _uid;      /* sender's uid */
+                        int _status;            /* exit code */
+                        compat_clock_t _utime;
+                        compat_clock_t _stime;
+                } _sigchld;
+
+                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+                struct {
+                        unsigned int _addr;     /* faulting insn/memory ref. */
+                } _sigfault;
+
+                /* SIGPOLL */
+                struct {
+                        int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                        int _fd;
+                } _sigpoll;
+        } _sifields;
+} compat_siginfo_t;
+
+int copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from);
+int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from);
+
+/* In a deft move of uber-hackery, we decide to carry the top half of all
+ * 64-bit registers in a non-portable, non-ABI, hidden structure.
+ * Userspace can read the hidden structure if it *wants* but is never
+ * guaranteed to be in the same place. Infact the uc_sigmask from the
+ * ucontext_t structure may push the hidden register file downards
+ */
+struct compat_regfile {
+        /* Upper half of all the 64-bit registers that were truncated
+           on a copy to a 32-bit userspace */
+        compat_int_t rf_gr[32];
+        compat_int_t rf_iasq[2];
+        compat_int_t rf_iaoq[2];
+        compat_int_t rf_sar;
+};
+
+#define COMPAT_SIGRETURN_TRAMP 4
+#define COMPAT_SIGRESTARTBLOCK_TRAMP 5
+#define COMPAT_TRAMP_SIZE (COMPAT_SIGRETURN_TRAMP + \
+				COMPAT_SIGRESTARTBLOCK_TRAMP)
+
+struct compat_rt_sigframe {
+        /* XXX: Must match trampoline size in arch/parisc/kernel/signal.c
+                Secondary to that it must protect the ERESTART_RESTARTBLOCK
+                trampoline we left on the stack (we were bad and didn't
+                change sp so we could run really fast.) */
+        compat_uint_t tramp[COMPAT_TRAMP_SIZE];
+        compat_siginfo_t info;
+        struct compat_ucontext uc;
+        /* Hidden location of truncated registers, *must* be last. */
+        struct compat_regfile regs;
+};
+
+/*
+ * The 32-bit ABI wants at least 48 bytes for a function call frame:
+ * 16 bytes for arg0-arg3, and 32 bytes for magic (the only part of
+ * which Linux/parisc uses is sp-20 for the saved return pointer...)
+ * Then, the stack pointer must be rounded to a cache line (64 bytes).
+ */
+#define SIGFRAME32              64
+#define FUNCTIONCALLFRAME32     48
+#define PARISC_RT_SIGFRAME_SIZE32 (((sizeof(struct compat_rt_sigframe) + FUNCTIONCALLFRAME32) + SIGFRAME32) & -SIGFRAME32)
+
 void sigset_32to64(sigset_t *s64, compat_sigset_t *s32);
 void sigset_64to32(compat_sigset_t *s32, sigset_t *s64);
 int do_sigaltstack32 (const compat_stack_t __user *uss32, 
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index d661634..af88afe 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -650,6 +650,8 @@
 #define LWS_ENTRY(_name_) .word  (lws_##_name_ - linux_gateway_page)
 #endif
 
+	.section .rodata,"a"
+
 	.align 4096
 	/* Light-weight-syscall table */
 	/* Start of lws table. */
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 32cbc04..51d2480 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -374,5 +374,24 @@
 	ENTRY_SAME(keyctl)
 	ENTRY_SAME(ioprio_set)
 	ENTRY_SAME(ioprio_get)
+	ENTRY_SAME(inotify_init)
+	ENTRY_SAME(inotify_add_watch)	/* 270 */
+	ENTRY_SAME(inotify_rm_watch)
+	ENTRY_COMP(pselect6)
+	ENTRY_COMP(ppoll)
+	ENTRY_SAME(migrate_pages)
+	ENTRY_COMP(openat)		/* 275 */
+	ENTRY_SAME(mkdirat)
+	ENTRY_SAME(mknodat)
+	ENTRY_SAME(fchownat)
+	ENTRY_COMP(futimesat)
+	ENTRY_COMP(newfstatat)		/* 280 */
+	ENTRY_SAME(unlinkat)
+	ENTRY_SAME(renameat)
+	ENTRY_SAME(linkat)
+	ENTRY_SAME(symlinkat)
+	ENTRY_SAME(readlinkat)		/* 285 */
+	ENTRY_SAME(fchmodat)
+	ENTRY_SAME(faccessat)
 	/* Nothing yet */
 
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 15914f0..ff20060 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -193,10 +193,9 @@
 
 HERE:
 		asm volatile ("copy %%r30, %0" : "=r"(sp));
-		r = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+		r = kzalloc(sizeof(struct pt_regs), GFP_KERNEL);
 		if (!r)
 			return;
-		memset(r, 0, sizeof(struct pt_regs));
 		r->iaoq[0] = (unsigned long)&&HERE;
 		r->gr[2] = (unsigned long)__builtin_return_address(0);
 		r->gr[30] = sp;
diff --git a/arch/parisc/math-emu/decode_exc.c b/arch/parisc/math-emu/decode_exc.c
index f84f258..66c8a9f 100644
--- a/arch/parisc/math-emu/decode_exc.c
+++ b/arch/parisc/math-emu/decode_exc.c
@@ -337,6 +337,7 @@
 		}
 		break;
 	  case INVALIDEXCEPTION:
+	  case OPC_2E_INVALIDEXCEPTION:
 		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
 		return SIGNALCODE(SIGFPE, FPE_FLTINV);
 	  case DIVISIONBYZEROEXCEPTION:
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 720287d..7847ca1 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -371,17 +371,11 @@
 
 void free_initmem(void)
 {
-	/* FIXME: */
-#if 0
-	printk(KERN_INFO "NOT FREEING INITMEM (%dk)\n",
-			(&__init_end - &__init_begin) >> 10);
-	return;
-#else
 	unsigned long addr;
 	
 	printk(KERN_INFO "Freeing unused kernel memory: ");
 
-#if 1
+#ifdef CONFIG_DEBUG_KERNEL
 	/* Attempt to catch anyone trying to execute code here
 	 * by filling the page with BRK insns.
 	 * 
@@ -414,9 +408,21 @@
 	pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
 	
 	printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10);
-#endif
 }
 
+
+#ifdef CONFIG_DEBUG_RODATA
+void mark_rodata_ro(void)
+{
+	extern char __start_rodata, __end_rodata;
+	/* rodata memory was already mapped with KERNEL_RO access rights by
+           pagetable_init() and map_pages(). No need to do additional stuff here */
+	printk (KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+		(unsigned long)(&__end_rodata - &__start_rodata) >> 10);
+}
+#endif
+
+
 /*
  * Just an arbitrary offset to serve as a "hole" between mapping areas
  * (between top of physical memory and a potential pcxl dma mapping
@@ -477,11 +483,6 @@
 
 }
 
-int do_check_pgt_cache(int low, int high)
-{
-	return 0;
-}
-
 unsigned long *empty_zero_page __read_mostly;
 
 void show_mem(void)
@@ -690,7 +691,7 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_end && initrd_end > mem_limit) {
-		printk("initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end);
+		printk(KERN_INFO "initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end);
 		map_pages(initrd_start, __pa(initrd_start),
 			initrd_end - initrd_start, PAGE_KERNEL);
 	}
@@ -792,8 +793,6 @@
 EXPORT_SYMBOL(map_hpux_gateway_page);
 #endif
 
-extern void flush_tlb_all_local(void);
-
 void __init paging_init(void)
 {
 	int i;
@@ -802,7 +801,7 @@
 	pagetable_init();
 	gateway_init();
 	flush_cache_all_local(); /* start with known state */
-	flush_tlb_all_local();
+	flush_tlb_all_local(NULL);
 
 	for (i = 0; i < npmem_ranges; i++) {
 		unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0 };
@@ -993,7 +992,7 @@
 	    do_recycle++;
 	}
 	spin_unlock(&sid_lock);
-	on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
+	on_each_cpu(flush_tlb_all_local, NULL, 1, 1);
 	if (do_recycle) {
 	    spin_lock(&sid_lock);
 	    recycle_sids(recycle_ndirty,recycle_dirty_array);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index df338c5..80d114a 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -83,6 +83,12 @@
 	default y if PPC32 && SMP
 	default n
 
+config DEFAULT_UIMAGE
+	bool
+	help
+	  Used to allow a board to specify it wants a uImage built by default
+	default n
+
 menu "Processor support"
 choice
 	prompt "Processor Type"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 44dd82b..5500ab5 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -142,6 +142,7 @@
 # Default to zImage, override when needed
 defaultimage-y			:= zImage
 defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
+defaultimage-$(CONFIG_DEFAULT_UIMAGE) := uImage
 KBUILD_IMAGE := $(defaultimage-y)
 all: $(KBUILD_IMAGE)
 
@@ -167,6 +168,8 @@
 
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
+
+archmrproper:
 	$(Q)rm -rf arch/$(ARCH)/include
 
 archprepare: checkbin
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index b657f7e..063b84f 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -533,6 +533,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=m
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 3c22ccb..d6fed3f 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -675,6 +675,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index 751a622..c775027 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -567,6 +567,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=m
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 07b6d3d..68194c0 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -454,6 +454,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 0b2b55a..6f6c6be 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -724,6 +724,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index a50ce0f..aa9893a 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -671,6 +671,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index c287980..80e9fe2 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,10 +12,10 @@
 
 obj-y				:= semaphore.o cputable.o ptrace.o syscalls.o \
 				   irq.o align.o signal_32.o pmc.o vdso.o \
-				   init_task.o process.o
+				   init_task.o process.o systbl.o
 obj-y				+= vdso32/
 obj-$(CONFIG_PPC64)		+= setup_64.o binfmt_elf32.o sys_ppc32.o \
-				   signal_64.o ptrace32.o systbl.o \
+				   signal_64.o ptrace32.o \
 				   paca.o cpu_setup_power4.o \
 				   firmware.o sysfs.o idle_64.o
 obj-$(CONFIG_PPC64)		+= vdso64/
@@ -46,7 +46,7 @@
 extra-y				+= vmlinux.lds
 
 obj-y				+= time.o prom.o traps.o setup-common.o udbg.o
-obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o misc_32.o systbl.o
+obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o misc_32.o
 obj-$(CONFIG_PPC64)		+= misc_64.o dma_64.o iommu.o
 obj-$(CONFIG_PPC_MULTIPLATFORM)	+= prom_init.o
 obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index d8da2a3..f20a672 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -227,7 +227,7 @@
 	MTMSRD(r10)
 	lwz	r9,TI_FLAGS(r12)
 	li	r8,-_LAST_ERRNO
-	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
+	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
 	bne-	syscall_exit_work
 	cmplw	0,r3,r8
 	blt+	syscall_exit_cont
@@ -357,7 +357,7 @@
 	lwz	r5,_MSR(r1)
 	andi.	r5,r5,MSR_PR
 	beq	ret_from_except
-	andi.	r0,r9,_TIF_SIGPENDING
+	andi.	r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
 	beq	ret_from_except
 	b	do_user_signal
 8:
@@ -683,7 +683,7 @@
 	/* Check current_thread_info()->flags */
 	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
 	lwz	r9,TI_FLAGS(r9)
-	andi.	r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
+	andi.	r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
 	bne	do_work
 
 restore_user:
@@ -917,7 +917,7 @@
 	lwz	r9,TI_FLAGS(r9)
 	andi.	r0,r9,_TIF_NEED_RESCHED
 	bne-	do_resched
-	andi.	r0,r9,_TIF_SIGPENDING
+	andi.	r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
 	beq	restore_user
 do_user_signal:			/* r10 contains MSR_KERNEL here */
 	ori	r10,r10,MSR_EE
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 5420363..388f861 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -160,7 +160,7 @@
 	mtmsrd	r10,1
 	ld	r9,TI_FLAGS(r12)
 	li	r11,-_LAST_ERRNO
-	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR)
+	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK)
 	bne-	syscall_exit_work
 	cmpld	r3,r11
 	ld	r5,_CCR(r1)
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index e4362df..340730f 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -66,7 +66,7 @@
 #else
 	ld	r4,PACACURRENT(r13)
 	addi	r5,r4,THREAD		/* Get THREAD */
-	ld	r4,THREAD_FPEXC_MODE(r5)
+	lwz	r4,THREAD_FPEXC_MODE(r5)
 	ori	r12,r12,MSR_FP
 	or	r12,r12,r4
 	std	r12,_MSR(r1)
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 3082684..4156596 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -749,11 +749,12 @@
 
 	.globl decrementer_iSeries_masked
 decrementer_iSeries_masked:
+	/* We may not have a valid TOC pointer in here. */
 	li	r11,1
 	ld	r12,PACALPPACAPTR(r13)
 	stb	r11,LPPACADECRINT(r12)
-	LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy)
-	lwz	r12,ADDROFF(tb_ticks_per_jiffy)(r12)
+	LOAD_REG_IMMEDIATE(r12, tb_ticks_per_jiffy)
+	lwz	r12,0(r12)
 	mtspr	SPRN_DEC,r12
 	/* fall through */
 
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 4d9b438..946f321 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -334,9 +334,6 @@
 
 	spin_unlock_irqrestore(&(tbl->it_lock), flags);
 
-	/* Make sure updates are seen by hardware */
-	mb();
-
 	DBG("mapped %d elements:\n", outcount);
 
 	/* For the sake of iommu_unmap_sg, we clear out the length in the
@@ -347,6 +344,10 @@
 		outs->dma_address = DMA_ERROR_CODE;
 		outs->dma_length = 0;
 	}
+
+	/* Make sure updates are seen by hardware */
+	mb();
+
 	return outcount;
 
  failure:
@@ -358,6 +359,8 @@
 			npages = (PAGE_ALIGN(s->dma_address + s->dma_length) - vaddr)
 				>> PAGE_SHIFT;
 			__iommu_free(tbl, vaddr, npages);
+			s->dma_address = DMA_ERROR_CODE;
+			s->dma_length = 0;
 		}
 	}
 	spin_unlock_irqrestore(&(tbl->it_lock), flags);
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index f970ace..c7a799a 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -134,7 +134,6 @@
 	return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags);
 }
 
-#ifdef CONFIG_ISA
 static int __init add_legacy_isa_port(struct device_node *np,
 				      struct device_node *isa_brg)
 {
@@ -168,7 +167,6 @@
 	return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, NO_IRQ, UPF_BOOT_AUTOCONF);
 
 }
-#endif
 
 #ifdef CONFIG_PCI
 static int __init add_legacy_pci_port(struct device_node *np,
@@ -276,7 +274,6 @@
 		of_node_put(soc);
 	}
 
-#ifdef CONFIG_ISA
 	/* First fill our array with ISA ports */
 	for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
 		struct device_node *isa = of_get_parent(np);
@@ -287,7 +284,6 @@
 		}
 		of_node_put(isa);
 	}
-#endif
 
 #ifdef CONFIG_PCI
 	/* Next, try to locate PCI ports */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d50c8df..294832a 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -491,7 +491,12 @@
 	size = 16;
 	finish_node(allnodes, &size, 1);
 	size -= 16;
-	end = start = (unsigned long) __va(lmb_alloc(size, 128));
+
+	if (0 == size)
+		end = start = 0;
+	else
+		end = start = (unsigned long)__va(lmb_alloc(size, 128));
+
 	finish_node(allnodes, &end, 0);
 	BUG_ON(end != start + size);
 
@@ -1398,8 +1403,8 @@
 
 	read_lock(&devtree_lock);
 	np = from ? from->allnext : allnodes;
-	for (; np != 0; np = np->allnext)
-		if (np->name != 0 && strcasecmp(np->name, name) == 0
+	for (; np != NULL; np = np->allnext)
+		if (np->name != NULL && strcasecmp(np->name, name) == 0
 		    && of_node_get(np))
 			break;
 	if (from)
@@ -1917,3 +1922,30 @@
 
 	return 0;
 }
+
+#ifdef CONFIG_KEXEC
+/* We may have allocated the flat device tree inside the crash kernel region
+ * in prom_init. If so we need to move it out into regular memory. */
+void kdump_move_device_tree(void)
+{
+	unsigned long start, end;
+	struct boot_param_header *new;
+
+	start = __pa((unsigned long)initial_boot_params);
+	end = start + initial_boot_params->totalsize;
+
+	if (end < crashk_res.start || start > crashk_res.end)
+		return;
+
+	new = (struct boot_param_header*)
+		__va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE));
+
+	memcpy(new, initial_boot_params, initial_boot_params->totalsize);
+
+	initial_boot_params = new;
+
+	DBG("Flat device tree blob moved to %p\n", initial_boot_params);
+
+	/* XXX should we unreserve the old DT? */
+}
+#endif /* CONFIG_KEXEC */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 7881ec9..ec7153f 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2098,6 +2098,10 @@
 	 */
 	prom_init_stdout();
 
+	/* Bail if this is a kdump kernel. */
+	if (PHYSICAL_START > 0)
+		prom_panic("Error: You can't boot a kdump kernel from OF!\n");
+
 	/*
 	 * Check for an initrd
 	 */
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index a8099c8..3934c22 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -465,8 +465,10 @@
 	if (parent == NULL)
 		return NULL;
 	bus = of_match_bus(parent);
-	if (strcmp(bus->name, "pci"))
+	if (strcmp(bus->name, "pci")) {
+		of_node_put(parent);
 		return NULL;
+	}
 	bus->count_cells(dev, &na, &ns);
 	of_node_put(parent);
 	if (!OF_CHECK_COUNTS(na, ns))
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 7fe4a5c..b5b2add 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -22,6 +22,7 @@
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
+#include <asm/hvcall.h>
 #include <asm/semaphore.h>
 #include <asm/machdep.h>
 #include <asm/page.h>
@@ -565,6 +566,7 @@
 #ifdef CONFIG_PPC_PSERIES
 static void rtas_percpu_suspend_me(void *info)
 {
+	int i;
 	long rc;
 	long flags;
 	struct rtas_suspend_me_data *data =
@@ -587,18 +589,16 @@
 
 	if (rc == H_Continue) {
 		data->waiting = 0;
-		rtas_call(ibm_suspend_me_token, 0, 1,
-			  data->args->args);
+		data->args->args[data->args->nargs] =
+			rtas_call(ibm_suspend_me_token, 0, 1, NULL);
+		for_each_cpu(i)
+			plpar_hcall_norets(H_PROD,i);
 	} else {
 		data->waiting = -EBUSY;
 		printk(KERN_ERR "Error on H_Join hypervisor call\n");
 	}
 
 out:
-	/* before we restore interrupts, make sure we don't
-	 * generate a spurious soft lockup errors
-	 */
-	touch_softlockup_watchdog();
 	local_irq_restore(flags);
 	return;
 }
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 5050009..aaf384c 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -672,8 +672,7 @@
 static void remove_flash_pde(struct proc_dir_entry *dp)
 {
 	if (dp) {
-		if (dp->data != NULL)
-			kfree(dp->data);
+		kfree(dp->data);
 		dp->owner = NULL;
 		remove_proc_entry(dp->name, dp->parent);
 	}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e29b275..a717dff 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -398,6 +398,9 @@
 {
 	DBG(" -> setup_system()\n");
 
+#ifdef CONFIG_KEXEC
+	kdump_move_device_tree();
+#endif
 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
 	 */
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 177bba7..bd837b5 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -142,11 +142,7 @@
 	return 0;
 }
 
-static inline compat_uptr_t to_user_ptr(void *kp)
-{
-	return (compat_uptr_t)(u64)kp;
-}
-
+#define to_user_ptr(p)		ptr_to_compat(p)
 #define from_user_ptr(p)	compat_ptr(p)
 
 static inline int save_general_regs(struct pt_regs *regs,
@@ -213,8 +209,8 @@
 	return 0;
 }
 
-#define to_user_ptr(p)		(p)
-#define from_user_ptr(p)	(p)
+#define to_user_ptr(p)		((unsigned long)(p))
+#define from_user_ptr(p)	((void __user *)(p))
 
 static inline int save_general_regs(struct pt_regs *regs,
 		struct mcontext __user *frame)
@@ -252,67 +248,19 @@
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
-	       struct pt_regs *regs)
+long sys_sigsuspend(old_sigset_t mask)
 {
-	sigset_t saveset;
-
 	mask &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs->result = -EINTR;
-	regs->gpr[3] = EINTR;
-	regs->ccr |= 0x10000000;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs)) {
-			set_thread_flag(TIF_RESTOREALL);
-			return 0;
-		}
-	}
-}
-
-long sys_rt_sigsuspend(
-#ifdef CONFIG_PPC64
-		compat_sigset_t __user *unewset,
-#else
-		sigset_t __user *unewset,
-#endif
-		size_t sigsetsize, int p3, int p4,
-		int p6, int p7, struct pt_regs *regs)
-{
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (get_sigset_t(&newset, unewset))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->result = -EINTR;
-	regs->gpr[3] = EINTR;
-	regs->ccr |= 0x10000000;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs)) {
-			set_thread_flag(TIF_RESTOREALL);
-			return 0;
-		}
-	}
+ 	current->state = TASK_INTERRUPTIBLE;
+ 	schedule();
+ 	set_thread_flag(TIF_RESTORE_SIGMASK);
+ 	return -ERESTARTNOHAND;
 }
 
 #ifdef CONFIG_PPC32
@@ -574,7 +522,7 @@
 
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 	if (!ret && oact) {
-		ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
+		ret = put_user(to_user_ptr(old_ka.sa.sa_handler), &oact->sa_handler);
 		ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask);
 		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 	}
@@ -723,8 +671,8 @@
 int compat_sys_sigaltstack(u32 __new, u32 __old, int r5,
 		      int r6, int r7, int r8, struct pt_regs *regs)
 {
-	stack_32_t __user * newstack = (stack_32_t __user *)(long) __new;
-	stack_32_t __user * oldstack = (stack_32_t __user *)(long) __old;
+	stack_32_t __user * newstack = compat_ptr(__new);
+	stack_32_t __user * oldstack = compat_ptr(__old);
 	stack_t uss, uoss;
 	int ret;
 	mm_segment_t old_fs;
@@ -756,7 +704,7 @@
 	set_fs(old_fs);
 	/* Copy the stack information to the user output buffer */
 	if (!ret && oldstack  &&
-		(put_user((long)uoss.ss_sp, &oldstack->ss_sp) ||
+		(put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) ||
 		 __put_user(uoss.ss_flags, &oldstack->ss_flags) ||
 		 __put_user(uoss.ss_size, &oldstack->ss_size)))
 		return -EFAULT;
@@ -1174,7 +1122,7 @@
 {
 	siginfo_t info;
 	struct k_sigaction ka;
-	unsigned int frame, newsp;
+	unsigned int newsp;
 	int signr, ret;
 
 #ifdef CONFIG_PPC32
@@ -1185,11 +1133,11 @@
 	}
 #endif
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else if (!oldset)
 		oldset = &current->blocked;
 
-	newsp = frame = 0;
-
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 #ifdef CONFIG_PPC32
 no_signal:
@@ -1219,8 +1167,14 @@
 		}
 	}
 
-	if (signr == 0)
+	if (signr == 0) {
+		/* No signal to deliver -- put the saved sigmask back */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+		}
 		return 0;		/* no signals delivered */
+	}
 
 	if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
 	    && !on_sig_stack(regs->gpr[1]))
@@ -1253,6 +1207,10 @@
 			sigaddset(&current->blocked, signr);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
+		/* A signal was successfully delivered; the saved sigmask is in
+		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
 	}
 
 	return ret;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 7b9d999..497a5d3 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -60,49 +60,13 @@
 	struct ucontext uc;
 	unsigned long _unused[2];
 	unsigned int tramp[TRAMP_SIZE];
-	struct siginfo *pinfo;
-	void *puc;
+	struct siginfo __user *pinfo;
+	void __user *puc;
 	struct siginfo info;
 	/* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
 	char abigap[288];
 } __attribute__ ((aligned (16)));
 
-
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4,
-		       int p6, int p7, struct pt_regs *regs)
-{
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->result = -EINTR;
-	regs->gpr[3] = EINTR;
-	regs->ccr |= 0x10000000;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs)) {
-			set_thread_flag(TIF_RESTOREALL);
-			return 0;
-		}
-	}
-}
-
 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
 		     unsigned long r6, unsigned long r7, unsigned long r8,
 		     struct pt_regs *regs)
@@ -556,11 +520,15 @@
 	if (test_thread_flag(TIF_32BIT))
 		return do_signal32(oldset, regs);
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else if (!oldset)
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
+		int ret;
+
 		/* Whee!  Actually deliver the signal.  */
 		if (TRAP(regs) == 0x0C00)
 			syscall_restart(regs, &ka);
@@ -573,7 +541,14 @@
 		if (current->thread.dabr)
 			set_dabr(current->thread.dabr);
 
-		return handle_signal(signr, &ka, &info, oldset, regs);
+		ret = handle_signal(signr, &ka, &info, oldset, regs);
+
+		/* If a signal was successfully delivered, the saved sigmask is in
+		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
+		if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+		return ret;
 	}
 
 	if (TRAP(regs) == 0x0C00) {	/* System Call! */
@@ -589,6 +564,11 @@
 			regs->result = 0;
 		}
 	}
+	/* No signal to deliver -- put the saved sigmask back */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 
 	return 0;
 }
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index c8458c5..13595a6 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -540,6 +540,9 @@
 	if (smp_ops->take_timebase)
 		smp_ops->take_timebase();
 
+	if (system_state > SYSTEM_BOOTING)
+		per_cpu(last_jiffy, cpu) = get_tb();
+
 	spin_lock(&call_lock);
 	cpu_set(cpu, cpu_online_map);
 	spin_unlock(&call_lock);
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 6801317..8a9f994 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -36,8 +36,6 @@
 #ifdef CONFIG_PPC64
 #define sys_sigpending	sys_ni_syscall
 #define sys_old_getrlimit sys_ni_syscall
-#else
-#define ppc_rtas	sys_ni_syscall
 #endif
 
 _GLOBAL(sys_call_table)
@@ -321,3 +319,6 @@
 SYSCALL(inotify_rm_watch)
 SYSCALL(spu_run)
 SYSCALL(spu_create)
+COMPAT_SYS(pselect6)
+COMPAT_SYS(ppoll)
+SYSCALL(unshare)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index c4a294d..1886045 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -612,10 +612,10 @@
 
 	ppc_tb_freq = DEFAULT_TB_FREQ;		/* hardcoded default */
 	node_found = 0;
-	if (cpu != 0) {
+	if (cpu) {
 		fp = (unsigned int *)get_property(cpu, "timebase-frequency",
 						  NULL);
-		if (fp != 0) {
+		if (fp) {
 			node_found = 1;
 			ppc_tb_freq = *fp;
 		}
@@ -626,10 +626,10 @@
 
 	ppc_proc_freq = DEFAULT_PROC_FREQ;
 	node_found = 0;
-	if (cpu != 0) {
+	if (cpu) {
 		fp = (unsigned int *)get_property(cpu, "clock-frequency",
 						  NULL);
-		if (fp != 0) {
+		if (fp) {
 			node_found = 1;
 			ppc_proc_freq = *fp;
 		}
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 2da65a9..5d29dcc 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -144,7 +144,7 @@
 }
 
 #ifdef CONFIG_PPC_MAPLE
-void udbg_maple_real_putc(unsigned char c)
+void udbg_maple_real_putc(char c)
 {
 	if (udbg_comport) {
 		while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c
index 9584608..bbe3eac 100644
--- a/arch/powerpc/mm/lmb.c
+++ b/arch/powerpc/mm/lmb.c
@@ -197,6 +197,8 @@
 {
 	struct lmb_region *_rgn = &(lmb.reserved);
 
+	BUG_ON(0 == size);
+
 	return lmb_add_region(_rgn, base, size);
 }
 
@@ -227,6 +229,8 @@
 	long i, j;
 	unsigned long base = 0;
 
+	BUG_ON(0 == size);
+
 #ifdef CONFIG_PPC32
 	/* On 32-bit, make sure we allocate lowmem */
 	if (max_addr == LMB_ALLOC_ANYWHERE)
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 15aac0d..550517c 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -435,17 +435,12 @@
 {
 	clear_page(page);
 
-	if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
-		return;
 	/*
 	 * We shouldnt have to do this, but some versions of glibc
 	 * require it (ld.so assumes zero filled pages are icache clean)
 	 * - Anton
 	 */
-
-	/* avoid an atomic op if possible */
-	if (test_bit(PG_arch_1, &pg->flags))
-		clear_bit(PG_arch_1, &pg->flags);
+	flush_dcache_page(pg);
 }
 EXPORT_SYMBOL(clear_user_page);
 
@@ -469,12 +464,7 @@
 		return;
 #endif
 
-	if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
-		return;
-
-	/* avoid an atomic op if possible */
-	if (test_bit(PG_arch_1, &pg->flags))
-		clear_bit(PG_arch_1, &pg->flags);
+	flush_dcache_page(pg);
 }
 
 void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 16031b5..3b998a3 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -2,7 +2,7 @@
 obj-y			+= pervasive.o
 
 obj-$(CONFIG_SMP)	+= smp.o
-obj-$(CONFIG_SPU_FS)	+= spufs/ spu-base.o
+obj-$(CONFIG_SPU_FS)	+= spu-base.o spufs/
 
 spu-base-y		+= spu_base.o spu_priv1.o
 
diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h
index 3a2057f..814f547 100644
--- a/arch/powerpc/platforms/chrp/chrp.h
+++ b/arch/powerpc/platforms/chrp/chrp.h
@@ -5,7 +5,6 @@
 extern void chrp_nvram_init(void);
 extern void chrp_get_rtc_time(struct rtc_time *);
 extern int chrp_set_rtc_time(struct rtc_time *);
-extern void chrp_calibrate_decr(void);
 extern long chrp_time_init(void);
 
 extern void chrp_find_bridges(void);
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 00c52f2..8ef279a 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -204,9 +204,11 @@
 	struct device_node *root = find_path_device("/");
 	struct device_node *rtas;
 
+	of_node_get(root);
 	rtas = of_find_node_by_name (root, "rtas");
 	if (rtas) {
 		hose->ops = &rtas_pci_ops;
+		of_node_put(rtas);
 	} else {
 		printk ("RTAS supporting Pegasos OF not found, please upgrade"
 			" your firmware\n");
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 2dc87aa..e1fadbf 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -506,7 +506,7 @@
 	ppc_md.halt           = rtas_halt;
 
 	ppc_md.time_init      = chrp_time_init;
-	ppc_md.calibrate_decr = chrp_calibrate_decr;
+	ppc_md.calibrate_decr = generic_calibrate_decr;
 
 	/* this may get overridden with rtas routines later... */
 	ppc_md.set_rtc_time   = chrp_set_rtc_time;
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
index 36a0f97..78df2e7 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -167,24 +167,3 @@
 	tm->tm_mon = mon;
 	tm->tm_year = year;
 }
-
-
-void __init chrp_calibrate_decr(void)
-{
-	struct device_node *cpu;
-	unsigned int freq, *fp;
-
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
-	freq = 16666000;		/* hardcoded default */
-	cpu = find_type_devices("cpu");
-	if (cpu != 0) {
-		fp = (unsigned int *)
-			get_property(cpu, "timebase-frequency", NULL);
-		if (fp != 0)
-			freq = *fp;
-	}
-	ppc_tb_freq = freq;
-}
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 535c802..87eb6bb 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1052,8 +1052,7 @@
 }
 EXPORT_SYMBOL_GPL(pmac_i2c_adapter_to_bus);
 
-extern int pmac_i2c_match_adapter(struct device_node *dev,
-				  struct i2c_adapter *adapter)
+int pmac_i2c_match_adapter(struct device_node *dev, struct i2c_adapter *adapter)
 {
 	struct pmac_i2c_bus *bus = pmac_i2c_find_bus(dev);
 
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index f671ed2..de3f30e 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -136,14 +136,14 @@
 	|(((unsigned int)(off)) & 0xFCUL) \
 	|1UL)
 
-static unsigned long macrisc_cfg_access(struct pci_controller* hose,
+static volatile void __iomem *macrisc_cfg_access(struct pci_controller* hose,
 					       u8 bus, u8 dev_fn, u8 offset)
 {
 	unsigned int caddr;
 
 	if (bus == hose->first_busno) {
 		if (dev_fn < (11 << 3))
-			return 0;
+			return NULL;
 		caddr = MACRISC_CFA0(dev_fn, offset);
 	} else
 		caddr = MACRISC_CFA1(bus, dev_fn, offset);
@@ -154,14 +154,14 @@
 	} while (in_le32(hose->cfg_addr) != caddr);
 
 	offset &= has_uninorth ? 0x07 : 0x03;
-	return ((unsigned long)hose->cfg_data) + offset;
+	return hose->cfg_data + offset;
 }
 
 static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn,
 				      int offset, int len, u32 *val)
 {
 	struct pci_controller *hose;
-	unsigned long addr;
+	volatile void __iomem *addr;
 
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
@@ -177,13 +177,13 @@
 	 */
 	switch (len) {
 	case 1:
-		*val = in_8((u8 *)addr);
+		*val = in_8(addr);
 		break;
 	case 2:
-		*val = in_le16((u16 *)addr);
+		*val = in_le16(addr);
 		break;
 	default:
-		*val = in_le32((u32 *)addr);
+		*val = in_le32(addr);
 		break;
 	}
 	return PCIBIOS_SUCCESSFUL;
@@ -193,7 +193,7 @@
 				       int offset, int len, u32 val)
 {
 	struct pci_controller *hose;
-	unsigned long addr;
+	volatile void __iomem *addr;
 
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
@@ -209,16 +209,16 @@
 	 */
 	switch (len) {
 	case 1:
-		out_8((u8 *)addr, val);
-		(void) in_8((u8 *)addr);
+		out_8(addr, val);
+		(void) in_8(addr);
 		break;
 	case 2:
-		out_le16((u16 *)addr, val);
-		(void) in_le16((u16 *)addr);
+		out_le16(addr, val);
+		(void) in_le16(addr);
 		break;
 	default:
-		out_le32((u32 *)addr, val);
-		(void) in_le32((u32 *)addr);
+		out_le32(addr, val);
+		(void) in_le32(addr);
 		break;
 	}
 	return PCIBIOS_SUCCESSFUL;
@@ -348,25 +348,23 @@
 		+ (((unsigned int)bus) << 16) \
 		+ 0x01000000UL)
 
-static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
+static volatile void __iomem *u3_ht_cfg_access(struct pci_controller* hose,
 					     u8 bus, u8 devfn, u8 offset)
 {
 	if (bus == hose->first_busno) {
 		/* For now, we don't self probe U3 HT bridge */
 		if (PCI_SLOT(devfn) == 0)
-			return 0;
-		return ((unsigned long)hose->cfg_data) +
-			U3_HT_CFA0(devfn, offset);
+			return NULL;
+		return hose->cfg_data + U3_HT_CFA0(devfn, offset);
 	} else
-		return ((unsigned long)hose->cfg_data) +
-			U3_HT_CFA1(bus, devfn, offset);
+		return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
 }
 
 static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
 				    int offset, int len, u32 *val)
 {
 	struct pci_controller *hose;
-	unsigned long addr;
+	volatile void __iomem *addr;
 
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
@@ -400,13 +398,13 @@
 	 */
 	switch (len) {
 	case 1:
-		*val = in_8((u8 *)addr);
+		*val = in_8(addr);
 		break;
 	case 2:
-		*val = in_le16((u16 *)addr);
+		*val = in_le16(addr);
 		break;
 	default:
-		*val = in_le32((u32 *)addr);
+		*val = in_le32(addr);
 		break;
 	}
 	return PCIBIOS_SUCCESSFUL;
@@ -416,7 +414,7 @@
 				     int offset, int len, u32 val)
 {
 	struct pci_controller *hose;
-	unsigned long addr;
+	volatile void __iomem *addr;
 
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
@@ -442,16 +440,16 @@
 	 */
 	switch (len) {
 	case 1:
-		out_8((u8 *)addr, val);
-		(void) in_8((u8 *)addr);
+		out_8(addr, val);
+		(void) in_8(addr);
 		break;
 	case 2:
-		out_le16((u16 *)addr, val);
-		(void) in_le16((u16 *)addr);
+		out_le16(addr, val);
+		(void) in_le16(addr);
 		break;
 	default:
-		out_le32((u32 *)addr, val);
-		(void) in_le32((u32 *)addr);
+		out_le32((u32 __iomem *)addr, val);
+		(void) in_le32(addr);
 		break;
 	}
 	return PCIBIOS_SUCCESSFUL;
@@ -476,7 +474,7 @@
 	 |(((unsigned int)(off)) & 0xfcU)	\
 	 |1UL)
 
-static unsigned long u4_pcie_cfg_access(struct pci_controller* hose,
+static volatile void __iomem *u4_pcie_cfg_access(struct pci_controller* hose,
 					u8 bus, u8 dev_fn, int offset)
 {
 	unsigned int caddr;
@@ -492,14 +490,14 @@
 	} while (in_le32(hose->cfg_addr) != caddr);
 
 	offset &= 0x03;
-	return ((unsigned long)hose->cfg_data) + offset;
+	return hose->cfg_data + offset;
 }
 
 static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
 			       int offset, int len, u32 *val)
 {
 	struct pci_controller *hose;
-	unsigned long addr;
+	volatile void __iomem *addr;
 
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
@@ -515,13 +513,13 @@
 	 */
 	switch (len) {
 	case 1:
-		*val = in_8((u8 *)addr);
+		*val = in_8(addr);
 		break;
 	case 2:
-		*val = in_le16((u16 *)addr);
+		*val = in_le16(addr);
 		break;
 	default:
-		*val = in_le32((u32 *)addr);
+		*val = in_le32(addr);
 		break;
 	}
 	return PCIBIOS_SUCCESSFUL;
@@ -531,7 +529,7 @@
 				int offset, int len, u32 val)
 {
 	struct pci_controller *hose;
-	unsigned long addr;
+	volatile void __iomem *addr;
 
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
@@ -547,16 +545,16 @@
 	 */
 	switch (len) {
 	case 1:
-		out_8((u8 *)addr, val);
-		(void) in_8((u8 *)addr);
+		out_8(addr, val);
+		(void) in_8(addr);
 		break;
 	case 2:
-		out_le16((u16 *)addr, val);
-		(void) in_le16((u16 *)addr);
+		out_le16(addr, val);
+		(void) in_le16(addr);
 		break;
 	default:
-		out_le32((u32 *)addr, val);
-		(void) in_le32((u32 *)addr);
+		out_le32(addr, val);
+		(void) in_le32(addr);
 		break;
 	}
 	return PCIBIOS_SUCCESSFUL;
@@ -773,8 +771,7 @@
 	 * the reg address cell, we shall fix that by killing struct
 	 * reg_property and using some accessor functions instead
 	 */
-	hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000,
-							   0x02000000);
+	hose->cfg_data = ioremap(0xf2000000, 0x02000000);
 
 	/*
 	 * /ht node doesn't expose a "ranges" property, so we "remove"
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index c32c623..356a739 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -862,21 +862,28 @@
 		spin_unlock_irqrestore(&pmf_lock, flags);
 		return -ENODEV;
 	}
+	if (list_empty(&func->irq_clients))
+		func->dev->handlers->irq_enable(func);
 	list_add(&client->link, &func->irq_clients);
+	client->func = func;
 	spin_unlock_irqrestore(&pmf_lock, flags);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pmf_register_irq_client);
 
-void pmf_unregister_irq_client(struct device_node *np,
-			      const char *name,
-			      struct pmf_irq_client *client)
+void pmf_unregister_irq_client(struct pmf_irq_client *client)
 {
+	struct pmf_function *func = client->func;
 	unsigned long flags;
 
+	BUG_ON(func == NULL);
+
 	spin_lock_irqsave(&pmf_lock, flags);
+	client->func = NULL;
 	list_del(&client->link);
+	if (list_empty(&func->irq_clients))
+		func->dev->handlers->irq_disable(func);
 	spin_unlock_irqrestore(&pmf_lock, flags);
 }
 EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 89c4c36..1955462 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -82,8 +82,6 @@
 
 #undef SHOW_GATWICK_IRQS
 
-unsigned char drive_info;
-
 int ppc_override_l2cr = 0;
 int ppc_override_l2cr_value;
 int has_l2cache = 0;
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 6373372..e3cbba4 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -333,7 +333,7 @@
 		rc = eeh_reset_device(frozen_pdn, NULL);
 		if (rc)
 			goto hard_fail;
-		pci_walk_bus(frozen_bus, eeh_report_reset, 0);
+		pci_walk_bus(frozen_bus, eeh_report_reset, NULL);
 	}
 
 	/* If all devices reported they can proceed, the re-enable PIO */
@@ -342,11 +342,11 @@
 		rc = eeh_reset_device(frozen_pdn, NULL);
 		if (rc)
 			goto hard_fail;
-		pci_walk_bus(frozen_bus, eeh_report_reset, 0);
+		pci_walk_bus(frozen_bus, eeh_report_reset, NULL);
 	}
 
 	/* Tell all device drivers that they can resume operations */
-	pci_walk_bus(frozen_bus, eeh_report_resume, 0);
+	pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
 
 	return;
 	
@@ -367,7 +367,7 @@
 	eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
 
 	/* Notify all devices that they're about to go down. */
-	pci_walk_bus(frozen_bus, eeh_report_failure, 0);
+	pci_walk_bus(frozen_bus, eeh_report_failure, NULL);
 
 	/* Shut down the device drivers for good. */
 	pcibios_remove_pci_devices(frozen_bus);
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 2193478..bdaa8aa 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -58,6 +58,7 @@
 
 	return find_bus_among_children(pdn->phb->bus, dn);
 }
+EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
 
 /**
  * pcibios_remove_pci_devices - remove all devices under this bus
@@ -106,6 +107,7 @@
 		}
 	}
 }
+EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
 
 static int
 pcibios_pci_config_bridge(struct pci_dev *dev)
@@ -172,3 +174,4 @@
 			pcibios_pci_config_bridge(dev);
 	}
 }
+EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index da6ceba..9edeca8 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -585,7 +585,7 @@
 static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
 {
 	/* Don't risk a hypervisor call if we're crashing */
-	if (!crash_shutdown) {
+	if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
 		unsigned long vpa = __pa(get_lppaca());
 
 		if (unregister_vpa(hard_smp_processor_id(), vpa)) {
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 977de9d..6298264 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -59,7 +59,7 @@
 static u32 *dart_vbase;
 
 /* Mapped base address for the dart */
-static unsigned int *__iomem dart;
+static unsigned int __iomem *dart;
 
 /* Dummy val that entries are set to when unused */
 static unsigned int dart_emptyval;
diff --git a/arch/ppc/configs/bamboo_defconfig b/arch/ppc/configs/bamboo_defconfig
index 0ba4e70..41fd393 100644
--- a/arch/ppc/configs/bamboo_defconfig
+++ b/arch/ppc/configs/bamboo_defconfig
@@ -499,6 +499,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/ppc/configs/katana_defconfig b/arch/ppc/configs/katana_defconfig
index 0f3bb9a..7311fe6 100644
--- a/arch/ppc/configs/katana_defconfig
+++ b/arch/ppc/configs/katana_defconfig
@@ -488,6 +488,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig
index 673dc64..b96a6d6 100644
--- a/arch/ppc/configs/mpc834x_sys_defconfig
+++ b/arch/ppc/configs/mpc834x_sys_defconfig
@@ -402,6 +402,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
index 93da595..a1ef929 100644
--- a/arch/ppc/configs/power3_defconfig
+++ b/arch/ppc/configs/power3_defconfig
@@ -442,6 +442,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index 3e6ca7f..c1e89ad 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -810,13 +810,16 @@
 	mtspr	SPRN_MD_TWC, r9
 	li	r11, MI_BOOTINIT	/* Create RPN for address 0 */
 	addis	r11, r11, 0x0080	/* Add 8M */
-	mtspr	SPRN_MD_RPN, r8
+	mtspr	SPRN_MD_RPN, r11
+
+	addi	r10, r10, 0x0100
+	mtspr	SPRN_MD_CTR, r10
 
 	addis	r8, r8, 0x0080		/* Add 8M */
 	mtspr	SPRN_MD_EPN, r8
 	mtspr	SPRN_MD_TWC, r9
 	addis	r11, r11, 0x0080	/* Add 8M */
-	mtspr	SPRN_MD_RPN, r8
+	mtspr	SPRN_MD_RPN, r11
 #endif
 
 	/* Since the cache is enabled according to the information we
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index c3427ee..5a93656 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -1048,286 +1048,3 @@
 	blr
 
 SYSCALL(execve)
-
-/* Why isn't this a) automatic, b) written in 'C'? */
-	.data
-	.align 4
-_GLOBAL(sys_call_table)
-	.long sys_restart_syscall /* 0 */
-	.long sys_exit
-	.long ppc_fork
-	.long sys_read
-	.long sys_write
-	.long sys_open		/* 5 */
-	.long sys_close
-	.long sys_waitpid
-	.long sys_creat
-	.long sys_link
-	.long sys_unlink	/* 10 */
-	.long sys_execve
-	.long sys_chdir
-	.long sys_time
-	.long sys_mknod
-	.long sys_chmod		/* 15 */
-	.long sys_lchown
-	.long sys_ni_syscall			/* old break syscall holder */
-	.long sys_stat
-	.long sys_lseek
-	.long sys_getpid	/* 20 */
-	.long sys_mount
-	.long sys_oldumount
-	.long sys_setuid
-	.long sys_getuid
-	.long sys_stime		/* 25 */
-	.long sys_ptrace
-	.long sys_alarm
-	.long sys_fstat
-	.long sys_pause
-	.long sys_utime		/* 30 */
-	.long sys_ni_syscall			/* old stty syscall holder */
-	.long sys_ni_syscall			/* old gtty syscall holder */
-	.long sys_access
-	.long sys_nice
-	.long sys_ni_syscall	/* 35 */	/* old ftime syscall holder */
-	.long sys_sync
-	.long sys_kill
-	.long sys_rename
-	.long sys_mkdir
-	.long sys_rmdir		/* 40 */
-	.long sys_dup
-	.long sys_pipe
-	.long sys_times
-	.long sys_ni_syscall			/* old prof syscall holder */
-	.long sys_brk		/* 45 */
-	.long sys_setgid
-	.long sys_getgid
-	.long sys_signal
-	.long sys_geteuid
-	.long sys_getegid	/* 50 */
-	.long sys_acct
-	.long sys_umount			/* recycled never used phys() */
-	.long sys_ni_syscall			/* old lock syscall holder */
-	.long sys_ioctl
-	.long sys_fcntl		/* 55 */
-	.long sys_ni_syscall			/* old mpx syscall holder */
-	.long sys_setpgid
-	.long sys_ni_syscall			/* old ulimit syscall holder */
-	.long sys_olduname
-	.long sys_umask		/* 60 */
-	.long sys_chroot
-	.long sys_ustat
-	.long sys_dup2
-	.long sys_getppid
-	.long sys_getpgrp	/* 65 */
-	.long sys_setsid
-	.long sys_sigaction
-	.long sys_sgetmask
-	.long sys_ssetmask
-	.long sys_setreuid	/* 70 */
-	.long sys_setregid
-	.long sys_sigsuspend
-	.long sys_sigpending
-	.long sys_sethostname
-	.long sys_setrlimit	/* 75 */
-	.long sys_old_getrlimit
-	.long sys_getrusage
-	.long sys_gettimeofday
-	.long sys_settimeofday
-	.long sys_getgroups	/* 80 */
-	.long sys_setgroups
-	.long ppc_select
-	.long sys_symlink
-	.long sys_lstat
-	.long sys_readlink	/* 85 */
-	.long sys_uselib
-	.long sys_swapon
-	.long sys_reboot
-	.long old_readdir
-	.long sys_mmap		/* 90 */
-	.long sys_munmap
-	.long sys_truncate
-	.long sys_ftruncate
-	.long sys_fchmod
-	.long sys_fchown	/* 95 */
-	.long sys_getpriority
-	.long sys_setpriority
-	.long sys_ni_syscall			/* old profil syscall holder */
-	.long sys_statfs
-	.long sys_fstatfs	/* 100 */
-	.long sys_ni_syscall
-	.long sys_socketcall
-	.long sys_syslog
-	.long sys_setitimer
-	.long sys_getitimer	/* 105 */
-	.long sys_newstat
-	.long sys_newlstat
-	.long sys_newfstat
-	.long sys_uname
-	.long sys_ni_syscall	/* 110 */
-	.long sys_vhangup
-	.long sys_ni_syscall	/* old 'idle' syscall */
-	.long sys_ni_syscall
-	.long sys_wait4
-	.long sys_swapoff	/* 115 */
-	.long sys_sysinfo
-	.long sys_ipc
-	.long sys_fsync
-	.long sys_sigreturn
-	.long ppc_clone		/* 120 */
-	.long sys_setdomainname
-	.long sys_newuname
-	.long sys_ni_syscall
-	.long sys_adjtimex
-	.long sys_mprotect	/* 125 */
-	.long sys_sigprocmask
-	.long sys_ni_syscall	/* old sys_create_module */
-	.long sys_init_module
-	.long sys_delete_module
-	.long sys_ni_syscall	/* old sys_get_kernel_syms */	/* 130 */
-	.long sys_quotactl
-	.long sys_getpgid
-	.long sys_fchdir
-	.long sys_bdflush
-	.long sys_sysfs		/* 135 */
-	.long sys_personality
-	.long sys_ni_syscall	/* for afs_syscall */
-	.long sys_setfsuid
-	.long sys_setfsgid
-	.long sys_llseek	/* 140 */
-	.long sys_getdents
-	.long ppc_select
-	.long sys_flock
-	.long sys_msync
-	.long sys_readv		/* 145 */
-	.long sys_writev
-	.long sys_getsid
-	.long sys_fdatasync
-	.long sys_sysctl
-	.long sys_mlock		/* 150 */
-	.long sys_munlock
-	.long sys_mlockall
-	.long sys_munlockall
-	.long sys_sched_setparam
-	.long sys_sched_getparam	/* 155 */
-	.long sys_sched_setscheduler
-	.long sys_sched_getscheduler
-	.long sys_sched_yield
-	.long sys_sched_get_priority_max
-	.long sys_sched_get_priority_min  /* 160 */
-	.long sys_sched_rr_get_interval
-	.long sys_nanosleep
-	.long sys_mremap
-	.long sys_setresuid
-	.long sys_getresuid	/* 165 */
-	.long sys_ni_syscall		/* old sys_query_module */
-	.long sys_poll
-	.long sys_nfsservctl
-	.long sys_setresgid
-	.long sys_getresgid	/* 170 */
-	.long sys_prctl
-	.long sys_rt_sigreturn
-	.long sys_rt_sigaction
-	.long sys_rt_sigprocmask
-	.long sys_rt_sigpending	/* 175 */
-	.long sys_rt_sigtimedwait
-	.long sys_rt_sigqueueinfo
-	.long sys_rt_sigsuspend
-	.long sys_pread64
-	.long sys_pwrite64	/* 180 */
-	.long sys_chown
-	.long sys_getcwd
-	.long sys_capget
-	.long sys_capset
-	.long sys_sigaltstack	/* 185 */
-	.long sys_sendfile
-	.long sys_ni_syscall		/* streams1 */
-	.long sys_ni_syscall		/* streams2 */
-	.long ppc_vfork
-	.long sys_getrlimit	/* 190 */
-	.long sys_readahead
-	.long sys_mmap2
-	.long sys_truncate64
-	.long sys_ftruncate64
-	.long sys_stat64	/* 195 */
-	.long sys_lstat64
-	.long sys_fstat64
-	.long sys_pciconfig_read
-	.long sys_pciconfig_write
-	.long sys_pciconfig_iobase 	/* 200 */
-	.long sys_ni_syscall		/* 201 - reserved - MacOnLinux - new */
-	.long sys_getdents64
-	.long sys_pivot_root
-	.long sys_fcntl64
-	.long sys_madvise	/* 205 */
-	.long sys_mincore
-	.long sys_gettid
-	.long sys_tkill
-	.long sys_setxattr
-	.long sys_lsetxattr	/* 210 */
-	.long sys_fsetxattr
-	.long sys_getxattr
-	.long sys_lgetxattr
-	.long sys_fgetxattr
-	.long sys_listxattr	/* 215 */
-	.long sys_llistxattr
-	.long sys_flistxattr
-	.long sys_removexattr
-	.long sys_lremovexattr
-	.long sys_fremovexattr	/* 220 */
-	.long sys_futex
-	.long sys_sched_setaffinity
-	.long sys_sched_getaffinity
-	.long sys_ni_syscall
-	.long sys_ni_syscall	/* 225 - reserved for Tux */
-	.long sys_sendfile64
-	.long sys_io_setup
-	.long sys_io_destroy
-	.long sys_io_getevents
-	.long sys_io_submit	/* 230 */
-	.long sys_io_cancel
-	.long sys_set_tid_address
-	.long sys_fadvise64
-	.long sys_exit_group
-	.long sys_lookup_dcookie /* 235 */
-	.long sys_epoll_create
-	.long sys_epoll_ctl
-	.long sys_epoll_wait
-	.long sys_remap_file_pages
-	.long sys_timer_create	/* 240 */
-	.long sys_timer_settime
-	.long sys_timer_gettime
-	.long sys_timer_getoverrun
-	.long sys_timer_delete
-	.long sys_clock_settime	/* 245 */
-	.long sys_clock_gettime
-	.long sys_clock_getres
-	.long sys_clock_nanosleep
-	.long sys_swapcontext
-	.long sys_tgkill	/* 250 */
-	.long sys_utimes
-	.long sys_statfs64
-	.long sys_fstatfs64
-	.long ppc_fadvise64_64
-	.long sys_ni_syscall		/* 255 - rtas (used on ppc64) */
-	.long sys_debug_setcontext
-	.long sys_ni_syscall		/* 257 reserved for vserver */
-	.long sys_ni_syscall		/* 258 reserved for new sys_remap_file_pages */
-	.long sys_ni_syscall		/* 259 reserved for new sys_mbind */
-	.long sys_ni_syscall		/* 260 reserved for new sys_get_mempolicy */
-	.long sys_ni_syscall		/* 261 reserved for new sys_set_mempolicy */
-	.long sys_mq_open
-	.long sys_mq_unlink
-	.long sys_mq_timedsend
-	.long sys_mq_timedreceive	/* 265 */
-	.long sys_mq_notify
-	.long sys_mq_getsetattr
-	.long sys_kexec_load
-	.long sys_add_key
-	.long sys_request_key		/* 270 */
-	.long sys_keyctl
-	.long sys_waitid
-	.long sys_ioprio_set
-	.long sys_ioprio_get
-	.long sys_inotify_init		/* 275 */
-	.long sys_inotify_add_watch
-	.long sys_inotify_rm_watch
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 3a6e4bc..15bd9b4 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -186,11 +186,15 @@
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(_tlbie);
 #ifdef CONFIG_ALTIVEC
+#ifndef CONFIG_SMP
 EXPORT_SYMBOL(last_task_used_altivec);
+#endif
 EXPORT_SYMBOL(giveup_altivec);
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_SPE
+#ifndef CONFIG_SMP
 EXPORT_SYMBOL(last_task_used_spe);
+#endif
 EXPORT_SYMBOL(giveup_spe);
 #endif /* CONFIG_SPE */
 #ifdef CONFIG_SMP
diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c
index 159b228..0ec53f0 100644
--- a/arch/ppc/platforms/4xx/bamboo.c
+++ b/arch/ppc/platforms/4xx/bamboo.c
@@ -332,8 +332,8 @@
 	port.irq = 0;
 	port.uartclk = clocks.uart0;
 	port.regshift = 0;
-	port.iotype = SERIAL_IO_MEM;
-	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	port.line = 0;
 
 	if (early_serial_setup(&port) != 0) {
diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c
index 8110f55..ce48a4f 100644
--- a/arch/ppc/platforms/4xx/bubinga.c
+++ b/arch/ppc/platforms/4xx/bubinga.c
@@ -97,8 +97,8 @@
 	port.irq = ACTING_UART0_INT;
 	port.uartclk = uart_clock;
 	port.regshift = 0;
-	port.iotype = SERIAL_IO_MEM;
-	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	port.line = 0;
 
 	if (early_serial_setup(&port) != 0) {
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
index 64ebae1..9a828b6 100644
--- a/arch/ppc/platforms/4xx/ebony.c
+++ b/arch/ppc/platforms/4xx/ebony.c
@@ -225,8 +225,8 @@
 	port.irq = 0;
 	port.uartclk = clocks.uart0;
 	port.regshift = 0;
-	port.iotype = SERIAL_IO_MEM;
-	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	port.line = 0;
 
 	if (early_serial_setup(&port) != 0) {
diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c
index d810b73..21d2913 100644
--- a/arch/ppc/platforms/4xx/luan.c
+++ b/arch/ppc/platforms/4xx/luan.c
@@ -279,8 +279,8 @@
 	port.irq = UART0_INT;
 	port.uartclk = clocks.uart0;
 	port.regshift = 0;
-	port.iotype = SERIAL_IO_MEM;
-	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	port.line = 0;
 
 	if (early_serial_setup(&port) != 0) {
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index 73b2c98..4f355b6 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -248,8 +248,8 @@
 	port.irq = UART0_INT;
 	port.uartclk = clocks.uart0;
 	port.regshift = 0;
-	port.iotype = SERIAL_IO_MEM;
-	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	port.line = 0;
 
 	if (early_serial_setup(&port) != 0) {
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c
index 0b1b77d..e90d97f 100644
--- a/arch/ppc/platforms/4xx/xilinx_ml300.c
+++ b/arch/ppc/platforms/4xx/xilinx_ml300.c
@@ -95,8 +95,8 @@
 		port.irq = old_ports[i].irq;
 		port.uartclk = old_ports[i].baud_base * 16;
 		port.regshift = old_ports[i].iomem_reg_shift;
-		port.iotype = SERIAL_IO_MEM;
-		port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+		port.iotype = UPIO_MEM;
+		port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 		port.line = i;
 
 		if (early_serial_setup(&port) != 0) {
diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c
index e60f4bd..b065b8b 100644
--- a/arch/ppc/platforms/4xx/yucca.c
+++ b/arch/ppc/platforms/4xx/yucca.c
@@ -305,8 +305,8 @@
 	port.irq = UART0_INT;
 	port.uartclk = clocks.uart0;
 	port.regshift = 0;
-	port.iotype = SERIAL_IO_MEM;
-	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	port.line = 0;
 
 	if (early_serial_setup(&port) != 0) {
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
index 012e1e6..1a659bb 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -301,14 +301,14 @@
 		struct uart_port p;
 
 		memset(&p, 0, sizeof (p));
-		p.iotype = SERIAL_IO_MEM;
+		p.iotype = UPIO_MEM;
 		p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4500);
 		p.uartclk = binfo->bi_busfreq;
 
 		gen550_init(0, &p);
 
 		memset(&p, 0, sizeof (p));
-		p.iotype = SERIAL_IO_MEM;
+		p.iotype = UPIO_MEM;
 		p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4600);
 		p.uartclk = binfo->bi_busfreq;
 
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index 2eceb1e..408d64f 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -162,14 +162,14 @@
 			  binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
 		memset(&p, 0, sizeof (p));
-		p.iotype = SERIAL_IO_MEM;
+		p.iotype = UPIO_MEM;
 		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
 		p.uartclk = binfo->bi_busfreq;
 
 		gen550_init(0, &p);
 
 		memset(&p, 0, sizeof (p));
-		p.iotype = SERIAL_IO_MEM;
+		p.iotype = UPIO_MEM;
 		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
 		p.uartclk = binfo->bi_busfreq;
 
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index b332eba..1801ab3 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -534,14 +534,14 @@
 				binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
 		memset(&p, 0, sizeof (p));
-		p.iotype = SERIAL_IO_MEM;
+		p.iotype = UPIO_MEM;
 		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
 		p.uartclk = binfo->bi_busfreq;
 
 		gen550_init(0, &p);
 
 		memset(&p, 0, sizeof (p));
-		p.iotype = SERIAL_IO_MEM;
+		p.iotype = UPIO_MEM;
 		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
 		p.uartclk = binfo->bi_busfreq;
 
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index e777ba8..8a72221 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -64,7 +64,7 @@
 	uart_req.irq = MPC85xx_IRQ_EXT9;
 	uart_req.flags = STD_COM_FLAGS;
 	uart_req.uartclk = BASE_BAUD * 16;
-        uart_req.iotype = SERIAL_IO_MEM;
+        uart_req.iotype = UPIO_MEM;
         uart_req.mapbase = UARTA_ADDR;
         uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE);
 	uart_req.type = PORT_16650;
diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c
index b436f4d..a5e38ba 100644
--- a/arch/ppc/platforms/85xx/tqm85xx.c
+++ b/arch/ppc/platforms/85xx/tqm85xx.c
@@ -346,14 +346,14 @@
 			  binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
 		memset(&p, 0, sizeof (p));
-		p.iotype = SERIAL_IO_MEM;
+		p.iotype = UPIO_MEM;
 		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
 		p.uartclk = binfo->bi_busfreq;
 
 		gen550_init(0, &p);
 
 		memset(&p, 0, sizeof (p));
-		p.iotype = SERIAL_IO_MEM;
+		p.iotype = UPIO_MEM;
 		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
 		p.uartclk = binfo->bi_busfreq;
 
diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c
index 48a4a51..aefcc0e 100644
--- a/arch/ppc/platforms/chestnut.c
+++ b/arch/ppc/platforms/chestnut.c
@@ -116,7 +116,7 @@
 	port.uartclk = BASE_BAUD * 16;
 	port.irq = UART0_INT;
 	port.flags = STD_COM_FLAGS | UPF_IOREMAP;
-	port.iotype = SERIAL_IO_MEM;
+	port.iotype = UPIO_MEM;
 	port.mapbase = CHESTNUT_UART0_IO_BASE;
 	port.regshift = 0;
 
diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c
index 32358b3..ffde8f6 100644
--- a/arch/ppc/platforms/ev64260.c
+++ b/arch/ppc/platforms/ev64260.c
@@ -330,7 +330,7 @@
 		port.irq = EV64260_UART_0_IRQ;
 		port.uartclk = BASE_BAUD * 16;
 		port.regshift = 2;
-		port.iotype = SERIAL_IO_MEM;
+		port.iotype = UPIO_MEM;
 		port.flags = STD_COM_FLAGS;
 
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
index 708b873..872c0a3 100644
--- a/arch/ppc/platforms/radstone_ppc7d.c
+++ b/arch/ppc/platforms/radstone_ppc7d.c
@@ -100,7 +100,7 @@
 	serial_req.uartclk = UART_CLK;
 	serial_req.irq = 4;
 	serial_req.flags = STD_COM_FLAGS;
-	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.iotype = UPIO_MEM;
 	serial_req.membase = (u_char *) PPC7D_SERIAL_0;
 
 	gen550_init(0, &serial_req);
diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c
index 5ad70d3..69e1de7 100644
--- a/arch/ppc/platforms/spruce.c
+++ b/arch/ppc/platforms/spruce.c
@@ -176,8 +176,8 @@
 	memset(&serial_req, 0, sizeof(serial_req));
 	serial_req.uartclk = uart_clk;
 	serial_req.irq = UART0_INT;
-	serial_req.flags = ASYNC_BOOT_AUTOCONF;
-	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.flags = UPF_BOOT_AUTOCONF;
+	serial_req.iotype = UPIO_MEM;
 	serial_req.membase = (u_char *)UART0_IO_BASE;
 	serial_req.regshift = 0;
 
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
index 94ea346..1f01b7e 100644
--- a/arch/ppc/syslib/mv64x60.c
+++ b/arch/ppc/syslib/mv64x60.c
@@ -313,7 +313,7 @@
 };
 #endif
 
-#ifdef CONFIG_MV643XX_ETH
+#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
 static struct resource mv64x60_eth_shared_resources[] = {
 	[0] = {
 		.name	= "ethernet shared base",
@@ -456,7 +456,7 @@
 	&mpsc0_device,
 	&mpsc1_device,
 #endif
-#ifdef CONFIG_MV643XX_ETH
+#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
 	&mv64x60_eth_shared_device,
 #endif
 #ifdef CONFIG_MV643XX_ETH_0
diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
index ab34b1d..2fe28de 100644
--- a/arch/ppc/syslib/ocp.c
+++ b/arch/ppc/syslib/ocp.c
@@ -189,8 +189,8 @@
 struct bus_type ocp_bus_type = {
 	.name = "ocp",
 	.match = ocp_device_match,
-	.probe = ocp_driver_probe,
-	.remove = ocp_driver_remove,
+	.probe = ocp_device_probe,
+	.remove = ocp_device_remove,
 	.suspend = ocp_device_suspend,
 	.resume = ocp_device_resume,
 };
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
index 1b5fe9e..7bada82 100644
--- a/arch/ppc/syslib/ppc83xx_setup.c
+++ b/arch/ppc/syslib/ppc83xx_setup.c
@@ -108,7 +108,7 @@
 
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
 	memset(&serial_req, 0, sizeof (serial_req));
-	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.iotype = UPIO_MEM;
 	serial_req.mapbase = pdata[0].mapbase;
 	serial_req.membase = pdata[0].membase;
 	serial_req.regshift = 0;
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
index 1a47ff4..e4dda43 100644
--- a/arch/ppc/syslib/ppc85xx_setup.c
+++ b/arch/ppc/syslib/ppc85xx_setup.c
@@ -90,7 +90,7 @@
 
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
 	memset(&serial_req, 0, sizeof (serial_req));
-	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.iotype = UPIO_MEM;
 	serial_req.mapbase = pdata[0].mapbase;
 	serial_req.membase = pdata[0].membase;
 	serial_req.regshift = 0;
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 7d23edc..f8d0cd5 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,19 +1,17 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-rc2
-# Mon Nov 21 13:51:30 2005
+# Linux kernel version: 2.6.16-rc2
+# Wed Feb  8 10:44:39 2006
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_S390=y
-CONFIG_UID16=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -29,18 +27,20 @@
 CONFIG_SYSCTL=y
 CONFIG_AUDIT=y
 # CONFIG_AUDITSYSCALL is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -49,8 +49,10 @@
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -76,11 +78,11 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_DEFAULT_IOSCHED="deadline"
 
 #
 # Base setup
@@ -151,6 +153,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -193,6 +196,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -362,6 +370,7 @@
 #
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=2048
+# CONFIG_HANGCHECK_TIMER is not set
 
 #
 # Watchdog Cards
@@ -488,6 +497,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -520,6 +530,7 @@
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -584,6 +595,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
@@ -592,27 +604,30 @@
 # CONFIG_NLS is not set
 
 #
-# Profiling support
+# Instrumentation Support
 #
 # CONFIG_PROFILING is not set
+# CONFIG_STATISTICS is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
-CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 
 #
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index bf9a7a3..2d02162 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -100,12 +100,12 @@
 #define SET_STAT_UID(stat, uid)		(stat).st_uid = high2lowuid(uid)
 #define SET_STAT_GID(stat, gid)		(stat).st_gid = high2lowgid(gid)
 
-asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
+asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
 {
 	return sys_chown(filename, low2highuid(user), low2highgid(group));
 }
 
-asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
+asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group)
 {
 	return sys_lchown(filename, low2highuid(user), low2highgid(group));
 }
@@ -141,7 +141,7 @@
 		low2highuid(suid));
 }
 
-asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
+asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid)
 {
 	int retval;
 
@@ -158,7 +158,7 @@
 		low2highgid(sgid));
 }
 
-asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
+asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
 {
 	int retval;
 
@@ -179,7 +179,7 @@
 	return sys_setfsgid((gid_t)gid);
 }
 
-static int groups16_to_user(u16 *grouplist, struct group_info *group_info)
+static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info)
 {
 	int i;
 	u16 group;
@@ -193,7 +193,7 @@
 	return 0;
 }
 
-static int groups16_from_user(struct group_info *group_info, u16 *grouplist)
+static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist)
 {
 	int i;
 	u16 group;
@@ -207,7 +207,7 @@
 	return 0;
 }
 
-asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
+asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
 {
 	int i;
 
@@ -231,7 +231,7 @@
 	return i;
 }
 
-asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
+asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
 {
 	struct group_info *group_info;
 	int retval;
@@ -278,14 +278,14 @@
 
 /* 32-bit timeval and related flotsam.  */
 
-static inline long get_tv32(struct timeval *o, struct compat_timeval *i)
+static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
 {
 	return (!access_ok(VERIFY_READ, o, sizeof(*o)) ||
 		(__get_user(o->tv_sec, &i->tv_sec) ||
 		 __get_user(o->tv_usec, &i->tv_usec)));
 }
 
-static inline long put_tv32(struct compat_timeval *o, struct timeval *i)
+static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
 {
 	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 		(__put_user(i->tv_sec, &o->tv_sec) ||
@@ -341,7 +341,7 @@
 	return -ENOSYS;
 }
 
-asmlinkage long sys32_truncate64(const char * path, unsigned long high, unsigned long low)
+asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
 {
 	if ((int)high < 0)
 		return -EINVAL;
@@ -357,7 +357,7 @@
 		return sys_ftruncate(fd, (high << 32) | low);
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
+int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
 {
 	int err;
 
@@ -591,7 +591,7 @@
 
 extern struct timezone sys_tz;
 
-asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
+asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
 {
 	if (tv) {
 		struct timeval ktv;
@@ -606,7 +606,7 @@
 	return 0;
 }
 
-static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
+static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
 {
 	long usec;
 
@@ -620,7 +620,7 @@
 	return 0;
 }
 
-asmlinkage long sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
+asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
 {
 	struct timespec kts;
 	struct timezone ktz;
@@ -645,7 +645,7 @@
 	return -ERESTARTNOHAND;
 }
 
-asmlinkage long sys32_pread64(unsigned int fd, char *ubuf,
+asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
 				size_t count, u32 poshi, u32 poslo)
 {
 	if ((compat_ssize_t) count < 0)
@@ -653,7 +653,7 @@
 	return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
-asmlinkage long sys32_pwrite64(unsigned int fd, const char *ubuf,
+asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
 				size_t count, u32 poshi, u32 poslo)
 {
 	if ((compat_ssize_t) count < 0)
@@ -666,7 +666,7 @@
 	return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
 }
 
-asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size_t count)
+asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, size_t count)
 {
 	mm_segment_t old_fs = get_fs();
 	int ret;
@@ -686,7 +686,7 @@
 }
 
 asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
-				compat_loff_t *offset, s32 count)
+				compat_loff_t __user *offset, s32 count)
 {
 	mm_segment_t old_fs = get_fs();
 	int ret;
@@ -722,7 +722,7 @@
 
 extern int do_adjtimex(struct timex *);
 
-asmlinkage long sys32_adjtimex(struct timex32 *utp)
+asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
 {
 	struct timex txc;
 	int ret;
@@ -789,12 +789,13 @@
 	u32 __unused[4];
 };
 
-asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
+asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 {
 	struct __sysctl_args32 tmp;
 	int error;
-	size_t oldlen, *oldlenp = NULL;
-	unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
+	size_t oldlen;
+	size_t __user *oldlenp = NULL;
+	unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
 
 	if (copy_from_user(&tmp, args, sizeof(tmp)))
 		return -EFAULT;
@@ -806,20 +807,20 @@
 		   basically copy the whole sysctl.c here, and
 		   glibc's __sysctl uses rw memory for the structure
 		   anyway.  */
-		if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
-		    put_user(oldlen, (size_t *)addr))
+		if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) ||
+		    put_user(oldlen, (size_t __user *)addr))
 			return -EFAULT;
-		oldlenp = (size_t *)addr;
+		oldlenp = (size_t __user *)addr;
 	}
 
 	lock_kernel();
-	error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
-			  oldlenp, (void *)A(tmp.newval), tmp.newlen);
+	error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval),
+			  oldlenp, compat_ptr(tmp.newval), tmp.newlen);
 	unlock_kernel();
 	if (oldlenp) {
 		if (!error) {
-			if (get_user(oldlen, (size_t *)addr) ||
-			    put_user(oldlen, (u32 *)A(tmp.oldlenp)))
+			if (get_user(oldlen, (size_t __user *)addr) ||
+			    put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)))
 				error = -EFAULT;
 		}
 		copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
@@ -853,7 +854,7 @@
 	unsigned long   st_ino;
 };	
 
-static int cp_stat64(struct stat64_emu31 *ubuf, struct kstat *stat)
+static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat)
 {
 	struct stat64_emu31 tmp;
 
@@ -877,7 +878,7 @@
 	return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 
 }
 
-asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf)
+asmlinkage long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf)
 {
 	struct kstat stat;
 	int ret = vfs_stat(filename, &stat);
@@ -886,7 +887,7 @@
 	return ret;
 }
 
-asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf)
+asmlinkage long sys32_lstat64(char __user * filename, struct stat64_emu31 __user * statbuf)
 {
 	struct kstat stat;
 	int ret = vfs_lstat(filename, &stat);
@@ -895,7 +896,7 @@
 	return ret;
 }
 
-asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf)
+asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf)
 {
 	struct kstat stat;
 	int ret = vfs_fstat(fd, &stat);
@@ -904,6 +905,26 @@
 	return ret;
 }
 
+asmlinkage long sys32_fstatat(unsigned int dfd, char __user *filename,
+			      struct stat64_emu31 __user* statbuf, int flag)
+{
+	struct kstat stat;
+	int error = -EINVAL;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat_fd(dfd, filename, &stat);
+	else
+		error = vfs_stat_fd(dfd, filename, &stat);
+
+	if (!error)
+		error = cp_stat64(statbuf, &stat);
+out:
+	return error;
+}
+
 /*
  * Linux/i386 didn't use to be able to handle more than
  * 4 system call parameters, so these system calls used a memory
@@ -952,7 +973,7 @@
 
 
 asmlinkage unsigned long
-old32_mmap(struct mmap_arg_struct_emu31 *arg)
+old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
 {
 	struct mmap_arg_struct_emu31 a;
 	int error = -EFAULT;
@@ -970,7 +991,7 @@
 }
 
 asmlinkage long 
-sys32_mmap2(struct mmap_arg_struct_emu31 *arg)
+sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
 {
 	struct mmap_arg_struct_emu31 a;
 	int error = -EFAULT;
@@ -982,7 +1003,7 @@
 	return error;
 }
 
-asmlinkage long sys32_read(unsigned int fd, char * buf, size_t count)
+asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)
 {
 	if ((compat_ssize_t) count < 0)
 		return -EINVAL; 
@@ -990,7 +1011,7 @@
 	return sys_read(fd, buf, count);
 }
 
-asmlinkage long sys32_write(unsigned int fd, char * buf, size_t count)
+asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count)
 {
 	if ((compat_ssize_t) count < 0)
 		return -EINVAL; 
@@ -1002,12 +1023,12 @@
 {
         unsigned long clone_flags;
         unsigned long newsp;
-	int *parent_tidptr, *child_tidptr;
+	int __user *parent_tidptr, *child_tidptr;
 
         clone_flags = regs.gprs[3] & 0xffffffffUL;
         newsp = regs.orig_gpr2 & 0x7fffffffUL;
-	parent_tidptr = (int *) (regs.gprs[4] & 0x7fffffffUL);
-	child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL);
+	parent_tidptr = compat_ptr(regs.gprs[4]);
+	child_tidptr = compat_ptr(regs.gprs[5]);
         if (!newsp)
                 newsp = regs.gprs[15];
         return do_fork(clone_flags, newsp, &regs, 0,
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index fa2b3bc..5291b5f 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -1,8 +1,7 @@
 /*
- *  arch/s390/kernel/signal32.c
+ *  arch/s390/kernel/compat_signal.c
  *
- *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 2000,2006
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *               Gerhard Tonn (ton@de.ibm.com)                  
  *
@@ -52,8 +51,6 @@
 	struct ucontext32 uc;
 } rt_sigframe32;
 
-asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
-
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
 	int err;
@@ -161,66 +158,6 @@
 	return err;
 }
 
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys32_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
-{
-	sigset_t saveset;
-
-	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	siginitset(&current->blocked, mask);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	regs->gprs[2] = -EINTR;
-
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule();
-		if (do_signal(regs, &saveset))
-			return -EINTR;
-	}
-}
-
-asmlinkage int
-sys32_rt_sigsuspend(struct pt_regs * regs, compat_sigset_t __user *unewset,
-								size_t sigsetsize)
-{
-	sigset_t saveset, newset;
-	compat_sigset_t set32;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&set32, unewset, sizeof(set32)))
-		return -EFAULT;
-	switch (_NSIG_WORDS) {
-	case 4: newset.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
-	case 3: newset.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
-	case 2: newset.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
-	case 1: newset.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
-	}
-        sigdelsetmask(&newset, ~_BLOCKABLE);
-
-        spin_lock_irq(&current->sighand->siglock);
-        saveset = current->blocked;
-        current->blocked = newset;
-        recalc_sigpending();
-        spin_unlock_irq(&current->sighand->siglock);
-        regs->gprs[2] = -EINTR;
-
-        while (1) {
-                set_current_state(TASK_INTERRUPTIBLE);
-                schedule();
-                if (do_signal(regs, &saveset))
-                        return -EINTR;
-        }
-}
-
 asmlinkage long
 sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
 		 struct old_sigaction32 __user *oact)
@@ -258,9 +195,6 @@
 	return ret;
 }
 
-int
-do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact);
-
 asmlinkage long
 sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
 	   struct sigaction32 __user *oact,  size_t sigsetsize)
@@ -520,7 +454,7 @@
 		return sig;
 }
 
-static void setup_frame32(int sig, struct k_sigaction *ka,
+static int setup_frame32(int sig, struct k_sigaction *ka,
 			sigset_t *set, struct pt_regs * regs)
 {
 	sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
@@ -565,13 +499,14 @@
 	/* Place signal number on stack to allow backtrace from handler.  */
 	if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
 		goto give_sigsegv;
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return -EFAULT;
 }
 
-static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
 			   sigset_t *set, struct pt_regs * regs)
 {
 	int err = 0;
@@ -615,31 +550,37 @@
 	regs->gprs[2] = map_signal(sig);
 	regs->gprs[3] = (__u64) &frame->info;
 	regs->gprs[4] = (__u64) &frame->uc;
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */	
 
-void
+int
 handle_signal32(unsigned long sig, struct k_sigaction *ka,
 		siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
+	int ret;
+
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame32(sig, ka, info, oldset, regs);
+		ret = setup_rt_frame32(sig, ka, info, oldset, regs);
 	else
-		setup_frame32(sig, ka, oldset, regs);
+		ret = setup_frame32(sig, ka, oldset, regs);
 
-	spin_lock_irq(&current->sighand->siglock);
-	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-	if (!(ka->sa.sa_flags & SA_NODEFER))
-		sigaddset(&current->blocked,sig);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	if (ret == 0) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		if (!(ka->sa.sa_flags & SA_NODEFER))
+			sigaddset(&current->blocked,sig);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+	return ret;
 }
 
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index cfde190..dd2d6c3 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1,9 +1,8 @@
 /*
-*  arch/s390/kernel/sys_wrapper31.S
+*  arch/s390/kernel/compat_wrapper.S
 *    wrapper for 31 bit compatible system calls.
 *
-*  S390 version
-*    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+*    Copyright (C) IBM Corp. 2000,2006
 *    Author(s): Gerhard Tonn (ton@de.ibm.com),
 *               Thomas Spatzier (tspat@de.ibm.com)
 */ 
@@ -288,7 +287,12 @@
 	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t 
 	jg	sys32_setregid16	# branch to system call
 
-#sys32_sigsuspend_wrapper		# done in sigsuspend_glue 
+	.globl sys_sigsuspend_wrapper
+sys_sigsuspend_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	llgfr	%r4,%r4			# old_sigset_t
+	jg	sys_sigsuspend
 
 	.globl  compat_sys_sigpending_wrapper 
 compat_sys_sigpending_wrapper:
@@ -855,7 +859,11 @@
 	llgtr	%r4,%r4			# siginfo_emu31_t *
 	jg	sys32_rt_sigqueueinfo	# branch to system call
 
-#sys32_rt_sigsuspend_wrapper		# done in rt_sigsuspend_glue 
+	.globl compat_sys_rt_sigsuspend_wrapper
+compat_sys_rt_sigsuspend_wrapper:
+	llgtr	%r2,%r2			# compat_sigset_t *
+	llgfr	%r3,%r3			# compat_size_t
+	jg	compat_sys_rt_sigsuspend
 
 	.globl  sys32_pread64_wrapper 
 sys32_pread64_wrapper:
@@ -1475,3 +1483,127 @@
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# u32
 	jg	sys_inotify_rm_watch
+
+	.globl compat_sys_openat_wrapper
+compat_sys_openat_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# const char *
+	lgfr	%r4,%r4			# int
+	lgfr	%r5,%r5			# int
+	jg	compat_sys_openat
+
+	.globl sys_mkdirat_wrapper
+sys_mkdirat_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	lgfr	%r4,%r4			# int
+	jg	sys_mkdirat
+
+	.globl sys_mknodat_wrapper
+sys_mknodat_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	lgfr	%r4,%r4			# int
+	llgfr	%r5,%r5			# unsigned int
+	jg	sys_mknodat
+
+	.globl sys_fchownat_wrapper
+sys_fchownat_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	llgfr	%r4,%r4			# uid_t
+	llgfr	%r5,%r5			# gid_t
+	lgfr	%r6,%r6			# int
+	jg	sys_fchownat
+
+	.globl compat_sys_futimesat_wrapper
+compat_sys_futimesat_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# char *
+	llgtr	%r4,%r4			# struct timeval *
+	jg	compat_sys_futimesat
+
+	.globl sys32_fstatat_wrapper
+sys32_fstatat_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# char *
+	llgtr	%r4,%r4			# struct stat64 *
+	lgfr	%r5,%r5			# int
+	jg	sys32_fstatat
+
+	.globl sys_unlinkat_wrapper
+sys_unlinkat_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	lgfr	%r4,%r4			# int
+	jg	sys_unlinkat
+
+	.globl sys_renameat_wrapper
+sys_renameat_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	lgfr	%r4,%r4			# int
+	llgtr	%r5,%r5			# const char *
+	jg	sys_renameat
+
+	.globl sys_linkat_wrapper
+sys_linkat_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	lgfr	%r4,%r4			# int
+	llgtr	%r5,%r5			# const char *
+	jg	sys_linkat
+
+	.globl sys_symlinkat_wrapper
+sys_symlinkat_wrapper:
+	llgtr	%r2,%r2			# const char *
+	lgfr	%r3,%r3			# int
+	llgtr	%r4,%r4			# const char *
+	jg	sys_symlinkat
+
+	.globl sys_readlinkat_wrapper
+sys_readlinkat_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	llgtr	%r4,%r4			# char *
+	lgfr	%r5,%r5			# int
+	jg	sys_readlinkat
+
+	.globl sys_fchmodat_wrapper
+sys_fchmodat_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	llgfr	%r4,%r4			# mode_t
+	jg	sys_fchmodat
+
+	.globl sys_faccessat_wrapper
+sys_faccessat_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	lgfr	%r4,%r4			# int
+	jg	sys_faccessat
+
+	.globl compat_sys_pselect6_wrapper
+compat_sys_pselect6_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# fd_set *
+	llgtr	%r4,%r4			# fd_set *
+	llgtr	%r5,%r5			# fd_set *
+	llgtr	%r6,%r6			# struct timespec *
+	llgt	%r0,164(%r15)		# void *
+	stg	%r0,160(%r15)
+	jg	compat_sys_pselect6
+
+	.globl compat_sys_ppoll_wrapper
+compat_sys_ppoll_wrapper:
+	llgtr	%r2,%r2			# struct pollfd *
+	llgfr	%r3,%r3			# unsigned int
+	llgtr	%r4,%r4			# struct timespec *
+	llgtr	%r5,%r5			# const sigset_t *
+	llgfr	%r6,%r6			# size_t
+	jg	compat_sys_ppoll
+
+	.globl sys_unshare_wrapper
+sys_unshare_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	jg	sys_unshare
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 27b0773..b244848 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -2,8 +2,7 @@
  *  arch/s390/kernel/entry.S
  *    S390 low-level entry points.
  *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Hartmut Penner (hp@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -50,9 +49,10 @@
 SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
 SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
-		 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+		 _TIF_MCCK_PENDING)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -251,8 +251,8 @@
 	bo	BASED(sysc_mcck_pending)
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bo	BASED(sysc_reschedule)
-	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
-	bo	BASED(sysc_sigpending)
+	tm	__TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+	bnz	BASED(sysc_sigpending)
 	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC
 	bo	BASED(sysc_restart)
 	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP
@@ -276,12 +276,11 @@
 	br	%r1			# TIF bit will be cleared by handler
 
 #
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
 sysc_sigpending:     
 	ni	__TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        sr      %r3,%r3                # clear *oldset
         l       %r1,BASED(.Ldo_signal)
 	basr	%r14,%r1               # call do_signal
 	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC
@@ -397,30 +396,6 @@
         l       %r1,BASED(.Lrt_sigreturn)
         br      %r1                   # branch to sys_sigreturn
 
-#
-# sigsuspend and rt_sigsuspend need pt_regs as an additional
-# parameter and they have to skip the store of %r2 into the
-# user register %r2 because the return value was set in 
-# sigsuspend and rt_sigsuspend already and must not be overwritten!
-#
-
-sys_sigsuspend_glue:    
-        lr      %r5,%r4               # move mask back
-        lr      %r4,%r3               # move history1 parameter
-        lr      %r3,%r2               # move history0 parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-        l       %r1,BASED(.Lsigsuspend)
-	la      %r14,4(%r14)          # skip store of return value
-        br      %r1                   # branch to sys_sigsuspend
-
-sys_rt_sigsuspend_glue: 
-        lr      %r4,%r3               # move sigsetsize parameter
-        lr      %r3,%r2               # move unewset parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-        l       %r1,BASED(.Lrt_sigsuspend)
-	la      %r14,4(%r14)          # skip store of return value
-        br      %r1                   # branch to sys_rt_sigsuspend
-
 sys_sigaltstack_glue:
         la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
         l       %r1,BASED(.Lsigaltstack)
@@ -604,15 +579,16 @@
 	lr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
+# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED
+#	        and _TIF_MCCK_PENDING
 #
 io_work_loop:
 	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
 	bo      BASED(io_mcck_pending)
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bo	BASED(io_reschedule)
-	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
-	bo	BASED(io_sigpending)
+	tm	__TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+	bnz	BASED(io_sigpending)
 	b	BASED(io_leave)
 
 #
@@ -636,12 +612,11 @@
 	b	BASED(io_work_loop)
 
 #
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
 io_sigpending:     
         stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        sr      %r3,%r3                # clear *oldset
         l       %r1,BASED(.Ldo_signal)
 	basr    %r14,%r1	       # call do_signal
         stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 369ab44..2ac095b 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -1,9 +1,8 @@
 /*
- *  arch/s390/kernel/entry.S
+ *  arch/s390/kernel/entry64.S
  *    S390 low-level entry points.
  *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Hartmut Penner (hp@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -53,9 +52,10 @@
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
-		 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+		 _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
 
@@ -249,8 +249,8 @@
 	jo	sysc_mcck_pending
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jo	sysc_reschedule
-	tm	__TI_flags+7(%r9),_TIF_SIGPENDING
-	jo	sysc_sigpending
+	tm	__TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+	jnz	sysc_sigpending
 	tm	__TI_flags+7(%r9),_TIF_RESTART_SVC
 	jo	sysc_restart
 	tm	__TI_flags+7(%r9),_TIF_SINGLE_STEP
@@ -272,12 +272,11 @@
 	jg	s390_handle_mcck    # TIF bit will be cleared by handler
 
 #
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
 sysc_sigpending:     
 	ni	__TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
         la      %r2,SP_PTREGS(%r15) # load pt_regs
-        sgr     %r3,%r3           # clear *oldset
 	brasl	%r14,do_signal    # call do_signal
 	tm	__TI_flags+7(%r9),_TIF_RESTART_SVC
 	jo	sysc_restart
@@ -414,52 +413,6 @@
         jg      sys32_rt_sigreturn    # branch to sys32_sigreturn
 #endif
 
-#
-# sigsuspend and rt_sigsuspend need pt_regs as an additional
-# parameter and they have to skip the store of %r2 into the
-# user register %r2 because the return value was set in 
-# sigsuspend and rt_sigsuspend already and must not be overwritten!
-#
-
-sys_sigsuspend_glue:    
-        lgr     %r5,%r4               # move mask back
-        lgr     %r4,%r3               # move history1 parameter
-        lgr     %r3,%r2               # move history0 parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-	la      %r14,6(%r14)          # skip store of return value
-        jg      sys_sigsuspend        # branch to sys_sigsuspend
-
-#ifdef CONFIG_COMPAT
-sys32_sigsuspend_glue:    
-	llgfr	%r4,%r4               # unsigned long			
-        lgr     %r5,%r4               # move mask back
-	lgfr	%r3,%r3               # int			
-        lgr     %r4,%r3               # move history1 parameter
-	lgfr	%r2,%r2               # int			
-        lgr     %r3,%r2               # move history0 parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-	la      %r14,6(%r14)          # skip store of return value
-        jg      sys32_sigsuspend      # branch to sys32_sigsuspend
-#endif
-
-sys_rt_sigsuspend_glue: 
-        lgr     %r4,%r3               # move sigsetsize parameter
-        lgr     %r3,%r2               # move unewset parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-	la      %r14,6(%r14)          # skip store of return value
-        jg      sys_rt_sigsuspend     # branch to sys_rt_sigsuspend
-
-#ifdef CONFIG_COMPAT
-sys32_rt_sigsuspend_glue: 
-	llgfr	%r3,%r3               # size_t			
-        lgr     %r4,%r3               # move sigsetsize parameter
-	llgtr	%r2,%r2               # sigset_emu31_t *
-        lgr     %r3,%r2               # move unewset parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-	la      %r14,6(%r14)          # skip store of return value
-        jg      sys32_rt_sigsuspend   # branch to sys32_rt_sigsuspend
-#endif
-
 sys_sigaltstack_glue:
         la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
         jg      sys_sigaltstack       # branch to sys_sigreturn
@@ -646,15 +599,16 @@
 	lgr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
+# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGPENDING, _TIF_NEED_RESCHED
+#	       and _TIF_MCCK_PENDING
 #
 io_work_loop:
 	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING
 	jo	io_mcck_pending
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jo	io_reschedule
-	tm	__TI_flags+7(%r9),_TIF_SIGPENDING
-	jo	io_sigpending
+	tm	__TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+	jnz	io_sigpending
 	j	io_leave
 
 #
@@ -676,12 +630,11 @@
 	j	io_work_loop
 
 #
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
 io_sigpending:     
 	stosm   __SF_EMPTY(%r15),0x03	# reenable interrupts
 	la      %r2,SP_PTREGS(%r15)	# load pt_regs
-	slgr    %r3,%r3			# clear *oldset
 	brasl	%r14,do_signal		# call do_signal
 	stnsm   __SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
 	j	io_work_loop
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index f0ed5c6..bad81b5 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -12,15 +12,16 @@
  * on the S390 architecture.
  */
 
-#include <asm/cio.h>
-#include <asm/setup.h>
 #include <linux/device.h>
 #include <linux/mm.h>
 #include <linux/kexec.h>
 #include <linux/delay.h>
+#include <asm/cio.h>
+#include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/system.h>
+#include <asm/smp.h>
 
 static void kexec_halt_all_cpus(void *);
 
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 6ae4a77..ae1927e 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -1,8 +1,7 @@
 /*
  *  arch/s390/kernel/signal.c
  *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *
  *    Based on Intel version
@@ -51,60 +50,24 @@
 	struct ucontext uc;
 } rt_sigframe;
 
-int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage int
-sys_sigsuspend(struct pt_regs * regs, int history0, int history1,
-	       old_sigset_t mask)
+sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-	sigset_t saveset;
-
 	mask &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
-	regs->gprs[2] = -EINTR;
 
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule();
-		if (do_signal(regs, &saveset))
-			return -EINTR;
-	}
-}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
 
-asmlinkage long
-sys_rt_sigsuspend(struct pt_regs *regs, sigset_t __user *unewset,
-						size_t sigsetsize)
-{
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	regs->gprs[2] = -EINTR;
-
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule();
-		if (do_signal(regs, &saveset))
-			return -EINTR;
-	}
+	return -ERESTARTNOHAND;
 }
 
 asmlinkage long
@@ -306,8 +269,8 @@
 		return sig;
 }
 
-static void setup_frame(int sig, struct k_sigaction *ka,
-			sigset_t *set, struct pt_regs * regs)
+static int setup_frame(int sig, struct k_sigaction *ka,
+		       sigset_t *set, struct pt_regs * regs)
 {
 	sigframe __user *frame;
 
@@ -355,13 +318,14 @@
 	/* Place signal number on stack to allow backtrace from handler.  */
 	if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
 		goto give_sigsegv;
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return -EFAULT;
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			   sigset_t *set, struct pt_regs * regs)
 {
 	int err = 0;
@@ -409,32 +373,39 @@
 	regs->gprs[2] = map_signal(sig);
 	regs->gprs[3] = (unsigned long) &frame->info;
 	regs->gprs[4] = (unsigned long) &frame->uc;
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */	
 
-static void
+static int
 handle_signal(unsigned long sig, struct k_sigaction *ka,
 	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
+	int ret;
+
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame(sig, ka, info, oldset, regs);
+		ret = setup_rt_frame(sig, ka, info, oldset, regs);
 	else
-		setup_frame(sig, ka, oldset, regs);
+		ret = setup_frame(sig, ka, oldset, regs);
 
-	spin_lock_irq(&current->sighand->siglock);
-	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-	if (!(ka->sa.sa_flags & SA_NODEFER))
-		sigaddset(&current->blocked,sig);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	if (ret == 0) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		if (!(ka->sa.sa_flags & SA_NODEFER))
+			sigaddset(&current->blocked,sig);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+
+	return ret;
 }
 
 /*
@@ -446,12 +417,13 @@
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+void do_signal(struct pt_regs *regs)
 {
 	unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
 	siginfo_t info;
 	int signr;
 	struct k_sigaction ka;
+	sigset_t *oldset;
 
 	/*
 	 * We want the common case to go fast, which
@@ -460,9 +432,11 @@
 	 * if so.
 	 */
 	if (!user_mode(regs))
-		return 1;
+		return;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	/* Are we from a system call? */
@@ -473,12 +447,14 @@
 
 		/* Prepare for system call restart.  We do this here so that a
 		   debugger will see the already changed PSW. */
-		if (retval == -ERESTARTNOHAND ||
-		    retval == -ERESTARTSYS ||
-		    retval == -ERESTARTNOINTR) {
+		switch (retval) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
 			regs->gprs[2] = regs->orig_gpr2;
 			regs->psw.addr = restart_addr;
-		} else if (retval == -ERESTART_RESTARTBLOCK) {
+			break;
+		case -ERESTART_RESTARTBLOCK:
 			regs->gprs[2] = -EINTR;
 		}
 	}
@@ -503,17 +479,38 @@
 		/* Whee!  Actually deliver the signal.  */
 #ifdef CONFIG_COMPAT
 		if (test_thread_flag(TIF_31BIT)) {
-			extern void handle_signal32(unsigned long sig,
-						    struct k_sigaction *ka,
-						    siginfo_t *info,
-						    sigset_t *oldset,
-						    struct pt_regs *regs);
-			handle_signal32(signr, &ka, &info, oldset, regs);
-			return 1;
+			extern int handle_signal32(unsigned long sig,
+						   struct k_sigaction *ka,
+						   siginfo_t *info,
+						   sigset_t *oldset,
+						   struct pt_regs *regs);
+			if (handle_signal32(
+				    signr, &ka, &info, oldset, regs) == 0) {
+				if (test_thread_flag(TIF_RESTORE_SIGMASK))
+					clear_thread_flag(TIF_RESTORE_SIGMASK);
+			}
+			return;
 	        }
 #endif
-		handle_signal(signr, &ka, &info, oldset, regs);
-		return 1;
+		if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+			/*
+			 * A signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag.
+			 */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+		return;
+	}
+
+	/*
+	 * If there's no signal to deliver, we just put the saved sigmask back.
+	 */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 	}
 
 	/* Restart a different system call. */
@@ -522,5 +519,4 @@
 		regs->gprs[2] = __NR_restart_syscall;
 		set_thread_flag(TIF_RESTART_SVC);
 	}
-	return 0;
 }
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index cbfcfd0..0d1ad5d 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -52,7 +52,7 @@
 struct _lowcore *lowcore_ptr[NR_CPUS];
 
 cpumask_t cpu_online_map;
-cpumask_t cpu_possible_map;
+cpumask_t cpu_possible_map = CPU_MASK_ALL;
 
 static struct task_struct *current_set[NR_CPUS];
 
@@ -514,9 +514,6 @@
 		num_cpus++;
 	}
 
-	for (cpu = 1; cpu < max_cpus; cpu++)
-		cpu_set(cpu, cpu_possible_map);
-
 	printk("Detected %d CPU's\n",(int) num_cpus);
 	printk("Boot cpu address %2X\n", boot_cpu_addr);
 }
@@ -810,7 +807,6 @@
 
 	cpu_set(0, cpu_online_map);
 	cpu_set(0, cpu_present_map);
-	cpu_set(0, cpu_possible_map);
 	S390_lowcore.percpu_offset = __per_cpu_offset[0];
 	current_set[0] = current;
 }
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index 6a63553..e351780 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -122,8 +122,8 @@
 #ifndef CONFIG_64BIT
 struct sel_arg_struct {
 	unsigned long n;
-	fd_set *inp, *outp, *exp;
-	struct timeval *tvp;
+	fd_set __user *inp, *outp, *exp;
+	struct timeval __user *tvp;
 };
 
 asmlinkage long old_select(struct sel_arg_struct __user *arg)
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 426d7ca..84921fe 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -80,7 +80,7 @@
 NI_SYSCALL							/* old ssetmask syscall*/
 SYSCALL(sys_setreuid16,sys_ni_syscall,sys32_setreuid16_wrapper)	/* old setreuid16 syscall */
 SYSCALL(sys_setregid16,sys_ni_syscall,sys32_setregid16_wrapper)	/* old setregid16 syscall */
-SYSCALL(sys_sigsuspend_glue,sys_sigsuspend_glue,sys32_sigsuspend_glue)
+SYSCALL(sys_sigsuspend,sys_sigsuspend,sys_sigsuspend_wrapper)
 SYSCALL(sys_sigpending,sys_sigpending,compat_sys_sigpending_wrapper)
 SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
 SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper)	/* 75 */
@@ -187,7 +187,7 @@
 SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper)
 SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,compat_sys_rt_sigtimedwait_wrapper)
 SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper)
-SYSCALL(sys_rt_sigsuspend_glue,sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue)
+SYSCALL(sys_rt_sigsuspend,sys_rt_sigsuspend,compat_sys_rt_sigsuspend_wrapper)
 SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper)		/* 180 */
 SYSCALL(sys_pwrite64,sys_pwrite64,sys32_pwrite64_wrapper)
 SYSCALL(sys_chown16,sys_ni_syscall,sys32_chown16_wrapper)	/* old chown16 syscall */
@@ -293,5 +293,22 @@
 SYSCALL(sys_ioprio_set,sys_ioprio_set,sys_ioprio_set_wrapper)
 SYSCALL(sys_ioprio_get,sys_ioprio_get,sys_ioprio_get_wrapper)
 SYSCALL(sys_inotify_init,sys_inotify_init,sys_inotify_init)
-SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper)
+SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper)	/* 285 */
 SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,sys_inotify_rm_watch_wrapper)
+NI_SYSCALL							/* 287 sys_migrate_pages */
+SYSCALL(sys_openat,sys_openat,compat_sys_openat_wrapper)
+SYSCALL(sys_mkdirat,sys_mkdirat,sys_mkdirat_wrapper)
+SYSCALL(sys_mknodat,sys_mknodat,sys_mknodat_wrapper)	/* 290 */
+SYSCALL(sys_fchownat,sys_fchownat,sys_fchownat_wrapper)
+SYSCALL(sys_futimesat,sys_futimesat,compat_sys_futimesat_wrapper)
+SYSCALL(sys_fstatat64,sys_newfstatat,sys32_fstatat_wrapper)
+SYSCALL(sys_unlinkat,sys_unlinkat,sys_unlinkat_wrapper)
+SYSCALL(sys_renameat,sys_renameat,sys_renameat_wrapper)	/* 295 */
+SYSCALL(sys_linkat,sys_linkat,sys_linkat_wrapper)
+SYSCALL(sys_symlinkat,sys_symlinkat,sys_symlinkat_wrapper)
+SYSCALL(sys_readlinkat,sys_readlinkat,sys_readlinkat_wrapper)
+SYSCALL(sys_fchmodat,sys_fchmodat,sys_fchmodat_wrapper)
+SYSCALL(sys_faccessat,sys_faccessat,sys_faccessat_wrapper)	/* 300 */
+SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6_wrapper)
+SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll_wrapper)
+SYSCALL(sys_unshare,sys_unshare,sys_unshare_wrapper)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 7c0fe15..fea043b 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -61,9 +61,18 @@
  */
 unsigned long long sched_clock(void)
 {
-	return ((get_clock() - jiffies_timer_cc) * 1000) >> 12;
+	return ((get_clock() - jiffies_timer_cc) * 125) >> 9;
 }
 
+/*
+ * Monotonic_clock - returns # of nanoseconds passed since time_init()
+ */
+unsigned long long monotonic_clock(void)
+{
+	return sched_clock();
+}
+EXPORT_SYMBOL(monotonic_clock);
+
 void tod_to_timeval(__u64 todval, struct timespec *xtime)
 {
 	unsigned long long sec;
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 5d21e9e..a46793b 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -486,7 +486,7 @@
 		info.si_signo = signal;
 		info.si_errno = 0;
 		info.si_code = ILL_ILLOPC;
-		info.si_addr = (void *) location;
+		info.si_addr = (void __user *) location;
 		do_trap(interruption_code, signal,
 			"illegal operation", regs, &info);
 	}
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index f20b51ff..e05d087 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -6,4 +6,4 @@
 
 lib-y += delay.o string.o
 lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o)
-lib-$(CONFIG_SMP) += spinlock.o
\ No newline at end of file
+lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 2d5cb13..b075ab4 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -42,8 +42,8 @@
 static long cmm_timeout_pages = 0;
 static long cmm_timeout_seconds = 0;
 
-static struct cmm_page_array *cmm_page_list = 0;
-static struct cmm_page_array *cmm_timed_page_list = 0;
+static struct cmm_page_array *cmm_page_list = NULL;
+static struct cmm_page_array *cmm_timed_page_list = NULL;
 
 static unsigned long cmm_thread_active = 0;
 static struct work_struct cmm_thread_starter;
@@ -259,7 +259,7 @@
 
 static int
 cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
-		  void *buffer, size_t *lenp, loff_t *ppos)
+		  void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	char buf[16], *p;
 	long pages;
@@ -300,7 +300,7 @@
 
 static int
 cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
-		    void *buffer, size_t *lenp, loff_t *ppos)
+		    void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	char buf[64], *p;
 	long pages, seconds;
@@ -419,7 +419,7 @@
 #ifdef CONFIG_CMM_IUCV
 	smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
 #endif
-	INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, 0);
+	INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, NULL);
 	init_waitqueue_head(&cmm_thread_wait);
 	init_timer(&cmm_timer);
 	return 0;
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 01bc7d5..504d56f 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -396,14 +396,8 @@
 
 source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
 
-config SH_PCLK_FREQ_BOOL
-	bool "Set default pclk frequency"
-	default y if !SH_RTC
-	default n
-
 config SH_PCLK_FREQ
 	int "Peripheral clock frequency (in Hz)"
-	depends on SH_PCLK_FREQ_BOOL
 	default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
 	default "60000000" if CPU_SUBTYPE_SH7751
 	default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760
diff --git a/arch/sh/boards/renesas/rts7751r2d/io.c b/arch/sh/boards/renesas/rts7751r2d/io.c
index c46f915..123abbb 100644
--- a/arch/sh/boards/renesas/rts7751r2d/io.c
+++ b/arch/sh/boards/renesas/rts7751r2d/io.c
@@ -216,24 +216,26 @@
 {
 	volatile __u8 *bp;
 	volatile __u16 *p;
+	unsigned char *s = addr;
 
 	if (CHECK_AX88796L_PORT(port)) {
 		p = (volatile unsigned short *)port88796l(port, 0);
-		while (count--) *((unsigned char *) addr)++ = *p & 0xff;
+		while (count--) *s++ = *p & 0xff;
 	} else if (PXSEG(port))
-		while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port;
+		while (count--) *s++ = *(volatile unsigned char *)port;
 	else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
 		bp = (__u8 *)PCI_IOMAP(port);
-		while (count--) *((volatile unsigned char *) addr)++ = *bp;
+		while (count--) *s++ = *bp;
 	} else {
 		p = (volatile unsigned short *)port2adr(port);
-		while (count--) *((unsigned char *) addr)++ = *p & 0xff;
+		while (count--) *s++ = *p & 0xff;
 	}
 }
 
 void rts7751r2d_insw(unsigned long port, void *addr, unsigned long count)
 {
 	volatile __u16 *p;
+	__u16 *s = addr;
 
 	if (CHECK_AX88796L_PORT(port))
 		p = (volatile unsigned short *)port88796l(port, 1);
@@ -243,7 +245,7 @@
 		p = (volatile unsigned short *)PCI_IOMAP(port);
 	else
 		p = (volatile unsigned short *)port2adr(port);
-	while (count--) *((__u16 *) addr)++ = *p;
+	while (count--) *s++ = *p;
 }
 
 void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count)
@@ -252,8 +254,9 @@
 		maybebadio(insl, port);
 	else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
 		volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
+		__u32 *s = addr;
 
-		while (count--) *((__u32 *) addr)++ = *p;
+		while (count--) *s++ = *p;
 	} else
 		maybebadio(insl, port);
 }
@@ -262,24 +265,26 @@
 {
 	volatile __u8 *bp;
 	volatile __u16 *p;
+	const __u8 *s = addr;
 
 	if (CHECK_AX88796L_PORT(port)) {
 		p = (volatile unsigned short *)port88796l(port, 0);
-		while (count--) *p = *((unsigned char *) addr)++;
+		while (count--) *p = *s++;
 	} else if (PXSEG(port))
-		while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++;
+		while (count--) *(volatile unsigned char *)port = *s++;
 	else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
 		bp = (__u8 *)PCI_IOMAP(port);
-		while (count--) *bp = *((volatile unsigned char *) addr)++;
+		while (count--) *bp = *s++;
 	} else {
 		p = (volatile unsigned short *)port2adr(port);
-		while (count--) *p = *((unsigned char *) addr)++;
+		while (count--) *p = *s++;
 	}
 }
 
 void rts7751r2d_outsw(unsigned long port, const void *addr, unsigned long count)
 {
 	volatile __u16 *p;
+	const __u16 *s = addr;
 
 	if (CHECK_AX88796L_PORT(port))
 		p = (volatile unsigned short *)port88796l(port, 1);
@@ -289,7 +294,7 @@
 		p = (volatile unsigned short *)PCI_IOMAP(port);
 	else
 		p = (volatile unsigned short *)port2adr(port);
-	while (count--) *p = *((__u16 *) addr)++;
+	while (count--) *p = *s++;
 }
 
 void rts7751r2d_outsl(unsigned long port, const void *addr, unsigned long count)
@@ -298,8 +303,9 @@
 		maybebadio(outsl, port);
 	else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
 		volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
+		const __u32 *s = addr;
 
-		while (count--) *p = *((__u32 *) addr)++;
+		while (count--) *p = *s++;
 	} else
 		maybebadio(outsl, port);
 }
diff --git a/arch/sh/boards/superh/microdev/io.c b/arch/sh/boards/superh/microdev/io.c
index fe83b2c..1ed7f88 100644
--- a/arch/sh/boards/superh/microdev/io.c
+++ b/arch/sh/boards/superh/microdev/io.c
@@ -16,7 +16,7 @@
 #include <linux/pci.h>
 #include <linux/wait.h>
 #include <asm/io.h>
-#include <asm/mach/io.h>
+#include <asm/microdev.h>
 
 	/*
 	 *	we need to have a 'safe' address to re-direct all I/O requests
@@ -52,8 +52,90 @@
 #define	IO_ISP1161_PHYS		0xa7700000ul	/* Physical address of Philips ISP1161x USB chip */
 #define	IO_SUPERIO_PHYS		0xa7800000ul	/* Physical address of SMSC FDC37C93xAPM SuperIO chip */
 
-#define PORT2ADDR(x) (microdev_isa_port2addr(x))
+/*
+ * map I/O ports to memory-mapped addresses
+ */
+static unsigned long microdev_isa_port2addr(unsigned long offset)
+{
+	unsigned long result;
 
+	if ((offset >= IO_LAN91C111_BASE) &&
+	    (offset <  IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
+			/*
+			 *	SMSC LAN91C111 Ethernet chip
+			 */
+		result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE;
+	} else if ((offset >= IO_SUPERIO_BASE) &&
+		   (offset <  IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) {
+			/*
+			 *	SMSC FDC37C93xAPM SuperIO chip
+			 *
+			 *	Configuration Registers
+			 */
+		result = IO_SUPERIO_PHYS + (offset << 1);
+#if 0
+	} else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG ||
+		   offset == KBD_STATUS_REG) {
+			/*
+			 *	SMSC FDC37C93xAPM SuperIO chip
+			 *
+			 *	PS/2 Keyboard + Mouse (ports 0x60 and 0x64).
+			 */
+	        result = IO_SUPERIO_PHYS + (offset << 1);
+#endif
+	} else if (((offset >= IO_IDE1_BASE) &&
+		    (offset <  IO_IDE1_BASE + IO_IDE_EXTENT)) ||
+		    (offset == IO_IDE1_MISC)) {
+			/*
+			 *	SMSC FDC37C93xAPM SuperIO chip
+			 *
+			 *	IDE #1
+			 */
+	        result = IO_SUPERIO_PHYS + (offset << 1);
+	} else if (((offset >= IO_IDE2_BASE) &&
+		    (offset <  IO_IDE2_BASE + IO_IDE_EXTENT)) ||
+		    (offset == IO_IDE2_MISC)) {
+			/*
+			 *	SMSC FDC37C93xAPM SuperIO chip
+			 *
+			 *	IDE #2
+			 */
+	        result = IO_SUPERIO_PHYS + (offset << 1);
+	} else if ((offset >= IO_SERIAL1_BASE) &&
+		   (offset <  IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) {
+			/*
+			 *	SMSC FDC37C93xAPM SuperIO chip
+			 *
+			 *	Serial #1
+			 */
+		result = IO_SUPERIO_PHYS + (offset << 1);
+	} else if ((offset >= IO_SERIAL2_BASE) &&
+		   (offset <  IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) {
+			/*
+			 *	SMSC FDC37C93xAPM SuperIO chip
+			 *
+			 *	Serial #2
+			 */
+		result = IO_SUPERIO_PHYS + (offset << 1);
+	} else if ((offset >= IO_ISP1161_BASE) &&
+		   (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) {
+			/*
+			 *	Philips USB ISP1161x chip
+			 */
+		result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE;
+	} else {
+			/*
+			 *	safe default.
+			 */
+		printk("Warning: unexpected port in %s( offset = 0x%lx )\n",
+		       __FUNCTION__, offset);
+		result = PVR;
+	}
+
+	return result;
+}
+
+#define PORT2ADDR(x) (microdev_isa_port2addr(x))
 
 static inline void delay(void)
 {
@@ -94,6 +176,17 @@
 	return *(volatile unsigned int*)PORT2ADDR(port);
 }
 
+void microdev_outw(unsigned short b, unsigned long port)
+{
+#ifdef CONFIG_PCI
+	if (port >= PCIBIOS_MIN_IO) {
+		microdev_pci_outw(b, port);
+		return;
+	}
+#endif
+	*(volatile unsigned short*)PORT2ADDR(port) = b;
+}
+
 void microdev_outb(unsigned char b, unsigned long port)
 {
 #ifdef CONFIG_PCI
@@ -158,17 +251,6 @@
 	}
 }
 
-void microdev_outw(unsigned short b, unsigned long port)
-{
-#ifdef CONFIG_PCI
-	if (port >= PCIBIOS_MIN_IO) {
-		microdev_pci_outw(b, port);
-		return;
-	}
-#endif
-	*(volatile unsigned short*)PORT2ADDR(port) = b;
-}
-
 void microdev_outl(unsigned int b, unsigned long port)
 {
 #ifdef CONFIG_PCI
@@ -284,87 +366,3 @@
 	while (count--)
 		*port_addr = *buf++;
 }
-
-/*
- * map I/O ports to memory-mapped addresses
- */
-unsigned long microdev_isa_port2addr(unsigned long offset)
-{
-	unsigned long result;
-
-	if ((offset >= IO_LAN91C111_BASE) &&
-	    (offset <  IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
-			/*
-			 *	SMSC LAN91C111 Ethernet chip
-			 */
-		result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE;
-	} else if ((offset >= IO_SUPERIO_BASE) &&
-		   (offset <  IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) {
-			/*
-			 *	SMSC FDC37C93xAPM SuperIO chip
-			 *
-			 *	Configuration Registers
-			 */
-		result = IO_SUPERIO_PHYS + (offset << 1);
-#if 0
-	} else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG ||
-		   offset == KBD_STATUS_REG) {
-			/*
-			 *	SMSC FDC37C93xAPM SuperIO chip
-			 *
-			 *	PS/2 Keyboard + Mouse (ports 0x60 and 0x64).
-			 */
-	        result = IO_SUPERIO_PHYS + (offset << 1);
-#endif
-	} else if (((offset >= IO_IDE1_BASE) &&
-		    (offset <  IO_IDE1_BASE + IO_IDE_EXTENT)) ||
-		    (offset == IO_IDE1_MISC)) {
-			/*
-			 *	SMSC FDC37C93xAPM SuperIO chip
-			 *
-			 *	IDE #1
-			 */
-	        result = IO_SUPERIO_PHYS + (offset << 1);
-	} else if (((offset >= IO_IDE2_BASE) &&
-		    (offset <  IO_IDE2_BASE + IO_IDE_EXTENT)) ||
-		    (offset == IO_IDE2_MISC)) {
-			/*
-			 *	SMSC FDC37C93xAPM SuperIO chip
-			 *
-			 *	IDE #2
-			 */
-	        result = IO_SUPERIO_PHYS + (offset << 1);
-	} else if ((offset >= IO_SERIAL1_BASE) &&
-		   (offset <  IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) {
-			/*
-			 *	SMSC FDC37C93xAPM SuperIO chip
-			 *
-			 *	Serial #1
-			 */
-		result = IO_SUPERIO_PHYS + (offset << 1);
-	} else if ((offset >= IO_SERIAL2_BASE) &&
-		   (offset <  IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) {
-			/*
-			 *	SMSC FDC37C93xAPM SuperIO chip
-			 *
-			 *	Serial #2
-			 */
-		result = IO_SUPERIO_PHYS + (offset << 1);
-	} else if ((offset >= IO_ISP1161_BASE) &&
-		   (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) {
-			/*
-			 *	Philips USB ISP1161x chip
-			 */
-		result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE;
-	} else {
-			/*
-			 *	safe default.
-			 */
-		printk("Warning: unexpected port in %s( offset = 0x%lx )\n",
-		       __FUNCTION__, offset);
-		result = PVR;
-	}
-
-	return result;
-}
-
diff --git a/arch/sh/boards/superh/microdev/irq.c b/arch/sh/boards/superh/microdev/irq.c
index 1395c1e..efcbd86 100644
--- a/arch/sh/boards/superh/microdev/irq.c
+++ b/arch/sh/boards/superh/microdev/irq.c
@@ -15,7 +15,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/mach/irq.h>
+#include <asm/microdev.h>
 
 #define NUM_EXTERNAL_IRQS 16	/* IRL0 .. IRL15 */
 
diff --git a/arch/sh/boards/superh/microdev/setup.c b/arch/sh/boards/superh/microdev/setup.c
index 1c1d65f..892b14d 100644
--- a/arch/sh/boards/superh/microdev/setup.c
+++ b/arch/sh/boards/superh/microdev/setup.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
  * Copyright (C) 2003, 2004 SuperH, Inc.
- * Copyright (C) 2004 Paul Mundt
+ * Copyright (C) 2004, 2005 Paul Mundt
  *
  * SuperH SH4-202 MicroDev board support.
  *
@@ -15,11 +15,10 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/ioport.h>
+#include <video/s1d13xxxfb.h>
+#include <asm/microdev.h>
 #include <asm/io.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/io.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
 
 extern void microdev_heartbeat(void);
 
@@ -51,8 +50,6 @@
 	.mv_outsw		= microdev_outsw,
 	.mv_outsl		= microdev_outsl,
 
-	.mv_isa_port2addr	= microdev_isa_port2addr,
-
 	.mv_init_irq		= init_microdev_irq,
 
 #ifdef CONFIG_HEARTBEAT
@@ -142,16 +139,161 @@
 	.resource	= smc91x_resources,
 };
 
-static int __init smc91x_setup(void)
+#ifdef CONFIG_FB_S1D13XXX
+static struct s1d13xxxfb_regval s1d13806_initregs[] = {
+	{ S1DREG_MISC,			0x00 },
+	{ S1DREG_COM_DISP_MODE,		0x00 },
+	{ S1DREG_GPIO_CNF0,		0x00 },
+	{ S1DREG_GPIO_CNF1,		0x00 },
+	{ S1DREG_GPIO_CTL0,		0x00 },
+	{ S1DREG_GPIO_CTL1,		0x00 },
+	{ S1DREG_CLK_CNF,		0x02 },
+	{ S1DREG_LCD_CLK_CNF,		0x01 },
+	{ S1DREG_CRT_CLK_CNF,		0x03 },
+	{ S1DREG_MPLUG_CLK_CNF,		0x03 },
+	{ S1DREG_CPU2MEM_WST_SEL,	0x02 },
+	{ S1DREG_SDRAM_REF_RATE,	0x03 },
+	{ S1DREG_SDRAM_TC0,		0x00 },
+	{ S1DREG_SDRAM_TC1,		0x01 },
+	{ S1DREG_MEM_CNF,		0x80 },
+	{ S1DREG_PANEL_TYPE,		0x25 },
+	{ S1DREG_MOD_RATE,		0x00 },
+	{ S1DREG_LCD_DISP_HWIDTH,	0x63 },
+	{ S1DREG_LCD_NDISP_HPER,	0x1e },
+	{ S1DREG_TFT_FPLINE_START,	0x06 },
+	{ S1DREG_TFT_FPLINE_PWIDTH,	0x03 },
+	{ S1DREG_LCD_DISP_VHEIGHT0,	0x57 },
+	{ S1DREG_LCD_DISP_VHEIGHT1,	0x02 },
+	{ S1DREG_LCD_NDISP_VPER,	0x00 },
+	{ S1DREG_TFT_FPFRAME_START,	0x0a },
+	{ S1DREG_TFT_FPFRAME_PWIDTH,	0x81 },
+	{ S1DREG_LCD_DISP_MODE,		0x03 },
+	{ S1DREG_LCD_MISC,		0x00 },
+	{ S1DREG_LCD_DISP_START0,	0x00 },
+	{ S1DREG_LCD_DISP_START1,	0x00 },
+	{ S1DREG_LCD_DISP_START2,	0x00 },
+	{ S1DREG_LCD_MEM_OFF0,		0x90 },
+	{ S1DREG_LCD_MEM_OFF1,		0x01 },
+	{ S1DREG_LCD_PIX_PAN,		0x00 },
+	{ S1DREG_LCD_DISP_FIFO_HTC,	0x00 },
+	{ S1DREG_LCD_DISP_FIFO_LTC,	0x00 },
+	{ S1DREG_CRT_DISP_HWIDTH,	0x63 },
+	{ S1DREG_CRT_NDISP_HPER,	0x1f },
+	{ S1DREG_CRT_HRTC_START,	0x04 },
+	{ S1DREG_CRT_HRTC_PWIDTH,	0x8f },
+	{ S1DREG_CRT_DISP_VHEIGHT0,	0x57 },
+	{ S1DREG_CRT_DISP_VHEIGHT1,	0x02 },
+	{ S1DREG_CRT_NDISP_VPER,	0x1b },
+	{ S1DREG_CRT_VRTC_START,	0x00 },
+	{ S1DREG_CRT_VRTC_PWIDTH,	0x83 },
+	{ S1DREG_TV_OUT_CTL,		0x10 },
+	{ S1DREG_CRT_DISP_MODE,		0x05 },
+	{ S1DREG_CRT_DISP_START0,	0x00 },
+	{ S1DREG_CRT_DISP_START1,	0x00 },
+	{ S1DREG_CRT_DISP_START2,	0x00 },
+	{ S1DREG_CRT_MEM_OFF0,		0x20 },
+	{ S1DREG_CRT_MEM_OFF1,		0x03 },
+	{ S1DREG_CRT_PIX_PAN,		0x00 },
+	{ S1DREG_CRT_DISP_FIFO_HTC,	0x00 },
+	{ S1DREG_CRT_DISP_FIFO_LTC,	0x00 },
+	{ S1DREG_LCD_CUR_CTL,		0x00 },
+	{ S1DREG_LCD_CUR_START,		0x01 },
+	{ S1DREG_LCD_CUR_XPOS0,		0x00 },
+	{ S1DREG_LCD_CUR_XPOS1,		0x00 },
+	{ S1DREG_LCD_CUR_YPOS0,		0x00 },
+	{ S1DREG_LCD_CUR_YPOS1,		0x00 },
+	{ S1DREG_LCD_CUR_BCTL0,		0x00 },
+	{ S1DREG_LCD_CUR_GCTL0,		0x00 },
+	{ S1DREG_LCD_CUR_RCTL0,		0x00 },
+	{ S1DREG_LCD_CUR_BCTL1,		0x1f },
+	{ S1DREG_LCD_CUR_GCTL1,		0x3f },
+	{ S1DREG_LCD_CUR_RCTL1,		0x1f },
+	{ S1DREG_LCD_CUR_FIFO_HTC,	0x00 },
+	{ S1DREG_CRT_CUR_CTL,		0x00 },
+	{ S1DREG_CRT_CUR_START,		0x01 },
+	{ S1DREG_CRT_CUR_XPOS0,		0x00 },
+	{ S1DREG_CRT_CUR_XPOS1,		0x00 },
+	{ S1DREG_CRT_CUR_YPOS0,		0x00 },
+	{ S1DREG_CRT_CUR_YPOS1,		0x00 },
+	{ S1DREG_CRT_CUR_BCTL0,		0x00 },
+	{ S1DREG_CRT_CUR_GCTL0,		0x00 },
+	{ S1DREG_CRT_CUR_RCTL0,		0x00 },
+	{ S1DREG_CRT_CUR_BCTL1,		0x1f },
+	{ S1DREG_CRT_CUR_GCTL1,		0x3f },
+	{ S1DREG_CRT_CUR_RCTL1,		0x1f },
+	{ S1DREG_CRT_CUR_FIFO_HTC,	0x00 },
+	{ S1DREG_BBLT_CTL0,		0x00 },
+	{ S1DREG_BBLT_CTL1,		0x00 },
+	{ S1DREG_BBLT_CC_EXP,		0x00 },
+	{ S1DREG_BBLT_OP,		0x00 },
+	{ S1DREG_BBLT_SRC_START0,	0x00 },
+	{ S1DREG_BBLT_SRC_START1,	0x00 },
+	{ S1DREG_BBLT_SRC_START2,	0x00 },
+	{ S1DREG_BBLT_DST_START0,	0x00 },
+	{ S1DREG_BBLT_DST_START1,	0x00 },
+	{ S1DREG_BBLT_DST_START2,	0x00 },
+	{ S1DREG_BBLT_MEM_OFF0,		0x00 },
+	{ S1DREG_BBLT_MEM_OFF1,		0x00 },
+	{ S1DREG_BBLT_WIDTH0,		0x00 },
+	{ S1DREG_BBLT_WIDTH1,		0x00 },
+	{ S1DREG_BBLT_HEIGHT0,		0x00 },
+	{ S1DREG_BBLT_HEIGHT1,		0x00 },
+	{ S1DREG_BBLT_BGC0,		0x00 },
+	{ S1DREG_BBLT_BGC1,		0x00 },
+	{ S1DREG_BBLT_FGC0,		0x00 },
+	{ S1DREG_BBLT_FGC1,		0x00 },
+	{ S1DREG_LKUP_MODE,		0x00 },
+	{ S1DREG_LKUP_ADDR,		0x00 },
+	{ S1DREG_PS_CNF,		0x10 },
+	{ S1DREG_PS_STATUS,		0x00 },
+	{ S1DREG_CPU2MEM_WDOGT,		0x00 },
+	{ S1DREG_COM_DISP_MODE,		0x02 },
+};
+
+static struct s1d13xxxfb_pdata s1d13806_platform_data = {
+	.initregs	= s1d13806_initregs,
+	.initregssize	= ARRAY_SIZE(s1d13806_initregs),
+};
+
+static struct resource s1d13806_resources[] = {
+	[0] = {
+		.start		= 0x07200000,
+		.end		= 0x07200000 + 0x00200000 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= 0x07000000,
+		.end		= 0x07000000 + 0x00200000 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device s1d13806_device = {
+	.name		= "s1d13806fb",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s1d13806_resources),
+	.resource	= s1d13806_resources,
+
+	.dev = {
+		.platform_data	= &s1d13806_platform_data,
+	},
+};
+#endif
+
+static struct platform_device *microdev_devices[] __initdata = {
+	&smc91x_device,
+#ifdef CONFIG_FB_S1D13XXX
+	&s1d13806_device,
+#endif
+};
+
+static int __init microdev_devices_setup(void)
 {
-	return platform_device_register(&smc91x_device);
+	return platform_add_devices(microdev_devices, ARRAY_SIZE(microdev_devices));
 }
 
-__initcall(smc91x_setup);
+__initcall(microdev_devices_setup);
 
-	/*
-	 * Initialize the board
-	 */
 void __init platform_setup(void)
 {
 	int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
diff --git a/arch/sh/boards/unknown/Makefile b/arch/sh/boards/unknown/Makefile
index cffc210..7d18f40 100644
--- a/arch/sh/boards/unknown/Makefile
+++ b/arch/sh/boards/unknown/Makefile
@@ -2,5 +2,5 @@
 # Makefile for unknown SH boards 
 #
 
-obj-y	 := mach.o io.o setup.o
+obj-y	 := setup.o
 
diff --git a/arch/sh/boards/unknown/io.c b/arch/sh/boards/unknown/io.c
deleted file mode 100644
index 8f3f172..0000000
--- a/arch/sh/boards/unknown/io.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * linux/arch/sh/kernel/io_unknown.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * I/O routine for unknown hardware.
- */
-
-static unsigned int unknown_handler(void)
-{
-	return 0;
-}
-
-#define UNKNOWN_ALIAS(fn) \
-	void unknown_##fn(void) __attribute__ ((alias ("unknown_handler")));
-
-UNKNOWN_ALIAS(inb)
-UNKNOWN_ALIAS(inw)
-UNKNOWN_ALIAS(inl)
-UNKNOWN_ALIAS(outb)
-UNKNOWN_ALIAS(outw)
-UNKNOWN_ALIAS(outl)
-UNKNOWN_ALIAS(inb_p)
-UNKNOWN_ALIAS(inw_p)
-UNKNOWN_ALIAS(inl_p)
-UNKNOWN_ALIAS(outb_p)
-UNKNOWN_ALIAS(outw_p)
-UNKNOWN_ALIAS(outl_p)
-UNKNOWN_ALIAS(insb)
-UNKNOWN_ALIAS(insw)
-UNKNOWN_ALIAS(insl)
-UNKNOWN_ALIAS(outsb)
-UNKNOWN_ALIAS(outsw)
-UNKNOWN_ALIAS(outsl)
-UNKNOWN_ALIAS(readb)
-UNKNOWN_ALIAS(readw)
-UNKNOWN_ALIAS(readl)
-UNKNOWN_ALIAS(writeb)
-UNKNOWN_ALIAS(writew)
-UNKNOWN_ALIAS(writel)
-UNKNOWN_ALIAS(isa_port2addr)
-UNKNOWN_ALIAS(ioremap)
-UNKNOWN_ALIAS(iounmap)
diff --git a/arch/sh/boards/unknown/mach.c b/arch/sh/boards/unknown/mach.c
deleted file mode 100644
index ad0bcc6..0000000
--- a/arch/sh/boards/unknown/mach.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_unknown.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine specific code for an unknown machine (internal peripherials only)
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io_unknown.h>
-
-#include <asm/rtc.h>
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_unknown __initmv = {
-#if defined(CONFIG_CPU_SH4)
-	.mv_nr_irqs		= 48,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
-	.mv_nr_irqs		= 32,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
-	.mv_nr_irqs		= 61,
-#endif
-
-	.mv_inb			= unknown_inb,
-	.mv_inw			= unknown_inw,
-	.mv_inl			= unknown_inl,
-	.mv_outb		= unknown_outb,
-	.mv_outw		= unknown_outw,
-	.mv_outl		= unknown_outl,
-
-	.mv_inb_p		= unknown_inb_p,
-	.mv_inw_p		= unknown_inw_p,
-	.mv_inl_p		= unknown_inl_p,
-	.mv_outb_p		= unknown_outb_p,
-	.mv_outw_p		= unknown_outw_p,
-	.mv_outl_p		= unknown_outl_p,
-
-	.mv_insb		= unknown_insb,
-	.mv_insw		= unknown_insw,
-	.mv_insl		= unknown_insl,
-	.mv_outsb		= unknown_outsb,
-	.mv_outsw		= unknown_outsw,
-	.mv_outsl		= unknown_outsl,
-
-	.mv_readb		= unknown_readb,
-	.mv_readw		= unknown_readw,
-	.mv_readl		= unknown_readl,
-	.mv_writeb		= unknown_writeb,
-	.mv_writew		= unknown_writew,
-	.mv_writel		= unknown_writel,
-
-	.mv_ioremap		= unknown_ioremap,
-	.mv_iounmap		= unknown_iounmap,
-
-	.mv_isa_port2addr	= unknown_isa_port2addr,
-};
-ALIAS_MV(unknown)
diff --git a/arch/sh/boards/unknown/setup.c b/arch/sh/boards/unknown/setup.c
index 7d772a6..02e84f0 100644
--- a/arch/sh/boards/unknown/setup.c
+++ b/arch/sh/boards/unknown/setup.c
@@ -7,10 +7,20 @@
  * License.  See linux/COPYING for more information.
  *
  * Setup code for an unknown machine (internal peripherials only)
+ *
+ * This is the simplest of all boards, and serves only as a quick and dirty
+ * method to start debugging a new board during bring-up until proper board
+ * setup code is written.
  */
-
 #include <linux/config.h>
 #include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/irq.h>
+
+struct sh_machine_vector mv_unknown __initmv = {
+	.mv_nr_irqs		= NR_IRQS,
+};
+ALIAS_MV(unknown)
 
 const char *get_system_type(void)
 {
diff --git a/arch/sh/cchips/voyagergx/consistent.c b/arch/sh/cchips/voyagergx/consistent.c
index 3d9a02c..07e8b9c 100644
--- a/arch/sh/cchips/voyagergx/consistent.c
+++ b/arch/sh/cchips/voyagergx/consistent.c
@@ -15,7 +15,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <asm/io.h>
-#include <asm/bus-sh.h>
+
 
 struct voya_alloc_entry {
 	struct list_head list;
@@ -30,12 +30,13 @@
 #define OHCI_HCCA_SIZE	0x100
 #define OHCI_SRAM_SIZE	0x10000
 
+#define VOYAGER_OHCI_NAME	"voyager-ohci"
+
 void *voyagergx_consistent_alloc(struct device *dev, size_t size,
 				 dma_addr_t *handle, gfp_t flag)
 {
 	struct list_head *list = &voya_alloc_list;
 	struct voya_alloc_entry *entry;
-	struct sh_dev *shdev = to_sh_dev(dev);
 	unsigned long start, end;
 	unsigned long flags;
 
@@ -46,9 +47,7 @@
 	 *
 	 * Everything else goes through consistent_alloc().
 	 */
-	if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
-		   (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
-		    shdev->dev_id != SH_DEV_ID_USB_OHCI))
+	if (!dev || strcmp(dev->driver->name, VOYAGER_OHCI_NAME))
 		return NULL;
 
 	start = OHCI_SRAM_START + OHCI_HCCA_SIZE;
@@ -98,12 +97,9 @@
 			      void *vaddr, dma_addr_t handle)
 {
 	struct voya_alloc_entry *entry;
-	struct sh_dev *shdev = to_sh_dev(dev);
 	unsigned long flags;
 
-	if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
-		   (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
-		    shdev->dev_id != SH_DEV_ID_USB_OHCI))
+	if (!dev || strcmp(dev->driver->name, VOYAGER_OHCI_NAME))
 		return -EINVAL;
 
 	spin_lock_irqsave(&voya_list_lock, flags);
@@ -123,4 +119,3 @@
 
 EXPORT_SYMBOL(voyagergx_consistent_alloc);
 EXPORT_SYMBOL(voyagergx_consistent_free);
-
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
index 1b6ac52..2ee330b 100644
--- a/arch/sh/cchips/voyagergx/irq.c
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -163,7 +163,12 @@
 	return irq;
 }
 
-static struct irqaction irq0  = { voyagergx_interrupt, SA_INTERRUPT, 0, "VOYAGERGX", NULL, NULL};
+static struct irqaction irq0  = {
+	.name		= "voyagergx",
+	.handler	= voyagergx_interrupt,
+	.flags		= SA_INTERRUPT,
+	.mask		= CPU_MASK_NONE,
+};
 
 void __init setup_voyagergx_irq(void)
 {
diff --git a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig
index a3bd280..ab3db76 100644
--- a/arch/sh/configs/microdev_defconfig
+++ b/arch/sh/configs/microdev_defconfig
@@ -1,10 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-sh
-# Wed Mar  2 15:09:41 2005
+# Linux kernel version: 2.6.16-rc1
+# Fri Jan 27 19:43:20 2006
 #
 CONFIG_SUPERH=y
-CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -17,11 +16,13 @@
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
@@ -29,22 +30,29 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -52,6 +60,24 @@
 # CONFIG_MODULES is not set
 
 #
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
 # System type
 #
 # CONFIG_SH_SOLUTION_ENGINE is not set
@@ -61,9 +87,7 @@
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
-# CONFIG_SH_HP620 is not set
-# CONFIG_SH_HP680 is not set
-# CONFIG_SH_HP690 is not set
+# CONFIG_SH_HP6XX is not set
 # CONFIG_SH_CQREEK is not set
 # CONFIG_SH_DMIDA is not set
 # CONFIG_SH_EC3104 is not set
@@ -78,45 +102,94 @@
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 # CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
 # CONFIG_SH_EDOSK7705 is not set
 CONFIG_SH_SH4202_MICRODEV=y
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
 # CONFIG_SH_UNKNOWN is not set
-# CONFIG_CPU_SH2 is not set
-# CONFIG_CPU_SH3 is not set
+
+#
+# Processor selection
+#
 CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
 # CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
-# CONFIG_CPU_SUBTYPE_SH73180 is not set
+CONFIG_CPU_SUBTYPE_SH4_202=y
+
+#
+# ST40 Processor Support
+#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-CONFIG_CPU_SUBTYPE_SH4_202=y
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
 CONFIG_MMU=y
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttySC0,115200"
-CONFIG_MEMORY_START=0x08000000
-CONFIG_MEMORY_SIZE=0x04000000
-CONFIG_MEMORY_SET=y
-# CONFIG_MEMORY_OVERRIDE is not set
-CONFIG_SH_RTC=y
-CONFIG_SH_FPU=y
-CONFIG_ZERO_PAGE_OFFSET=0x00001000
-CONFIG_BOOT_LINK_OFFSET=0x00800000
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_PREEMPT=y
-# CONFIG_UBC_WAKEUP is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
 # CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x04000000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
 # CONFIG_SH_STORE_QUEUES is not set
-# CONFIG_SMP is not set
-CONFIG_SH_PCLK_CALC=y
-CONFIG_SH_PCLK_FREQ=65986048
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=66000000
 
 #
 # CPU Frequency scaling
@@ -137,9 +210,25 @@
 CONFIG_HEARTBEAT=y
 
 #
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+# Kernel features
 #
-CONFIG_ISA=y
+# CONFIG_KEXEC is not set
+CONFIG_PREEMPT=y
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200"
+
+#
+# Bus options
+#
+# CONFIG_SUPERHYWAY is not set
 # CONFIG_PCI is not set
 
 #
@@ -148,11 +237,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-CONFIG_PCMCIA_PROBE=y
-
-#
 # PCI Hotplug Support
 #
 
@@ -164,9 +248,79 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
-# SH initrd options
+# Networking
 #
-# CONFIG_EMBEDDED_RAMDISK is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_UNIX is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -180,6 +334,11 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -192,13 +351,10 @@
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -206,17 +362,7 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -241,9 +387,7 @@
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
-CONFIG_IDE_SH=y
 # CONFIG_IDE_ARM is not set
-# CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -251,14 +395,10 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -266,6 +406,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -276,69 +417,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_UNIX is not set
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -346,9 +426,9 @@
 # CONFIG_TUN is not set
 
 #
-# ARCnet devices
+# PHY device support
 #
-# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -356,17 +436,7 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 # CONFIG_STNIC is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
 CONFIG_SMC91X=y
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -379,7 +449,6 @@
 #
 # Token Ring devices
 #
-# CONFIG_TR is not set
 
 #
 # Wireless LAN (non-hamradio)
@@ -394,6 +463,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -411,20 +482,10 @@
 # CONFIG_INPUT is not set
 
 #
-# Userland interfaces
+# Hardware I/O ports
 #
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
-# Input Device Drivers
-#
+# CONFIG_GAMEPORT is not set
 
 #
 # Character devices
@@ -464,24 +525,46 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
 
 #
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -508,7 +591,7 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
 #
 
 #
@@ -524,13 +607,21 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# EDAC - error detection and reporting (RAS)
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -540,17 +631,17 @@
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -574,16 +665,12 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -607,12 +694,14 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
@@ -622,6 +711,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -681,8 +771,10 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
@@ -706,6 +798,7 @@
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -730,5 +823,6 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 7a86eeb..f05cd96 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -8,7 +8,7 @@
 	ptrace.o setup.o time.o sys_sh.o semaphore.o \
 	io.o io_generic.o sh_ksyms.o
 
-obj-y				+= cpu/
+obj-y				+= cpu/ timers/
 
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_CF_ENABLER)	+= cf-enabler.o
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index 5bfc33b..59d5b74 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Linux/SuperH CPU-specifc backends.
 #
 
-obj-y	+= irq/ init.o bus.o clock.o
+obj-y	+= irq/ init.o clock.o
 
 obj-$(CONFIG_CPU_SH2)		+= sh2/
 obj-$(CONFIG_CPU_SH3)		+= sh3/
diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c
deleted file mode 100644
index fc6c4bd..0000000
--- a/arch/sh/kernel/cpu/bus.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * arch/sh/kernel/cpu/bus.c
- *
- * Virtual bus for SuperH.
- *
- * Copyright (C) 2004 Paul Mundt
- *
- * Shamelessly cloned from arch/arm/mach-omap/bus.c, which was written
- * by:
- *
- *  	Copyright (C) 2003 - 2004 Nokia Corporation
- *  	Written by Tony Lindgren <tony@atomide.com>
- *  	Portions of code based on sa1111.c.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <asm/bus-sh.h>
-
-static int sh_bus_match(struct device *dev, struct device_driver *drv)
-{
-	struct sh_driver *shdrv = to_sh_driver(drv);
-	struct sh_dev *shdev = to_sh_dev(dev);
-
-	return shdev->dev_id == shdrv->dev_id;
-}
-
-static int sh_bus_suspend(struct device *dev, pm_message_t state)
-{
-	struct sh_dev *shdev = to_sh_dev(dev);
-	struct sh_driver *shdrv = to_sh_driver(dev->driver);
-
-	if (shdrv && shdrv->suspend)
-		return shdrv->suspend(shdev, state);
-
-	return 0;
-}
-
-static int sh_bus_resume(struct device *dev)
-{
-	struct sh_dev *shdev = to_sh_dev(dev);
-	struct sh_driver *shdrv = to_sh_driver(dev->driver);
-
-	if (shdrv && shdrv->resume)
-		return shdrv->resume(shdev);
-
-	return 0;
-}
-
-static int sh_device_probe(struct device *dev)
-{
-	struct sh_dev *shdev = to_sh_dev(dev);
-	struct sh_driver *shdrv = to_sh_driver(dev->driver);
-
-	if (shdrv && shdrv->probe)
-		return shdrv->probe(shdev);
-
-	return -ENODEV;
-}
-
-static int sh_device_remove(struct device *dev)
-{
-	struct sh_dev *shdev = to_sh_dev(dev);
-	struct sh_driver *shdrv = to_sh_driver(dev->driver);
-
-	if (shdrv && shdrv->remove)
-		return shdrv->remove(shdev);
-
-	return 0;
-}
-
-static struct device sh_bus_devices[SH_NR_BUSES] = {
-	{
-		.bus_id		= SH_BUS_NAME_VIRT,
-	},
-};
-
-struct bus_type sh_bus_types[SH_NR_BUSES] = {
-	{
-		.name		= SH_BUS_NAME_VIRT,
-		.match		= sh_bus_match,
-		.probe		= sh_bus_probe,
-		.remove		= sh_bus_remove,
-		.suspend	= sh_bus_suspend,
-		.resume		= sh_bus_resume,
-	},
-};
-
-int sh_device_register(struct sh_dev *dev)
-{
-	if (!dev)
-		return -EINVAL;
-
-	if (dev->bus_id < 0 || dev->bus_id >= SH_NR_BUSES) {
-		printk(KERN_ERR "%s: bus_id invalid: %s bus: %d\n",
-		       __FUNCTION__, dev->name, dev->bus_id);
-		return -EINVAL;
-	}
-
-	dev->dev.parent = &sh_bus_devices[dev->bus_id];
-	dev->dev.bus    = &sh_bus_types[dev->bus_id];
-
-	/* This is needed for USB OHCI to work */
-	if (dev->dma_mask)
-		dev->dev.dma_mask = dev->dma_mask;
-	if (dev->coherent_dma_mask)
-		dev->dev.coherent_dma_mask = dev->coherent_dma_mask;
-
-	snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u",
-		 dev->name, dev->dev_id);
-
-	printk(KERN_INFO "Registering SH device '%s'. Parent at %s\n",
-	       dev->dev.bus_id, dev->dev.parent->bus_id);
-
-	return device_register(&dev->dev);
-}
-
-void sh_device_unregister(struct sh_dev *dev)
-{
-	device_unregister(&dev->dev);
-}
-
-int sh_driver_register(struct sh_driver *drv)
-{
-	if (!drv)
-		return -EINVAL;
-
-	if (drv->bus_id < 0 || drv->bus_id >= SH_NR_BUSES) {
-		printk(KERN_ERR "%s: bus_id invalid: bus: %d device %d\n",
-		       __FUNCTION__, drv->bus_id, drv->dev_id);
-		return -EINVAL;
-	}
-
-	drv->drv.bus    = &sh_bus_types[drv->bus_id];
-
-	return driver_register(&drv->drv);
-}
-
-void sh_driver_unregister(struct sh_driver *drv)
-{
-	driver_unregister(&drv->drv);
-}
-
-static int __init sh_bus_init(void)
-{
-	int i, ret = 0;
-
-	for (i = 0; i < SH_NR_BUSES; i++) {
-		ret = device_register(&sh_bus_devices[i]);
-		if (ret != 0) {
-			printk(KERN_ERR "Unable to register bus device %s\n",
-			       sh_bus_devices[i].bus_id);
-			continue;
-		}
-
-		ret = bus_register(&sh_bus_types[i]);
-		if (ret != 0) {
-			printk(KERN_ERR "Unable to register bus %s\n",
-			       sh_bus_types[i].name);
-			device_unregister(&sh_bus_devices[i]);
-		}
-	}
-
-	printk(KERN_INFO "SH Virtual Bus initialized\n");
-
-	return ret;
-}
-
-static void __exit sh_bus_exit(void)
-{
-	int i;
-
-	for (i = 0; i < SH_NR_BUSES; i++) {
-		bus_unregister(&sh_bus_types[i]);
-		device_unregister(&sh_bus_devices[i]);
-	}
-}
-
-module_init(sh_bus_init);
-module_exit(sh_bus_exit);
-
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
-MODULE_DESCRIPTION("SH Virtual Bus");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(sh_bus_types);
-EXPORT_SYMBOL(sh_device_register);
-EXPORT_SYMBOL(sh_device_unregister);
-EXPORT_SYMBOL(sh_driver_register);
-EXPORT_SYMBOL(sh_driver_unregister);
-
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 989e7fd..97fa37f 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -38,9 +38,7 @@
 static struct clk master_clk = {
 	.name		= "master_clk",
 	.flags		= CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
-#ifdef CONFIG_SH_PCLK_FREQ_BOOL
 	.rate		= CONFIG_SH_PCLK_FREQ,
-#endif
 };
 
 static struct clk module_clk = {
@@ -227,16 +225,7 @@
 {
 	int i, ret = 0;
 
-	if (unlikely(!master_clk.rate))
-		/*
-		 * NOTE: This will break if the default divisor has been
-		 * changed.
-		 *
-		 * No one should be changing the default on us however,
-		 * expect that a sane value for CONFIG_SH_PCLK_FREQ will
-		 * be defined in the event of a different divisor.
-		 */
-		master_clk.rate = get_timer_frequency() * 4;
+	BUG_ON(unlikely(!master_clk.rate));
 
 	for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
 		struct clk *clk = onchip_clocks[i];
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index fdbd718..e55150e 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -108,8 +108,7 @@
 		enable_ipr_irq(irq);
 }
 
-void make_ipr_irq(unsigned int irq, unsigned int addr, int pos,
-		  int priority, int maskpos)
+void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
 {
 	disable_irq_nosync(irq);
 	ipr_data[irq].addr = addr;
@@ -123,44 +122,44 @@
 void __init init_IRQ(void)
 {
 #ifndef CONFIG_CPU_SUBTYPE_SH7780
-	make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY, 0);
-	make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY, 0);
+	make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
+	make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
 #if defined(CONFIG_SH_RTC)
-	make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY, 0);
+	make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
 #endif
 
 #ifdef SCI_ERI_IRQ
-	make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
-	make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
-	make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
+	make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+	make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+	make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
 #endif
 
 #ifdef SCIF1_ERI_IRQ
-	make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
-	make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
-	make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
-	make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
+	make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+	make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+	make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+	make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7300)
-	make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY, 0);
-	make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0);
-	make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0);
-	make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY, 0);
+	make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY);
+	make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+	make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+	make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
 #endif
 
 #ifdef SCIF_ERI_IRQ
-	make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
-	make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
-	make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
-	make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
+	make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+	make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+	make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+	make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
 #endif
 
 #ifdef IRDA_ERI_IRQ
-	make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
-	make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
-	make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
-	make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
+	make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+	make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+	make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+	make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
@@ -175,12 +174,12 @@
 	 * You should set corresponding bits of PFC to "00"
 	 * to enable these interrupts.
 	 */
-	make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY, 0);
-	make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY, 0);
-	make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY, 0);
-	make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY, 0);
-	make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY, 0);
-	make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY, 0);
+	make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY);
+	make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
+	make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
+	make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY);
+	make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY);
+	make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY);
 #endif
 #endif
 
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
index fb63681..a440d36 100644
--- a/arch/sh/kernel/entry.S
+++ b/arch/sh/kernel/entry.S
@@ -16,6 +16,7 @@
 #include <linux/config.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
+#include <asm/cpu/mmu_context.h>
 #include <asm/unistd.h>
 
 #if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
@@ -75,23 +76,6 @@
 ENOSYS = 38
 EINVAL = 22
 
-#if defined(CONFIG_CPU_SH3)
-TRA     = 0xffffffd0
-EXPEVT  = 0xffffffd4
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
-INTEVT  = 0xa4000000		! INTEVTE2(0xa4000000)
-#else
-INTEVT  = 0xffffffd8
-#endif
-MMU_TEA = 0xfffffffc		! TLB Exception Address Register
-#elif defined(CONFIG_CPU_SH4)
-TRA     = 0xff000020
-EXPEVT  = 0xff000024
-INTEVT  = 0xff000028
-MMU_TEA = 0xff00000c		! TLB Exception Address Register
-#endif
-
 #if defined(CONFIG_KGDB_NMI)
 NMI_VEC = 0x1c0			! Must catch early for debounce
 #endif
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index a4dc2b5..9fd1723 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -15,21 +15,18 @@
 #include <linux/unistd.h>
 #include <linux/mm.h>
 #include <linux/elfcore.h>
-#include <linux/slab.h>
 #include <linux/a.out.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
 #include <linux/ptrace.h>
 #include <linux/platform.h>
 #include <linux/kallsyms.h>
+#include <linux/kexec.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/elf.h>
-#if defined(CONFIG_SH_HS7751RVOIP)
-#include <asm/hs7751rvoip/hs7751rvoip.h>
-#elif defined(CONFIG_SH_RTS7751R2D)
-#include <asm/rts7751r2d/rts7751r2d.h>
-#endif
 
 static int hlt_counter=0;
 
@@ -37,6 +34,11 @@
 
 #define HARD_IDLE_TIMEOUT (HZ / 3)
 
+void (*pm_idle)(void);
+
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
 void disable_hlt(void)
 {
 	hlt_counter++;
@@ -51,17 +53,25 @@
 
 EXPORT_SYMBOL(enable_hlt);
 
+void default_idle(void)
+{
+	if (!hlt_counter)
+		cpu_sleep();
+	else
+		cpu_relax();
+}
+
 void cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
-		if (hlt_counter) {
-			while (!need_resched())
-				cpu_relax();
-		} else {
-			while (!need_resched())
-				cpu_sleep();
-		}
+		void (*idle)(void) = pm_idle;
+
+		if (!idle)
+			idle = default_idle;
+
+		while (!need_resched())
+			idle();
 
 		preempt_enable_no_resched();
 		schedule();
@@ -88,28 +98,16 @@
 
 void machine_halt(void)
 {
-#if defined(CONFIG_SH_HS7751RVOIP)
-	unsigned short value;
+	local_irq_disable();
 
-	value = ctrl_inw(PA_OUTPORTR);
-	ctrl_outw((value & 0xffdf), PA_OUTPORTR);
-#elif defined(CONFIG_SH_RTS7751R2D)
-	ctrl_outw(0x0001, PA_POWOFF);
-#endif
 	while (1)
 		cpu_sleep();
 }
 
 void machine_power_off(void)
 {
-#if defined(CONFIG_SH_HS7751RVOIP)
-	unsigned short value;
-
-	value = ctrl_inw(PA_OUTPORTR);
-	ctrl_outw((value & 0xffdf), PA_OUTPORTR);
-#elif defined(CONFIG_SH_RTS7751R2D)
-	ctrl_outw(0x0001, PA_POWOFF);
-#endif
+	if (pm_power_off)
+		pm_power_off();
 }
 
 void show_regs(struct pt_regs * regs)
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 036050b..a067a34 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -22,10 +22,10 @@
 #include <linux/cpu.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/io_generic.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
+#include <asm/clock.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
@@ -41,7 +41,7 @@
  * This value will be used at the very early stage of serial setup.
  * The bigger value means no problem.
  */
-struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, };
+struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
 struct screen_info screen_info;
 
 #if defined(CONFIG_SH_UNKNOWN)
@@ -186,7 +186,7 @@
 
 static int __init sh_mv_setup(char **cmdline_p)
 {
-#if defined(CONFIG_SH_UNKNOWN)
+#ifdef CONFIG_SH_UNKNOWN
 	extern struct sh_machine_vector mv_unknown;
 #endif
 	struct sh_machine_vector *mv = NULL;
@@ -196,7 +196,7 @@
 
 	parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
 
-#ifdef CONFIG_SH_GENERIC
+#ifdef CONFIG_SH_UNKNOWN
 	if (mv == NULL) {
 		mv = &mv_unknown;
 		if (*mv_name != '\0') {
@@ -206,9 +206,6 @@
 	}
 	sh_mv = *mv;
 #endif
-#ifdef CONFIG_SH_UNKNOWN
-	sh_mv = mv_unknown;
-#endif
 
 	/*
 	 * Manually walk the vec, fill in anything that the board hasn't yet
@@ -231,10 +228,8 @@
 	mv_set(readb);	mv_set(readw);	mv_set(readl);
 	mv_set(writeb);	mv_set(writew);	mv_set(writel);
 
-	mv_set(ioremap);
-	mv_set(iounmap);
-
-	mv_set(isa_port2addr);
+	mv_set(ioport_map);
+	mv_set(ioport_unmap);
 	mv_set(irq_demux);
 
 #ifdef CONFIG_SH_UNKNOWN
@@ -273,10 +268,10 @@
 	init_mm.end_data = (unsigned long) _edata;
 	init_mm.brk = (unsigned long) _end;
 
-	code_resource.start = virt_to_bus(_text);
-	code_resource.end = virt_to_bus(_etext)-1;
-	data_resource.start = virt_to_bus(_etext);
-	data_resource.end = virt_to_bus(_edata)-1;
+	code_resource.start = (unsigned long)virt_to_phys(_text);
+	code_resource.end = (unsigned long)virt_to_phys(_etext)-1;
+	data_resource.start = (unsigned long)virt_to_phys(_etext);
+	data_resource.end = (unsigned long)virt_to_phys(_edata)-1;
 
 	sh_mv_setup(cmdline_p);
 
@@ -435,6 +430,9 @@
 	[CPU_ST40GX1]	= "ST40GX1",
 	[CPU_SH4_202]	= "SH4-202",
 	[CPU_SH4_501]	= "SH4-501",
+	[CPU_SH7770]	= "SH7770",
+	[CPU_SH7780]	= "SH7780",
+	[CPU_SH7781]	= "SH7781",
 	[CPU_SH_NONE]	= "Unknown"
 };
 
@@ -445,7 +443,7 @@
 
 #ifdef CONFIG_PROC_FS
 static const char *cpu_flags[] = {
-	"none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
+	"none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", "ptea", NULL
 };
 
 static void show_cpuflags(struct seq_file *m)
@@ -459,7 +457,7 @@
 		return;
 	}
 
-	for (i = 0; i < cpu_data->flags; i++)
+	for (i = 0; cpu_flags[i]; i++)
 		if ((cpu_data->flags & (1 << i)))
 			seq_printf(m, " %s", cpu_flags[i+1]);
 
@@ -472,7 +470,8 @@
 
 	cache_size = info.ways * info.sets * info.linesz;
 
-	seq_printf(m, "%s size\t: %dKiB\n", type, cache_size >> 10);
+	seq_printf(m, "%s size\t: %2dKiB (%d-way)\n",
+		   type, cache_size >> 10, info.ways);
 }
 
 /*
@@ -511,21 +510,9 @@
 		     boot_cpu_data.loops_per_jiffy/(500000/HZ),
 		     (boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100);
 
-#define PRINT_CLOCK(name, value) \
-	seq_printf(m, name " clock\t: %d.%02dMHz\n", \
-		     ((value) / 1000000), ((value) % 1000000)/10000)
-	
-	PRINT_CLOCK("cpu", boot_cpu_data.cpu_clock);
-	PRINT_CLOCK("bus", boot_cpu_data.bus_clock);
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-	PRINT_CLOCK("memory", boot_cpu_data.memory_clock);
-#endif
-	PRINT_CLOCK("module", boot_cpu_data.module_clock);
-
-	return 0;
+	return show_clocks(m);
 }
 
-
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
 	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
@@ -596,7 +583,7 @@
 		options += map->namelen + 1;
 
 		options = (*options == ',') ? options+1 : options;
-		
+
 		/* Read optional parameters (baud/parity/bits) */
 		baud = simple_strtoul(options, &options, 10);
 		if (baud != 0) {
diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
index 472b450..de29c45 100644
--- a/arch/sh64/kernel/sh_ksyms.c
+++ b/arch/sh64/kernel/sh_ksyms.c
@@ -31,14 +31,6 @@
 
 extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
 
-#if 0
-/* Not yet - there's no declaration of drive_info anywhere. */
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
-extern struct drive_info_struct drive_info;
-EXPORT_SYMBOL(drive_info);
-#endif
-#endif
-
 /* platform dependent support */
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(iounmap);
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index 1195af3..0773c9f 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -29,6 +29,7 @@
 #include <linux/init.h>
 #include <linux/profile.h>
 #include <linux/smp.h>
+#include <linux/module.h>
 
 #include <asm/registers.h>	 /* required by inline __asm__ stmt. */
 
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 03ecb4e..887f6a1 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -38,7 +38,7 @@
 
 #define curptr      g6
 
-#define NR_SYSCALLS 284      /* Each OS is different... */
+#define NR_SYSCALLS 300      /* Each OS is different... */
 
 /* These are just handy. */
 #define _SV	save	%sp, -STACKFRAME_SZ, %sp
@@ -1277,62 +1277,6 @@
 	 mov	%l5, %o7
 
 	.align	4
-	.globl	sys_sigpause
-sys_sigpause:
-	/* Note: %o0 already has correct value... */
-	call	do_sigpause
-	 add	%sp, STACKFRAME_SZ, %o1
-
-	ld	[%curptr + TI_FLAGS], %l5
-	andcc	%l5, _TIF_SYSCALL_TRACE, %g0
-	be	1f
-	 nop
-
-	call	syscall_trace
-	 nop
-
-1:
-	/* We are returning to a signal handler. */
-	RESTORE_ALL
-
-	.align	4
-	.globl	sys_sigsuspend
-sys_sigsuspend:
-	call	do_sigsuspend
-	 add	%sp, STACKFRAME_SZ, %o0
-
-	ld	[%curptr + TI_FLAGS], %l5
-	andcc	%l5, _TIF_SYSCALL_TRACE, %g0
-	be	1f
-	 nop
-
-	call	syscall_trace
-	 nop
-
-1:
-	/* We are returning to a signal handler. */
-	RESTORE_ALL
-
-	.align	4
-	.globl	sys_rt_sigsuspend
-sys_rt_sigsuspend:
-	/* Note: %o0, %o1 already have correct value... */
-	call	do_rt_sigsuspend
-	 add	%sp, STACKFRAME_SZ, %o2
-
-	ld	[%curptr + TI_FLAGS], %l5
-	andcc	%l5, _TIF_SYSCALL_TRACE, %g0
-	be	1f
-	 nop
-
-	call	syscall_trace
-	 nop
-
-1:
-	/* We are returning to a signal handler. */
-	RESTORE_ALL
-
-	.align	4
 	.globl	sys_sigreturn
 sys_sigreturn:
 	call	do_sigreturn
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index fbb05a4..118cac8 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -54,7 +54,7 @@
  * This is done via auxio, but could be used as a fallback
  * handler when auxio is not present-- unused for now...
  */
-void (*pm_power_off)(void);
+void (*pm_power_off)(void) = machine_power_off;
 
 /*
  * sysctl - toggle power-off restriction for serial console 
diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S
index f7460d8..77ca6fd 100644
--- a/arch/sparc/kernel/rtrap.S
+++ b/arch/sparc/kernel/rtrap.S
@@ -68,15 +68,14 @@
 
 	ld	[%curptr + TI_FLAGS], %g2
 signal_p:
-	andcc	%g2, (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING), %g0
+	andcc	%g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0
 	bz,a	ret_trap_continue
 	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr
 
-	clr	%o0
-	mov	%l5, %o2
-	mov	%l6, %o3
+	mov	%l5, %o1
+	mov	%l6, %o2
 	call	do_signal
-	 add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
+	 add	%sp, STACKFRAME_SZ, %o0	! pt_regs ptr
 
 	/* Fall through. */
 	ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 5f34d7d..0748d81 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -35,9 +35,6 @@
 		   void *fpqueue, unsigned long *fpqdepth);
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
 
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
-			 unsigned long orig_o0, int restart_syscall);
-
 /* Signal frames: the original one (compatible with SunOS):
  *
  * Set up a signal frame... Make the stack look the way SunOS
@@ -95,98 +92,30 @@
 #define NF_ALIGNEDSZ  (((sizeof(struct new_signal_frame) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- * This is really tricky on the Sparc, watch out...
- */
-asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
+static int _sigpause_common(old_sigset_t set)
 {
-	sigset_t saveset;
-
 	set &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, set);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs->pc = regs->npc;
-	regs->npc += 4;
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
 
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->psr |= PSR_C;
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal(&saveset, regs, 0, 0))
-			return;
-	}
+	return -ERESTARTNOHAND;
 }
 
-asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
+asmlinkage int sys_sigpause(unsigned int set)
 {
-	_sigpause_common(set, regs);
+	return _sigpause_common(set);
 }
 
-asmlinkage void do_sigsuspend (struct pt_regs *regs)
+asmlinkage int sys_sigsuspend(old_sigset_t set)
 {
-	_sigpause_common(regs->u_regs[UREG_I0], regs);
-}
-
-asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
-				 struct pt_regs *regs)
-{
-	sigset_t oldset, set;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t)) {
-		regs->psr |= PSR_C;
-		regs->u_regs[UREG_I0] = EINVAL;
-		return;
-	}
-
-	if (copy_from_user(&set, uset, sizeof(set))) {
-		regs->psr |= PSR_C;
-		regs->u_regs[UREG_I0] = EFAULT;
-		return;
-	}
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	oldset = current->blocked;
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->pc = regs->npc;
-	regs->npc += 4;
-
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->psr |= PSR_C;
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal(&oldset, regs, 0, 0))
-			return;
-	}
+	return _sigpause_common(set);
 }
 
 static inline int
@@ -1067,13 +996,13 @@
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
-			 unsigned long orig_i0, int restart_syscall)
+asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall)
 {
 	siginfo_t info;
 	struct sparc_deliver_cookie cookie;
 	struct k_sigaction ka;
 	int signr;
+	sigset_t *oldset;
 
 	/*
 	 * XXX Disable svr4 signal handling until solaris emulation works.
@@ -1089,7 +1018,9 @@
 	cookie.restart_syscall = restart_syscall;
 	cookie.orig_i0 = orig_i0;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
@@ -1098,7 +1029,14 @@
 			syscall_restart(cookie.orig_i0, regs, &ka.sa);
 		handle_signal(signr, &ka, &info, oldset,
 			      regs, svr4_signal);
-		return 1;
+		/* a signal was successfully delivered; the saved
+		 * sigmask will have been stored in the signal frame,
+		 * and will be restored by sigreturn, so we can simply
+		 * clear the TIF_RESTORE_SIGMASK flag.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+		return;
 	}
 	if (cookie.restart_syscall &&
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -1115,7 +1053,14 @@
 		regs->pc -= 4;
 		regs->npc -= 4;
 	}
-	return 0;
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back
+	 */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
 
 asmlinkage int
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 0b0d492..19b2539 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -66,7 +66,6 @@
 
 extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
 extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
-void _sigpause_common (unsigned int set, struct pt_regs *);
 extern void (*__copy_1page)(void *, const void *);
 extern void __memmove(void *, const void *, __kernel_size_t);
 extern void (*bzero_1page)(void *);
@@ -227,7 +226,6 @@
 /* Solaris/SunOS binary compatibility */
 EXPORT_SYMBOL(svr4_setcontext);
 EXPORT_SYMBOL(svr4_getcontext);
-EXPORT_SYMBOL(_sigpause_common);
 
 EXPORT_SYMBOL(dump_thread);
 
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index e457a40..768de64 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -75,7 +75,10 @@
 /*265*/	.long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
 /*270*/	.long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 /*275*/	.long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/	.long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
+/*280*/	.long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+/*285*/	.long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
+/*290*/	.long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+/*295*/	.long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
 
 #ifdef CONFIG_SUNOS_EMUL
 	/* Now the SunOS syscall table. */
@@ -181,6 +184,12 @@
 	.long sunos_nosys, sunos_nosys, sunos_nosys
 	.long sunos_nosys
 /*280*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys
+/*290*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
 	.long sunos_nosys
 
 #endif
diff --git a/arch/sparc/math-emu/math.c b/arch/sparc/math-emu/math.c
index be2c809..8613b3e 100644
--- a/arch/sparc/math-emu/math.c
+++ b/arch/sparc/math-emu/math.c
@@ -323,11 +323,6 @@
 		case FMOVS:
 		case FABSS:
 		case FNEGS: TYPE(2,1,0,1,0,0,0); break;
-		default:
-#ifdef DEBUG_MATHEMU
-			printk("unknown FPop1: %03lx\n",(insn>>5)&0x1ff);
-#endif
-			break;
 		}
 	} else if ((insn & 0xc1f80000) == 0x81a80000)	/* FPOP2 */ {
 		switch ((insn >> 5) & 0x1ff) {
@@ -337,11 +332,6 @@
 		case FCMPED: TYPE(3,0,0,2,1,2,1); break;
 		case FCMPQ: TYPE(3,0,0,3,1,3,1); break;
 		case FCMPEQ: TYPE(3,0,0,3,1,3,1); break;
-		default:
-#ifdef DEBUG_MATHEMU
-			printk("unknown FPop2: %03lx\n",(insn>>5)&0x1ff);
-#endif
-			break;
 		}
 	}
 
diff --git a/arch/sparc64/boot/.gitignore b/arch/sparc64/boot/.gitignore
new file mode 100644
index 0000000..36356f9
--- /dev/null
+++ b/arch/sparc64/boot/.gitignore
@@ -0,0 +1,4 @@
+image
+tftpboot.img
+vmlinux.aout
+piggyback
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index a3fb337..069d497 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15
-# Mon Jan  9 14:36:29 2006
+# Linux kernel version: 2.6.16-rc2
+# Tue Feb  7 17:47:18 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -23,7 +23,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -31,7 +30,7 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -155,6 +154,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -224,6 +224,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 CONFIG_VLAN_8021Q=m
@@ -420,8 +425,7 @@
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLOGICPTI is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set
+# CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -529,6 +533,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=m
 CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
@@ -738,6 +743,12 @@
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -755,6 +766,7 @@
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
@@ -1014,6 +1026,7 @@
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
@@ -1107,6 +1120,10 @@
 #
 
 #
+# EDAC - error detection and reporting (RAS)
+#
+
+#
 # Misc Linux/SPARC drivers
 #
 CONFIG_SUN_OPENPROMIO=m
@@ -1268,12 +1285,13 @@
 # Kernel hacking
 #
 CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 CONFIG_SCHEDSTATS=y
 # CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1281,6 +1299,7 @@
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_DCFLUSH is not set
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 7100029..a73553a 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -25,7 +25,7 @@
 
 #define curptr      g6
 
-#define NR_SYSCALLS 284      /* Each OS is different... */
+#define NR_SYSCALLS 300      /* Each OS is different... */
 
 	.text
 	.align		32
@@ -1416,7 +1416,6 @@
 	 add		%sp, PTREGS_OFF, %o0
 
 	.globl	sys_pipe, sys_sigpause, sys_nis_syscall
-	.globl	sys_sigsuspend, sys_rt_sigsuspend
 	.globl	sys_rt_sigreturn
 	.globl	sys_ptrace
 	.globl	sys_sigaltstack
@@ -1440,28 +1439,6 @@
 		 mov		%i6, %o2
 #endif
 		.align		32
-sys_sigsuspend:	add		%sp, PTREGS_OFF, %o0
-		call		do_sigsuspend
-		 add		%o7, 1f-.-4, %o7
-		nop
-sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
-		add		%sp, PTREGS_OFF, %o2
-		call		do_rt_sigsuspend
-		 add		%o7, 1f-.-4, %o7
-		nop
-#ifdef CONFIG_COMPAT
-	.globl	sys32_rt_sigsuspend
-sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
-		srl		%o0, 0, %o0
-		add		%sp, PTREGS_OFF, %o2
-		call		do_rt_sigsuspend32
-		 add		%o7, 1f-.-4, %o7
-#endif
-		/* NOTE: %o0 has a correct value already */
-sys_sigpause:	add		%sp, PTREGS_OFF, %o1
-		call		do_sigpause
-		 add		%o7, 1f-.-4, %o7
-		nop
 #ifdef CONFIG_COMPAT
 	.globl	sys32_sigreturn
 sys32_sigreturn:
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 1dc3650..059b0d0 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -164,6 +164,7 @@
 	panic("Reboot failed!");
 }
 
+#ifdef CONFIG_COMPAT
 static void show_regwindow32(struct pt_regs *regs)
 {
 	struct reg_window32 __user *rw;
@@ -189,6 +190,9 @@
 	       r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3],
 	       r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]);
 }
+#else
+#define show_regwindow32(regs)	do { } while (0)
+#endif
 
 static void show_regwindow(struct pt_regs *regs)
 {
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index 090dcca..b80eba0 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -53,14 +53,13 @@
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		ldx			[%g6 + TI_FLAGS], %l0
 
-1:		andcc			%l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+1:		andcc			%l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
 		be,pt			%xcc, __handle_user_windows_continue
 		 nop
-		clr			%o0
-		mov			%l5, %o2
-		mov			%l6, %o3
-		add			%sp, PTREGS_OFF, %o1
-		mov			%l0, %o4
+		mov			%l5, %o1
+		mov			%l6, %o2
+		add			%sp, PTREGS_OFF, %o0
+		mov			%l0, %o3
 
 		call			do_notify_resume
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
@@ -96,15 +95,14 @@
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		ldx			[%g6 + TI_FLAGS], %l0
-1:		andcc			%l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+1:		andcc			%l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
 
 		be,pt			%xcc, __handle_perfctrs_continue
 		 sethi			%hi(TSTATE_PEF), %o0
-		clr			%o0
-		mov			%l5, %o2
-		mov			%l6, %o3
-		add			%sp, PTREGS_OFF, %o1
-		mov			%l0, %o4
+		mov			%l5, %o1
+		mov			%l6, %o2
+		add			%sp, PTREGS_OFF, %o0
+		mov			%l0, %o3
 		call			do_notify_resume
 
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
@@ -129,11 +127,10 @@
 		ba,a,pt			%xcc, __handle_userfpu_continue
 
 __handle_signal:
-		clr			%o0
-		mov			%l5, %o2
-		mov			%l6, %o3
-		add			%sp, PTREGS_OFF, %o1
-		mov			%l0, %o4
+		mov			%l5, %o1
+		mov			%l6, %o2
+		add			%sp, PTREGS_OFF, %o0
+		mov			%l0, %o3
 		call			do_notify_resume
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
@@ -200,7 +197,7 @@
 		 andcc			%l1, %o0, %g0
 		andcc			%l0, _TIF_NEED_RESCHED, %g0
 		bne,pn			%xcc, __handle_preemption
-		 andcc			%l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+		 andcc			%l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
 		bne,pn			%xcc, __handle_signal
 __handle_signal_continue:
 		 ldub			[%g6 + TI_WSAVED], %o2
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 2507458..054461e 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -561,6 +561,8 @@
 		serial_console = 1;
 	} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
 		serial_console = 2;
+	} else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) {
+		serial_console = 3;
 	} else {
 		prom_printf("Inconsistent console: "
 			    "input %d, output %d\n",
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index 60f5dfa..ca11a4c 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -36,9 +36,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-static int do_signal(sigset_t *oldset, struct pt_regs * regs,
-		     unsigned long orig_o0, int ret_from_syscall);
-
 /* {set, get}context() needed for 64-bit SparcLinux userland. */
 asmlinkage void sparc64_set_context(struct pt_regs *regs)
 {
@@ -242,114 +239,29 @@
 /* Align macros */
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- * This is really tricky on the Sparc, watch out...
- */
-asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
+static long _sigpause_common(old_sigset_t set)
 {
-	sigset_t saveset;
-
-#ifdef CONFIG_SPARC32_COMPAT
-	if (test_thread_flag(TIF_32BIT)) {
-		extern asmlinkage void _sigpause32_common(compat_old_sigset_t,
-							  struct pt_regs *);
-		_sigpause32_common(set, regs);
-		return;
-	}
-#endif
 	set &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, set);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
-	
-	if (test_thread_flag(TIF_32BIT)) {
-		regs->tpc = (regs->tnpc & 0xffffffff);
-		regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
-	} else {
-		regs->tpc = regs->tnpc;
-		regs->tnpc += 4;
-	}
 
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal(&saveset, regs, 0, 0))
-			return;
-	}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
 }
 
-asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
+asmlinkage long sys_sigpause(unsigned int set)
 {
-	_sigpause_common(set, regs);
+	return _sigpause_common(set);
 }
 
-asmlinkage void do_sigsuspend(struct pt_regs *regs)
+asmlinkage long sys_sigsuspend(old_sigset_t set)
 {
-	_sigpause_common(regs->u_regs[UREG_I0], regs);
-}
-
-asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, struct pt_regs *regs)
-{
-	sigset_t oldset, set;
-        
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t)) {
-		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-		regs->u_regs[UREG_I0] = EINVAL;
-		return;
-	}
-	if (copy_from_user(&set, uset, sizeof(set))) {
-		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-		regs->u_regs[UREG_I0] = EFAULT;
-		return;
-	}
-                                                                
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	oldset = current->blocked;
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	
-	if (test_thread_flag(TIF_32BIT)) {
-		regs->tpc = (regs->tnpc & 0xffffffff);
-		regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
-	} else {
-		regs->tpc = regs->tnpc;
-		regs->tnpc += 4;
-	}
-
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal(&oldset, regs, 0, 0))
-			return;
-	}
+	return _sigpause_common(set);
 }
 
 static inline int
@@ -607,26 +519,29 @@
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-static int do_signal(sigset_t *oldset, struct pt_regs * regs,
-		     unsigned long orig_i0, int restart_syscall)
+static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall)
 {
 	siginfo_t info;
 	struct signal_deliver_cookie cookie;
 	struct k_sigaction ka;
 	int signr;
+	sigset_t *oldset;
 	
 	cookie.restart_syscall = restart_syscall;
 	cookie.orig_i0 = orig_i0;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 #ifdef CONFIG_SPARC32_COMPAT
 	if (test_thread_flag(TIF_32BIT)) {
-		extern int do_signal32(sigset_t *, struct pt_regs *,
-				       unsigned long, int);
-		return do_signal32(oldset, regs, orig_i0,
-				   cookie.restart_syscall);
+		extern void do_signal32(sigset_t *, struct pt_regs *,
+					unsigned long, int);
+		do_signal32(oldset, regs, orig_i0,
+			    cookie.restart_syscall);
+		return;
 	}
 #endif	
 
@@ -635,7 +550,15 @@
 		if (cookie.restart_syscall)
 			syscall_restart(orig_i0, regs, &ka.sa);
 		handle_signal(signr, &ka, &info, oldset, regs);
-		return 1;
+
+		/* a signal was successfully delivered; the saved
+		 * sigmask will have been stored in the signal frame,
+		 * and will be restored by sigreturn, so we can simply
+		 * clear the TIF_RESTORE_SIGMASK flag.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+		return;
 	}
 	if (cookie.restart_syscall &&
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -652,15 +575,21 @@
 		regs->tpc -= 4;
 		regs->tnpc -= 4;
 	}
-	return 0;
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back
+	 */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
 
-void do_notify_resume(sigset_t *oldset, struct pt_regs *regs,
-		      unsigned long orig_i0, int restart_syscall,
+void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall,
 		      unsigned long thread_info_flags)
 {
-	if (thread_info_flags & _TIF_SIGPENDING)
-		do_signal(oldset, regs, orig_i0, restart_syscall);
+	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+		do_signal(regs, orig_i0, restart_syscall);
 }
 
 void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 009a86e..708ba9b 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -32,9 +32,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-int do_signal32(sigset_t *oldset, struct pt_regs *regs,
-		unsigned long orig_o0, int ret_from_syscall);
-
 /* Signal frames: the original one (compatible with SunOS):
  *
  * Set up a signal frame... Make the stack look the way SunOS
@@ -226,102 +223,6 @@
 	return 0;
 }
 
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- * This is really tricky on the Sparc, watch out...
- */
-asmlinkage void _sigpause32_common(compat_old_sigset_t set, struct pt_regs *regs)
-{
-	sigset_t saveset;
-
-	set &= _BLOCKABLE;
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	siginitset(&current->blocked, set);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	
-	regs->tpc = regs->tnpc;
-	regs->tnpc += 4;
-	if (test_thread_flag(TIF_32BIT)) {
-		regs->tpc &= 0xffffffff;
-		regs->tnpc &= 0xffffffff;
-	}
-
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->tstate |= TSTATE_ICARRY;
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal32(&saveset, regs, 0, 0))
-			return;
-	}
-}
-
-asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *regs)
-{
-	sigset_t oldset, set;
-	compat_sigset_t set32;
-        
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (((compat_size_t)sigsetsize) != sizeof(sigset_t)) {
-		regs->tstate |= TSTATE_ICARRY;
-		regs->u_regs[UREG_I0] = EINVAL;
-		return;
-	}
-	if (copy_from_user(&set32, compat_ptr(uset), sizeof(set32))) {
-		regs->tstate |= TSTATE_ICARRY;
-		regs->u_regs[UREG_I0] = EFAULT;
-		return;
-	}
-	switch (_NSIG_WORDS) {
-	case 4: set.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
-	case 3: set.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
-	case 2: set.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
-	case 1: set.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
-	}
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	oldset = current->blocked;
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	
-	regs->tpc = regs->tnpc;
-	regs->tnpc += 4;
-	if (test_thread_flag(TIF_32BIT)) {
-		regs->tpc &= 0xffffffff;
-		regs->tnpc &= 0xffffffff;
-	}
-
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->tstate |= TSTATE_ICARRY;
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal32(&oldset, regs, 0, 0))
-			return;
-	}
-}
-
 static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
 {
 	unsigned long *fpregs = current_thread_info()->fpregs;
@@ -1362,8 +1263,8 @@
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-int do_signal32(sigset_t *oldset, struct pt_regs * regs,
-		unsigned long orig_i0, int restart_syscall)
+void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+		 unsigned long orig_i0, int restart_syscall)
 {
 	siginfo_t info;
 	struct signal_deliver_cookie cookie;
@@ -1380,7 +1281,15 @@
 			syscall_restart32(orig_i0, regs, &ka.sa);
 		handle_signal32(signr, &ka, &info, oldset,
 				regs, svr4_signal);
-		return 1;
+
+		/* a signal was successfully delivered; the saved
+		 * sigmask will have been stored in the signal frame,
+		 * and will be restored by sigreturn, so we can simply
+		 * clear the TIF_RESTORE_SIGMASK flag.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+		return;
 	}
 	if (cookie.restart_syscall &&
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -1397,7 +1306,14 @@
 		regs->tpc -= 4;
 		regs->tnpc -= 4;
 	}
-	return 0;
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back
+	 */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
 
 struct sigstack32 {
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index d177d7e..3c06bfb 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -69,7 +69,6 @@
 
 extern void die_if_kernel(char *str, struct pt_regs *regs);
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-void _sigpause_common (unsigned int set, struct pt_regs *);
 extern void *__bzero(void *, size_t);
 extern void *__memscan_zero(void *, size_t);
 extern void *__memscan_generic(void *, int, size_t);
@@ -236,9 +235,10 @@
 /* I/O device mmaping on Sparc64. */
 EXPORT_SYMBOL(io_remap_pfn_range);
 
+#ifdef CONFIG_COMPAT
 /* Solaris/SunOS binary compatibility */
-EXPORT_SYMBOL(_sigpause_common);
 EXPORT_SYMBOL(verify_compat_iovec);
+#endif
 
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(pte_alloc_one_kernel);
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index 9cd272a..60b5937 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -84,7 +84,6 @@
 SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1)
 SIGN1(sys32_mlockall, sys_mlockall, %o0)
 SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0)
-SIGN1(sys32_clock_settime, compat_sys_clock_settime, %o1)
 SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1)
 SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1)
 SIGN1(sys32_io_submit, compat_sys_io_submit, %o1)
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index d4b7a10..417727b 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -428,6 +428,27 @@
 	return error;
 }
 
+asmlinkage long compat_sys_fstatat64(unsigned int dfd, char __user *filename,
+		struct compat_stat64 __user * statbuf, int flag)
+{
+	struct kstat stat;
+	int error = -EINVAL;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat_fd(dfd, filename, &stat);
+	else
+		error = vfs_stat_fd(dfd, filename, &stat);
+
+	if (!error)
+		error = cp_compat_stat64(&stat, statbuf);
+
+out:
+	return error;
+}
+
 asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
 {
 	return sys_sysfs(option, arg1, arg2);
@@ -821,7 +842,7 @@
 			return -EFAULT;
 	}
 
-	return do_utimes(filename, (tvs ? &ktvs[0] : NULL));
+	return do_utimes(AT_FDCWD, filename, (tvs ? &ktvs[0] : NULL));
 }
 
 /* These are here just in case some old sparc32 binary calls it. */
@@ -1003,7 +1024,7 @@
 asmlinkage long sparc32_open(const char __user *filename,
 			     int flags, int mode)
 {
-	return do_sys_open(filename, flags, mode);
+	return do_sys_open(AT_FDCWD, filename, flags, mode);
 }
 
 extern unsigned long do_mremap(unsigned long addr,
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 98d24bc..c3adb7a 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -41,7 +41,7 @@
 /*90*/	.word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
 	.word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
-	.word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
+	.word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
 /*110*/	.word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
 	.word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/	.word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
@@ -71,12 +71,15 @@
 /*240*/	.word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
 	.word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
 /*250*/	.word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
-	.word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
+	.word sys_ni_syscall, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
 /*260*/	.word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
 	.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/	.word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
 	.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/	.word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
+/*280*/	.word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
+	.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
+/*285*/	.word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+	.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
 
 #endif /* CONFIG_COMPAT */
 
@@ -142,7 +145,10 @@
 	.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
 /*270*/	.word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 	.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/	.word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl
+/*280*/	.word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+	.word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
+/*285*/	.word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+	.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
     defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -239,12 +245,20 @@
 /*250*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
+	.word sunos_nosys
+/*260*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
+	.word sunos_nosys
+/*270*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
+	.word sunos_nosys
+/*280*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
+	.word sunos_nosys
+/*290*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys
diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c
index eae5db8..ac6d035 100644
--- a/arch/sparc64/prom/console.c
+++ b/arch/sparc64/prom/console.c
@@ -99,8 +99,12 @@
 	if (!strncmp(propb, "keyboard", 8))
 		return PROMDEV_ITTYA;
 
+	if (!strncmp (propb, "rsc", 3))
+		return PROMDEV_IRSC;
+
 	if (strncmp (propb, "tty", 3) || !propb[3])
 		return PROMDEV_I_UNK;
+
 	switch (propb[3]) {
 		case 'a': return PROMDEV_ITTYA;
 		case 'b': return PROMDEV_ITTYB;
@@ -136,8 +140,12 @@
 	if (!strncmp(propb, "screen", 6))
 		return PROMDEV_OTTYA;
 
+	if (!strncmp (propb, "rsc", 3))
+		return PROMDEV_ORSC;
+
 	if (strncmp (propb, "tty", 3) || !propb[3])
 		return PROMDEV_O_UNK;
+
 	switch (propb[3]) {
 		case 'a': return PROMDEV_OTTYA;
 		case 'b': return PROMDEV_OTTYB;
diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S
index 4b6ae58..eb314ed 100644
--- a/arch/sparc64/solaris/entry64.S
+++ b/arch/sparc64/solaris/entry64.S
@@ -180,6 +180,8 @@
 	 nop
 	call		sys_sigsuspend
 	 stx		%o0, [%sp + PTREGS_OFF + PT_V9_I0]
+	b,pt		%xcc, ret_from_solaris
+	 nop
 
 	.globl		solaris_getpid
 solaris_getpid:
diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S
index d25667e..7043ca1 100644
--- a/arch/sparc64/solaris/systbl.S
+++ b/arch/sparc64/solaris/systbl.S
@@ -283,32 +283,3 @@
 	.word solaris_unimplemented	/* 			253	*/
 	.word solaris_unimplemented	/* 			254	*/
 	.word solaris_unimplemented	/* 			255	*/
-	.word solaris_unimplemented	/* 			256	*/
-	.word solaris_unimplemented	/* 			257	*/
-	.word solaris_unimplemented	/* 			258	*/
-	.word solaris_unimplemented	/* 			259	*/
-	.word solaris_unimplemented	/* 			260	*/
-	.word solaris_unimplemented	/* 			261	*/
-	.word solaris_unimplemented	/* 			262	*/
-	.word solaris_unimplemented	/* 			263	*/
-	.word solaris_unimplemented	/* 			264	*/
-	.word solaris_unimplemented	/* 			265	*/
-	.word solaris_unimplemented	/* 			266	*/
-	.word solaris_unimplemented	/* 			267	*/
-	.word solaris_unimplemented	/* 			268	*/
-	.word solaris_unimplemented	/* 			269	*/
-	.word solaris_unimplemented	/* 			270	*/
-	.word solaris_unimplemented	/* 			271	*/
-	.word solaris_unimplemented	/* 			272	*/
-	.word solaris_unimplemented	/* 			273	*/
-	.word solaris_unimplemented	/* 			274	*/
-	.word solaris_unimplemented	/* 			275	*/
-	.word solaris_unimplemented	/* 			276	*/
-	.word solaris_unimplemented	/* 			277	*/
-	.word solaris_unimplemented	/* 			278	*/
-	.word solaris_unimplemented	/* 			279	*/
-	.word solaris_unimplemented	/* 			280	*/
-	.word solaris_unimplemented	/* 			281	*/
-	.word solaris_unimplemented	/* 			282	*/
-	.word solaris_unimplemented	/* 			283	*/
-
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 8ff3bcb..5982fe2 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -143,6 +143,7 @@
 
 config HPPFS
 	tristate "HoneyPot ProcFS (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
 	help
 	hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
 	entries to be overridden, removed, or fabricated from the host.
@@ -155,10 +156,6 @@
 	You only need this if you are setting up a UML honeypot.  Otherwise,
 	it is safe to say 'N' here.
 
-	If you are actively using it, please report any problems, since it's
-	getting fixed. In this moment, it is experimental on 2.6 (it works on
-	2.4).
-
 config MCONSOLE
 	bool "Management console"
 	default y
@@ -243,8 +240,16 @@
         Only change this if you are running nested UMLs.
 
 config HIGHMEM
-	bool "Highmem support"
-	depends on !64BIT
+	bool "Highmem support (EXPERIMENTAL)"
+	depends on !64BIT && EXPERIMENTAL
+	default n
+	help
+	This was used to allow UML to run with big amounts of memory.
+	Currently it is unstable, so if unsure say N.
+
+	To use big amounts of memory, it is recommended to disable TT mode (i.e.
+	CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) -
+	this should allow the guest to use up to 2.75G of memory.
 
 config KERNEL_STACK_ORDER
 	int "Kernel stack size order"
@@ -269,17 +274,13 @@
 
 source "init/Kconfig"
 
-source "net/Kconfig"
-
-source "drivers/base/Kconfig"
+source "drivers/block/Kconfig"
 
 source "arch/um/Kconfig.char"
 
-source "drivers/block/Kconfig"
+source "drivers/base/Kconfig"
 
-config NETDEVICES
-	bool
-	default NET
+source "net/Kconfig"
 
 source "arch/um/Kconfig.net"
 
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index c71b39a..ef79ed2 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -22,13 +22,17 @@
  	default 0x80000000 if HOST_2G_2G
 
 config 3_LEVEL_PGTABLES
-	bool "Three-level pagetables"
+	bool "Three-level pagetables (EXPERIMENTAL)"
 	default n
+	depends on EXPERIMENTAL
 	help
 	Three-level pagetables will let UML have more than 4G of physical
 	memory.  All the memory that can't be mapped directly will be treated
 	as high memory.
 
+	However, this it experimental on 32-bit architectures, so if unsure say
+	N (on x86-64 it's automatically enabled, instead, as it's safe there).
+
 config STUB_CODE
 	hex
 	default 0xbfffe000
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 45435ff..c58b657 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -32,7 +32,7 @@
 um-modes-$(CONFIG_MODE_SKAS) += skas
 
 MODE_INCLUDE	+= $(foreach mode,$(um-modes-y),\
-		   -I$(srctree)/$(ARCH_DIR)/kernel/$(mode)/include)
+		   -I$(srctree)/$(ARCH_DIR)/include/$(mode))
 
 MAKEFILES-INCL	+= $(foreach mode,$(um-modes-y),\
 		   $(srctree)/$(ARCH_DIR)/Makefile-$(mode))
@@ -47,13 +47,16 @@
 endif
 SYS_DIR		:= $(ARCH_DIR)/include/sysdep-$(SUBARCH)
 
-# -Dvmap=kernel_vmap affects everything, and prevents anything from
-# referencing the libpcap.o symbol so named.
+# -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so
+# named - it's a common symbol in libpcap, so we get a binary which crashes.
 #
-# Same things for in6addr_loopback - found in libc.
+# Same things for in6addr_loopback and mktime - found in libc. For these two we
+# only get link-time error, luckily.
+#
+# These apply to USER_CFLAGS to.
 
-CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
-	$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
+CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\"	\
+	$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap	\
 	-Din6addr_loopback=kernel_in6addr_loopback
 
 AFLAGS += $(ARCH_INCLUDE)
@@ -66,6 +69,7 @@
 # kernel_errno to separate them from the libc errno.  This allows -fno-common
 # in CFLAGS.  Otherwise, it would cause ld to complain about the two different
 # errnos.
+# These apply to kernelspace only.
 
 CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
 	-Dmktime=kernel_mktime
@@ -168,10 +172,13 @@
 	$(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
 endif
 
-$(ARCH_DIR)/include/sysdep:
+$(objtree)/$(ARCH_DIR)/include:
+	@echo '  MKDIR $@'
+	$(Q)mkdir -p $@
+
+$(ARCH_DIR)/include/sysdep: $(objtree)/$(ARCH_DIR)/include
 	@echo '  SYMLINK $@'
 ifneq ($(KBUILD_SRC),)
-	$(Q)mkdir -p $(ARCH_DIR)/include
 	$(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep
 else
 	$(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
@@ -214,7 +221,7 @@
 
 CLEAN_FILES += $(ARCH_DIR)/user-offsets.s
 
-$(ARCH_DIR)/include/kern_constants.h:
+$(ARCH_DIR)/include/kern_constants.h: $(objtree)/$(ARCH_DIR)/include
 	@echo '  SYMLINK $@'
 	$(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@
 
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index ab0d0b1..7218c75 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -403,7 +403,7 @@
 	return 0;
 }
 
-void free_one_chan(struct chan *chan, int delay_free_irq)
+static void free_one_chan(struct chan *chan, int delay_free_irq)
 {
 	list_del(&chan->list);
 
@@ -416,7 +416,7 @@
 	kfree(chan);
 }
 
-void free_chan(struct list_head *chans, int delay_free_irq)
+static void free_chan(struct list_head *chans, int delay_free_irq)
 {
 	struct list_head *ele, *next;
 	struct chan *chan;
@@ -497,7 +497,7 @@
 	struct chan_ops *ops;
 };
 
-struct chan_type chan_table[] = {
+static struct chan_type chan_table[] = {
 	{ "fd", &fd_ops },
 
 #ifdef CONFIG_NULL_CHAN
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 5d50d4a..2f880cb 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -9,6 +9,7 @@
 #include <termios.h>
 #include <string.h>
 #include <signal.h>
+#include <sched.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
@@ -73,7 +74,6 @@
 struct winch_data {
 	int pty_fd;
 	int pipe_fd;
-	int close_me;
 };
 
 static int winch_thread(void *arg)
@@ -84,7 +84,6 @@
 	int count, err;
 	char c = 1;
 
-	os_close_file(data->close_me);
 	pty_fd = data->pty_fd;
 	pipe_fd = data->pipe_fd;
 	count = os_write_file(pipe_fd, &c, sizeof(c));
@@ -153,15 +152,16 @@
 	}
 
 	data = ((struct winch_data) { .pty_fd 		= fd,
-				      .pipe_fd 		= fds[1],
-				      .close_me 	= fds[0] } );
-	err = run_helper_thread(winch_thread, &data, 0, &stack, 0);
+				      .pipe_fd 		= fds[1] } );
+	/* CLONE_FILES so this thread doesn't hold open files which are open
+	 * now, but later closed.  This is a problem with /dev/net/tun.
+	 */
+	err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0);
 	if(err < 0){
 		printk("fork of winch_thread failed - errno = %d\n", errno);
 		goto out_close;
 	}
 
-	os_close_file(fds[1]);
 	*fd_out = fds[0];
 	n = os_read_file(fds[0], &c, sizeof(c));
 	if(n != sizeof(c)){
@@ -169,13 +169,12 @@
 		printk("read failed, err = %d\n", -n);
 		printk("fd %d will not support SIGWINCH\n", fd);
                 err = -EINVAL;
-		goto out_close1;
+		goto out_close;
 	}
 	return err ;
 
  out_close:
 	os_close_file(fds[1]);
- out_close1:
 	os_close_file(fds[0]);
  out:
 	return err;
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index 30d285b..a61b7b4 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -18,7 +18,7 @@
 	char *ctl_sock;
 };
 
-void daemon_init(struct net_device *dev, void *data)
+static void daemon_init(struct net_device *dev, void *data)
 {
 	struct uml_net_private *pri;
 	struct daemon_data *dpri;
@@ -31,6 +31,10 @@
 	dpri->fd = -1;
 	dpri->control = -1;
 	dpri->dev = dev;
+	/* We will free this pointer. If it contains crap we're burned. */
+	dpri->ctl_addr = NULL;
+	dpri->data_addr = NULL;
+	dpri->local_addr = NULL;
 
 	printk("daemon backend (uml_switch version %d) - %s:%s", 
 	       SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock);
@@ -60,7 +64,7 @@
 	.write			= daemon_write,
 };
 
-int daemon_setup(char *str, char **mac_out, void *data)
+static int daemon_setup(char *str, char **mac_out, void *data)
 {
 	struct daemon_init *init = data;
 	char *remain;
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index 1bb085b2..c944265 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -158,10 +158,16 @@
 	struct daemon_data *pri = data;
 
 	os_close_file(pri->fd);
+	pri->fd = -1;
 	os_close_file(pri->control);
+	pri->control = -1;
+
 	kfree(pri->data_addr);
+	pri->data_addr = NULL;
 	kfree(pri->ctl_addr);
+	pri->ctl_addr = NULL;
 	kfree(pri->local_addr);
+	pri->local_addr = NULL;
 }
 
 int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 3296e86..c41f75e 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -11,6 +11,7 @@
 #include "user.h"
 #include "user_util.h"
 #include "chan_user.h"
+#include "os.h"
 
 struct fd_chan {
 	int fd;
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 46ceb25..6c2d4cc 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -714,7 +714,7 @@
 	struct tty_struct *tty;
 };
 
-irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct winch *winch = data;
 	struct tty_struct *tty;
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index 217438c..c9b078f 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -26,7 +26,7 @@
 	int ttl;
 };
 
-void mcast_init(struct net_device *dev, void *data)
+static void mcast_init(struct net_device *dev, void *data)
 {
 	struct uml_net_private *pri;
 	struct mcast_data *dpri;
@@ -40,7 +40,7 @@
 	dpri->dev = dev;
 
 	printk("mcast backend ");
-	printk("multicast adddress: %s:%u, TTL:%u ",
+	printk("multicast address: %s:%u, TTL:%u ",
 	       dpri->addr, dpri->port, dpri->ttl);
 
 	printk("\n");
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index e3d5765..54388d1 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -273,7 +273,7 @@
     config <dev> - Query the configuration of a device \n\
     remove <dev> - Remove a device from UML \n\
     sysrq <letter> - Performs the SysRq action controlled by the letter \n\
-    cad - invoke the Ctl-Alt-Del handler \n\
+    cad - invoke the Ctrl-Alt-Del handler \n\
     stop - pause the UML; it will do nothing until it receives a 'go' \n\
     go - continue the UML after a 'stop' \n\
     log <string> - make UML enter <string> into the kernel log\n\
@@ -327,7 +327,7 @@
 
 /* This list is populated by __initcall routines. */
 
-LIST_HEAD(mconsole_devices);
+static LIST_HEAD(mconsole_devices);
 
 void mconsole_register_dev(struct mc_device *new)
 {
@@ -561,6 +561,8 @@
 }
 #endif
 
+#ifdef CONFIG_MODE_SKAS
+
 static void stack_proc(void *arg)
 {
 	struct task_struct *from = current, *to = arg;
@@ -574,7 +576,7 @@
  *  Dumps a stacks registers to the linux console.
  *  Usage stack <pid>.
  */
-void do_stack(struct mc_request *req)
+static void do_stack_trace(struct mc_request *req)
 {
 	char *ptr = req->request.data;
 	int pid_requested= -1;
@@ -605,6 +607,7 @@
 	}
 	with_console(req, stack_proc, to);
 }
+#endif /* CONFIG_MODE_SKAS */
 
 void mconsole_stack(struct mc_request *req)
 {
@@ -613,7 +616,7 @@
 	 */
 	CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode",
 				   1, 0),
-		    do_stack(req));
+		    do_stack_trace(req));
 }
 
 /* Changed by mconsole_setup, which is __setup, and called before SMP is
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index fb1f9fb..8c7279b 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -68,6 +68,11 @@
 	return pkt_len;
 }
 
+static void uml_dev_close(void* dev)
+{
+	dev_close( (struct net_device *) dev);
+}
+
 irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
@@ -80,15 +85,21 @@
 	spin_lock(&lp->lock);
 	while((err = uml_net_rx(dev)) > 0) ;
 	if(err < 0) {
+		DECLARE_WORK(close_work, uml_dev_close, dev);
 		printk(KERN_ERR 
 		       "Device '%s' read returned %d, shutting it down\n", 
 		       dev->name, err);
-		dev_close(dev);
+		/* dev_close can't be called in interrupt context, and takes
+		 * again lp->lock.
+		 * And dev_close() can be safely called multiple times on the
+		 * same device, since it tests for (dev->flags & IFF_UP). So
+		 * there's no harm in delaying the device shutdown. */
+		schedule_work(&close_work);
 		goto out;
 	}
 	reactivate_fd(lp->fd, UM_ETH_IRQ);
 
- out:
+out:
 	spin_unlock(&lp->lock);
 	return(IRQ_HANDLED);
 }
@@ -120,9 +131,8 @@
 			     SA_INTERRUPT | SA_SHIRQ, dev->name, dev);
 	if(err != 0){
 		printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err);
-		if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
-		lp->fd = -1;
 		err = -ENETUNREACH;
+		goto out_close;
 	}
 
 	lp->tl.data = (unsigned long) &lp->user;
@@ -134,9 +144,19 @@
 	 */
 	while((err = uml_net_rx(dev)) > 0) ;
 
- out:
 	spin_unlock(&lp->lock);
-	return(err);
+
+	spin_lock(&opened_lock);
+	list_add(&lp->list, &opened);
+	spin_unlock(&opened_lock);
+
+	return 0;
+out_close:
+	if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
+	lp->fd = -1;
+out:
+	spin_unlock(&lp->lock);
+	return err;
 }
 
 static int uml_net_close(struct net_device *dev)
@@ -150,9 +170,13 @@
 	if(lp->close != NULL)
 		(*lp->close)(lp->fd, &lp->user);
 	lp->fd = -1;
-	list_del(&lp->list);
 
 	spin_unlock(&lp->lock);
+
+	spin_lock(&opened_lock);
+	list_del(&lp->list);
+	spin_unlock(&opened_lock);
+
 	return 0;
 }
 
@@ -317,6 +341,11 @@
 		return 1;
 	}
 
+	lp = dev->priv;
+	/* This points to the transport private data. It's still clear, but we
+	 * must memset it to 0 *now*. Let's help the drivers. */
+	memset(lp, 0, size);
+
 	/* sysfs register */
 	if (!driver_registered) {
 		platform_driver_register(&uml_net_driver);
@@ -358,7 +387,6 @@
 		free_netdev(dev);
 		return 1;
 	}
-	lp = dev->priv;
 
 	/* lp.user is the first four bytes of the transport data, which
 	 * has already been initialized.  This structure assignment will
@@ -395,11 +423,7 @@
 	if (device->have_mac)
 		set_ether_mac(dev, device->mac);
 
-	spin_lock(&opened_lock);
-	list_add(&lp->list, &opened);
-	spin_unlock(&opened_lock);
-
-	return(0);
+	return 0;
 }
 
 static struct uml_net *find_device(int n)
diff --git a/arch/um/drivers/slip_common.h b/arch/um/drivers/slip_common.h
index 2ae76d8..d574e0a 100644
--- a/arch/um/drivers/slip_common.h
+++ b/arch/um/drivers/slip_common.h
@@ -88,12 +88,13 @@
 	int esc;
 };
 
-#define SLIP_PROTO_INIT { \
-	.ibuf  	= { '\0' }, \
-	.obuf  	= { '\0' }, \
-        .more	= 0, \
-	.pos	= 0, \
-	.esc	= 0 \
+static inline void slip_proto_init(struct slip_proto * slip)
+{
+	memset(slip->ibuf, 0, sizeof(slip->ibuf));
+	memset(slip->obuf, 0, sizeof(slip->obuf));
+	slip->more = 0;
+	slip->pos = 0;
+	slip->esc = 0;
 }
 
 extern int slip_proto_read(int fd, void *buf, int len,
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c
index 9a6f5c8..a62f5ef 100644
--- a/arch/um/drivers/slip_kern.c
+++ b/arch/um/drivers/slip_kern.c
@@ -21,13 +21,14 @@
 
 	private = dev->priv;
 	spri = (struct slip_data *) private->user;
-	*spri = ((struct slip_data)
-		{ .name 	= { '\0' },
-		  .addr		= NULL,
-		  .gate_addr 	= init->gate_addr,
-		  .slave  	= -1,
-		  .slip		= SLIP_PROTO_INIT,
-		  .dev 		= dev });
+
+	memset(spri->name, 0, sizeof(spri->name));
+	spri->addr = NULL;
+	spri->gate_addr = init->gate_addr;
+	spri->slave = -1;
+	spri->dev = dev;
+
+	slip_proto_init(&spri->slip);
 
 	dev->init = NULL;
 	dev->header_cache_update = NULL;
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
index 9864d27..33d7982 100644
--- a/arch/um/drivers/slirp_kern.c
+++ b/arch/um/drivers/slirp_kern.c
@@ -21,12 +21,13 @@
 
 	private = dev->priv;
 	spri = (struct slirp_data *) private->user;
-	*spri = ((struct slirp_data)
-		{ .argw 	= init->argw,
-		  .pid  	= -1,
-		  .slave  	= -1,
-		  .slip		= SLIP_PROTO_INIT,
-		  .dev 		= dev });
+
+	spri->argw = init->argw;
+	spri->pid = -1;
+	spri->slave = -1;
+	spri->dev = dev;
+
+	slip_proto_init(&spri->slip);
 
 	dev->init = NULL;
 	dev->hard_header_len = 0;
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index a32ef55..a4d6415 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -33,7 +33,7 @@
 
 #define NR_PORTS 64
 
-void ssl_announce(char *dev_name, int dev)
+static void ssl_announce(char *dev_name, int dev)
 {
 	printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev,
 	       dev_name);
@@ -98,7 +98,7 @@
 	return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n);
 }
 
-int ssl_open(struct tty_struct *tty, struct file *filp)
+static int ssl_open(struct tty_struct *tty, struct file *filp)
 {
 	return line_open(serial_lines, tty);
 }
@@ -182,7 +182,7 @@
 	.index		= -1,
 };
 
-int ssl_init(void)
+static int ssl_init(void)
 {
 	char *new_title;
 
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 7696f8d..101efd2 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1103,31 +1103,33 @@
 	return(-EINVAL);
 }
 
-static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
+static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
 {
 	struct uml_stat buf1, buf2;
 	int err;
 
-	if(from_cmdline == NULL) return(1);
-	if(!strcmp(from_cmdline, from_cow)) return(1);
+	if(from_cmdline == NULL)
+		return 0;
+	if(!strcmp(from_cmdline, from_cow))
+		return 0;
 
 	err = os_stat_file(from_cmdline, &buf1);
 	if(err < 0){
 		printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
-		return(1);
+		return 0;
 	}
 	err = os_stat_file(from_cow, &buf2);
 	if(err < 0){
 		printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
-		return(1);
+		return 1;
 	}
 	if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
-		return(1);
+		return 0;
 
 	printk("Backing file mismatch - \"%s\" requested,\n"
 	       "\"%s\" specified in COW header of \"%s\"\n",
 	       from_cmdline, from_cow, cow);
-	return(0);
+	return 1;
 }
 
 static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
@@ -1189,18 +1191,19 @@
 	unsigned long long size;
 	__u32 version, align;
 	char *backing_file;
-	int fd, err, sectorsize, same, mode = 0644;
+	int fd, err, sectorsize, asked_switch, mode = 0644;
 
 	fd = os_open_file(file, *openflags, mode);
-	if(fd < 0){
-		if((fd == -ENOENT) && (create_cow_out != NULL))
+	if (fd < 0) {
+		if ((fd == -ENOENT) && (create_cow_out != NULL))
 			*create_cow_out = 1;
-                if(!openflags->w ||
-                   ((fd != -EROFS) && (fd != -EACCES))) return(fd);
+                if (!openflags->w ||
+                   ((fd != -EROFS) && (fd != -EACCES)))
+			return fd;
 		openflags->w = 0;
 		fd = os_open_file(file, *openflags, mode);
-		if(fd < 0)
-			return(fd);
+		if (fd < 0)
+			return fd;
         }
 
 	err = os_lock_file(fd, openflags->w);
@@ -1209,7 +1212,9 @@
 		goto out_close;
 	}
 
-	if(backing_file_out == NULL) return(fd);
+	/* Succesful return case! */
+	if(backing_file_out == NULL)
+		return(fd);
 
 	err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
 			      &size, &sectorsize, &align, bitmap_offset_out);
@@ -1218,34 +1223,34 @@
 		       "errno = %d\n", file, -err);
 		goto out_close;
 	}
-	if(err) return(fd);
+	if(err)
+		return(fd);
 
-	if(backing_file_out == NULL) return(fd);
+	asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
 
-	same = same_backing_files(*backing_file_out, backing_file, file);
-
-	if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
+	/* Allow switching only if no mismatch. */
+	if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) {
 		printk("Switching backing file to '%s'\n", *backing_file_out);
 		err = write_cow_header(file, fd, *backing_file_out,
 				       sectorsize, align, &size);
-		if(err){
+		if (err) {
 			printk("Switch failed, errno = %d\n", -err);
-			return(err);
+			goto out_close;
 		}
-	}
-	else {
+	} else {
 		*backing_file_out = backing_file;
 		err = backing_file_mismatch(*backing_file_out, size, mtime);
-		if(err) goto out_close;
+		if (err)
+			goto out_close;
 	}
 
 	cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
 		  bitmap_len_out, data_offset_out);
 
-        return(fd);
+        return fd;
  out_close:
 	os_close_file(fd);
-	return(err);
+	return err;
 }
 
 int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 8f4e46d..07176d9 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -31,8 +31,6 @@
 extern int jail;
 extern int nsyscalls;
 
-extern struct task_struct *idle_threads[NR_CPUS];
-
 #define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
 #define UML_ROUND_UP(addr) \
 	UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
@@ -120,8 +118,10 @@
 extern int is_syscall(unsigned long addr);
 extern void arch_switch(void);
 extern void free_irq(unsigned int, void *);
-extern int um_in_interrupt(void);
 extern int cpu(void);
+
+/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
+extern int __cant_sleep(void);
 extern void segv_handler(int sig, union uml_pt_regs *regs);
 extern void sigio_handler(int sig, union uml_pt_regs *regs);
 
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
new file mode 100644
index 0000000..018b381
--- /dev/null
+++ b/arch/um/include/longjmp.h
@@ -0,0 +1,19 @@
+#ifndef __UML_LONGJMP_H
+#define __UML_LONGJMP_H
+
+#include <setjmp.h>
+#include "os.h"
+
+#define UML_SIGLONGJMP(buf, val) do { \
+	longjmp(*buf, val);	\
+} while(0)
+
+#define UML_SIGSETJMP(buf, enable) ({ \
+	int n; \
+	enable = get_signals(); \
+	n = setjmp(*buf); \
+	if(n != 0) \
+		set_signals(enable); \
+	n; })
+
+#endif
diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h
index 2d88afd..e7539a8 100644
--- a/arch/um/include/mode_kern.h
+++ b/arch/um/include/mode_kern.h
@@ -9,22 +9,11 @@
 #include "linux/config.h"
 
 #ifdef CONFIG_MODE_TT
-#include "mode_kern-tt.h"
+#include "mode_kern_tt.h"
 #endif
 
 #ifdef CONFIG_MODE_SKAS
-#include "mode_kern-skas.h"
+#include "mode_kern_skas.h"
 #endif
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index dd72d66..eb1710b 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -11,6 +11,7 @@
 #include "../os/include/file.h"
 #include "sysdep/ptrace.h"
 #include "kern_util.h"
+#include "skas/mm_id.h"
 
 #define OS_TYPE_FILE 1 
 #define OS_TYPE_DIR 2 
@@ -190,11 +191,12 @@
 			     int r, int w, int x);
 extern int os_unmap_memory(void *addr, int len);
 extern void os_flush_stdout(void);
-extern unsigned long long os_usecs(void);
 
 /* tt.c
  * for tt mode only (will be deleted in future...)
  */
+extern void stop(void);
+extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
 extern int protect_memory(unsigned long addr, unsigned long len,
 			  int r, int w, int x, int must_succeed);
 extern void forward_pending_sigio(int target);
@@ -230,9 +232,63 @@
 extern void unblock_signals(void);
 extern int get_signals(void);
 extern int set_signals(int enable);
+extern void os_usr1_signal(int on);
 
 /* trap.c */
 extern void os_fill_handlinfo(struct kern_handlers h);
 extern void do_longjmp(void *p, int val);
 
+/* util.c */
+extern void stack_protections(unsigned long address);
+extern void task_protections(unsigned long address);
+extern int raw(int fd);
+extern void setup_machinename(char *machine_out);
+extern void setup_hostinfo(void);
+extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
+
+/* time.c */
+#define BILLION (1000 * 1000 * 1000)
+
+extern void switch_timers(int to_real);
+extern void idle_sleep(int secs);
+extern void enable_timer(void);
+extern void disable_timer(void);
+extern void user_time_init(void);
+extern void uml_idle_timer(void);
+extern unsigned long long os_nsecs(void);
+
+/* skas/mem.c */
+extern long run_syscall_stub(struct mm_id * mm_idp,
+			     int syscall, unsigned long *args, long expected,
+			     void **addr, int done);
+extern long syscall_stub_data(struct mm_id * mm_idp,
+			      unsigned long *data, int data_count,
+			      void **addr, void **stub_addr);
+extern int map(struct mm_id * mm_idp, unsigned long virt,
+	       unsigned long len, int r, int w, int x, int phys_fd,
+	       unsigned long long offset, int done, void **data);
+extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
+		 int done, void **data);
+extern int protect(struct mm_id * mm_idp, unsigned long addr,
+		   unsigned long len, int r, int w, int x, int done,
+		   void **data);
+
+/* skas/process.c */
+extern int is_skas_winch(int pid, int fd, void *data);
+extern int start_userspace(unsigned long stub_stack);
+extern int copy_context_skas0(unsigned long stack, int pid);
+extern void userspace(union uml_pt_regs *regs);
+extern void map_stub_pages(int fd, unsigned long code,
+			   unsigned long data, unsigned long stack);
+extern void new_thread(void *stack, void **switch_buf_ptr,
+			 void **fork_buf_ptr, void (*handler)(int));
+extern void thread_wait(void *sw, void *fb);
+extern void switch_threads(void *me, void *next);
+extern int start_idle_thread(void *stack, void *switch_buf_ptr,
+			     void **fork_buf_ptr);
+extern void initial_thread_cb_skas(void (*proc)(void *),
+				 void *arg);
+extern void halt_skas(void);
+extern void reboot_skas(void);
+
 #endif
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 4892e5f..83b688c 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -14,7 +14,7 @@
 extern void save_registers(int pid, union uml_pt_regs *regs);
 extern void restore_registers(int pid, union uml_pt_regs *regs);
 extern void init_registers(int pid);
-extern void get_safe_registers(unsigned long * regs);
+extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs);
 extern void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer);
 
 #endif
diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/include/skas/mm_id.h
similarity index 100%
rename from arch/um/kernel/skas/include/mm_id.h
rename to arch/um/include/skas/mm_id.h
diff --git a/arch/um/include/skas/mmu-skas.h b/arch/um/include/skas/mmu-skas.h
new file mode 100644
index 0000000..d8869a6
--- /dev/null
+++ b/arch/um/include/skas/mmu-skas.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_MMU_H
+#define __SKAS_MMU_H
+
+#include "linux/config.h"
+#include "mm_id.h"
+#include "asm/ldt.h"
+
+struct mmu_context_skas {
+	struct mm_id id;
+	unsigned long last_page_table;
+#ifdef CONFIG_3_LEVEL_PGTABLES
+	unsigned long last_pmd;
+#endif
+	uml_ldt_t ldt;
+};
+
+extern void switch_mm_skas(struct mm_id * mm_idp);
+
+#endif
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
new file mode 100644
index 0000000..260065c
--- /dev/null
+++ b/arch/um/include/skas/mode-skas.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_SKAS_H__
+#define __MODE_SKAS_H__
+
+#include <sysdep/ptrace.h>
+
+extern unsigned long exec_regs[];
+extern unsigned long exec_fp_regs[];
+extern unsigned long exec_fpx_regs[];
+extern int have_fpx_regs;
+
+extern void sig_handler_common_skas(int sig, void *sc_ptr);
+extern void kill_off_processes_skas(void);
+
+#endif
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/include/skas/mode_kern_skas.h
similarity index 76%
rename from arch/um/kernel/skas/include/mode_kern-skas.h
rename to arch/um/include/skas/mode_kern_skas.h
index c97a80d..63c5873 100644
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ b/arch/um/include/skas/mode_kern_skas.h
@@ -18,7 +18,6 @@
 			    unsigned long sp, unsigned long stack_top,
 			    struct task_struct *p, struct pt_regs *regs);
 extern void release_thread_skas(struct task_struct *task);
-extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
 extern void init_idle_skas(void);
 extern void flush_tlb_kernel_range_skas(unsigned long start,
 					unsigned long end);
@@ -39,14 +38,3 @@
 #define kmem_end_skas (host_task_size - 1024 * 1024)
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/include/proc_mm.h b/arch/um/include/skas/proc_mm.h
similarity index 60%
rename from arch/um/kernel/skas/include/proc_mm.h
rename to arch/um/include/skas/proc_mm.h
index cce61a6..9028092 100644
--- a/arch/um/kernel/skas/include/proc_mm.h
+++ b/arch/um/include/skas/proc_mm.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -22,13 +22,13 @@
 
 struct mm_munmap {
 	unsigned long addr;
-	unsigned long len;	
+	unsigned long len;
 };
 
 struct mm_mprotect {
 	unsigned long addr;
 	unsigned long len;
-        unsigned int prot;
+	unsigned int prot;
 };
 
 struct proc_mm_op {
@@ -42,14 +42,3 @@
 };
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
new file mode 100644
index 0000000..8635728
--- /dev/null
+++ b/arch/um/include/skas/skas.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_H
+#define __SKAS_H
+
+#include "mm_id.h"
+#include "sysdep/ptrace.h"
+
+extern int userspace_pid[];
+extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
+extern int skas_needs_stub;
+
+extern int user_thread(unsigned long stack, int flags);
+extern void new_thread_proc(void *stack, void (*handler)(int sig));
+extern void new_thread_handler(int sig);
+extern void handle_syscall(union uml_pt_regs *regs);
+extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
+extern int new_mm(unsigned long stack);
+extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
+extern long execute_syscall_skas(void *r);
+extern unsigned long current_stub_stack(void);
+
+#endif
diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/include/skas/stub-data.h
similarity index 100%
rename from arch/um/kernel/skas/include/stub-data.h
rename to arch/um/include/skas/stub-data.h
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/include/skas/uaccess-skas.h
similarity index 63%
rename from arch/um/kernel/skas/include/uaccess-skas.h
rename to arch/um/include/skas/uaccess-skas.h
index 64516c5..224a75f 100644
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ b/arch/um/include/skas/uaccess-skas.h
@@ -19,14 +19,3 @@
 extern int strnlen_user_skas(const void __user *str, int len);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
deleted file mode 100644
index 17d7ef2..0000000
--- a/arch/um/include/time_user.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TIME_USER_H__
-#define __TIME_USER_H__
-
-extern void timer(void);
-extern void switch_timers(int to_real);
-extern void idle_sleep(int secs);
-extern void enable_timer(void);
-extern void prepare_timer(void * ptr);
-extern void disable_timer(void);
-extern unsigned long time_lock(void);
-extern void time_unlock(unsigned long);
-extern void user_time_init(void);
-
-#endif
diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/include/tt/debug.h
similarity index 98%
rename from arch/um/kernel/tt/include/debug.h
rename to arch/um/include/tt/debug.h
index 7384354..9778fa8 100644
--- a/arch/um/kernel/tt/include/debug.h
+++ b/arch/um/include/tt/debug.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000, 2001, 2002  Jeff Dike (jdike@karaya.com) and
  * Lars Brinkhoff.
  * Licensed under the GPL
diff --git a/arch/um/include/tt/mmu-tt.h b/arch/um/include/tt/mmu-tt.h
new file mode 100644
index 0000000..572a78b2
--- /dev/null
+++ b/arch/um/include/tt/mmu-tt.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_MMU_H
+#define __TT_MMU_H
+
+struct mmu_context_tt {
+};
+
+#endif
diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h
new file mode 100644
index 0000000..2823cd5
--- /dev/null
+++ b/arch/um/include/tt/mode-tt.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_TT_H__
+#define __MODE_TT_H__
+
+#include "sysdep/ptrace.h"
+
+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
+
+extern int tracing_pid;
+
+extern int tracer(int (*init_proc)(void *), void *sp);
+extern void sig_handler_common_tt(int sig, void *sc);
+extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
+extern void reboot_tt(void);
+extern void halt_tt(void);
+extern int is_tracer_winch(int pid, int fd, void *data);
+extern void kill_off_processes_tt(void);
+
+#endif
diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h
new file mode 100644
index 0000000..efa0012
--- /dev/null
+++ b/arch/um/include/tt/mode_kern_tt.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_MODE_KERN_H__
+#define __TT_MODE_KERN_H__
+
+#include "linux/sched.h"
+#include "asm/page.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+
+extern void switch_to_tt(void *prev, void *next);
+extern void flush_thread_tt(void);
+extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
+			   unsigned long esp);
+extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
+			  unsigned long stack_top, struct task_struct *p,
+			  struct pt_regs *regs);
+extern void release_thread_tt(struct task_struct *task);
+extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
+extern void init_idle_tt(void);
+extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_vm_tt(void);
+extern void __flush_tlb_one_tt(unsigned long addr);
+extern void flush_tlb_range_tt(struct vm_area_struct *vma,
+			       unsigned long start, unsigned long end);
+extern void flush_tlb_mm_tt(struct mm_struct *mm);
+extern void force_flush_all_tt(void);
+extern long execute_syscall_tt(void *r);
+extern void before_mem_tt(unsigned long brk_start);
+extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
+				       unsigned long *task_size_out);
+extern int start_uml_tt(void);
+extern int external_pid_tt(struct task_struct *task);
+extern int thread_pid_tt(struct task_struct *task);
+
+#define kmem_end_tt (host_task_size - ABOVE_KMEM)
+
+#endif
diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/include/tt/tt.h
similarity index 73%
rename from arch/um/kernel/tt/include/tt.h
rename to arch/um/include/tt/tt.h
index c667b67..8085219 100644
--- a/arch/um/kernel/tt/include/tt.h
+++ b/arch/um/include/tt/tt.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -34,13 +34,3 @@
 
 #endif
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h
similarity index 80%
rename from arch/um/kernel/tt/include/uaccess-tt.h
rename to arch/um/include/tt/uaccess-tt.h
index b9bfe9c..b19645f 100644
--- a/arch/um/kernel/tt/include/uaccess-tt.h
+++ b/arch/um/include/tt/uaccess-tt.h
@@ -46,14 +46,3 @@
 extern int strnlen_user_tt(const void __user *str, int len);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 0f865ef..91b0ac4 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -18,6 +18,7 @@
 extern unsigned long strlcpy(char *, const char *, unsigned long);
 extern unsigned long strlcat(char *, const char *, unsigned long);
 extern void *um_vmalloc(int size);
+extern void *um_vmalloc_atomic(int size);
 extern void vfree(void *ptr);
 
 #endif
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index c1dbd77..a6f1f17 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -44,10 +44,6 @@
 extern int pty_output_sigio;
 extern int pty_close_sigio;
 
-extern void stop(void);
-extern void stack_protections(unsigned long address);
-extern void task_protections(unsigned long address);
-extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
 extern void *add_signal_handler(int sig, void (*handler)(int));
 extern int linux_main(int argc, char **argv);
 extern void set_cmdline(char *cmd);
@@ -55,8 +51,6 @@
 extern int get_pty(void);
 extern void *um_kmalloc(int size);
 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
-extern void setup_machinename(char *machine_out);
-extern void setup_hostinfo(void);
 extern void do_exec(int old_pid, int new_pid);
 extern void tracer_panic(char *msg, ...);
 extern int detach(int pid, int sig);
@@ -70,18 +64,6 @@
 extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
 extern int arch_fixup(unsigned long address, void *sc_ptr);
 extern void arch_init_thread(void);
-extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
 extern int raw(int fd);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 193cc2b..693018b 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -9,9 +9,8 @@
 obj-y = config.o exec_kern.o exitcode.o \
 	init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
 	process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
-	signal_kern.o smp.o syscall_kern.o sysrq.o time.o \
-	time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o \
-	user_util.o
+	signal_kern.o smp.o syscall_kern.o sysrq.o \
+	time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
@@ -24,7 +23,7 @@
 
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
-USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o
+USER_OBJS := $(user-objs-y) config.o tty_log.o
 
 include arch/um/scripts/Makefile.rules
 
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index efd222f..c264e1c 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -17,7 +17,6 @@
 #include "irq_user.h"
 #include "tlb.h"
 #include "os.h"
-#include "time_user.h"
 #include "choose-mode.h"
 #include "mode_kern.h"
 
@@ -34,7 +33,7 @@
 extern void log_exec(char **argv, void *tty);
 
 static long execve1(char *file, char __user * __user *argv,
-		    char *__user __user *env)
+		    char __user *__user *env)
 {
         long error;
 
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index f3b583a..544665e 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -265,7 +265,7 @@
 	highmem_len = highmem_pages * sizeof(struct page);
 
 	total_pages = phys_pages + iomem_pages + highmem_pages;
-	total_len = phys_len + iomem_pages + highmem_len;
+	total_len = phys_len + iomem_len + highmem_len;
 
 	if(kmalloc_ok){
 		map = kmalloc(total_len, GFP_KERNEL);
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 7f13b85..3113cab 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -39,7 +39,6 @@
 #include "init.h"
 #include "irq_user.h"
 #include "mem_user.h"
-#include "time_user.h"
 #include "tlb.h"
 #include "frame_kern.h"
 #include "sigcontext.h"
@@ -288,17 +287,27 @@
 
 void *um_kmalloc(int size)
 {
-	return(kmalloc(size, GFP_KERNEL));
+	return kmalloc(size, GFP_KERNEL);
 }
 
 void *um_kmalloc_atomic(int size)
 {
-	return(kmalloc(size, GFP_ATOMIC));
+	return kmalloc(size, GFP_ATOMIC);
 }
 
 void *um_vmalloc(int size)
 {
-	return(vmalloc(size));
+	return vmalloc(size);
+}
+
+void *um_vmalloc_atomic(int size)
+{
+	return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
+}
+
+int __cant_sleep(void) {
+	return in_atomic() || irqs_disabled() || in_interrupt();
+	/* Is in_interrupt() really needed? */
 }
 
 unsigned long get_fault_addr(void)
@@ -370,11 +379,6 @@
 	return(0);
 }
 
-int um_in_interrupt(void)
-{
-	return(in_interrupt());
-}
-
 int cpu(void)
 {
 	return(current_thread->cpu);
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 6f1a3a2..3ef73bf 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -5,6 +5,7 @@
 
 #include "linux/module.h"
 #include "linux/sched.h"
+#include "asm/smp.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 62e5cfd..f7b18e1 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -337,70 +337,103 @@
 	return(err);
 }
 
-static int setup_initial_poll(int fd)
+static struct pollfd* setup_initial_poll(int fd)
 {
 	struct pollfd *p;
 
-	p = um_kmalloc_atomic(sizeof(struct pollfd));
-	if(p == NULL){
+	p = um_kmalloc(sizeof(struct pollfd));
+	if (p == NULL) {
 		printk("setup_initial_poll : failed to allocate poll\n");
-		return(-1);
+		return NULL;
 	}
 	*p = ((struct pollfd) { .fd  	= fd,
 				.events 	= POLLIN,
 				.revents 	= 0 });
-	current_poll = ((struct pollfds) { .poll 	= p,
-					   .used 	= 1,
-					   .size 	= 1 });
-	return(0);
+	return p;
 }
 
 void write_sigio_workaround(void)
 {
 	unsigned long stack;
+	struct pollfd *p;
 	int err;
+	int l_write_sigio_fds[2];
+	int l_sigio_private[2];
+	int l_write_sigio_pid;
 
+	/* We call this *tons* of times - and most ones we must just fail. */
 	sigio_lock();
-	if(write_sigio_pid != -1)
-		goto out;
+	l_write_sigio_pid = write_sigio_pid;
+	sigio_unlock();
 
-	err = os_pipe(write_sigio_fds, 1, 1);
+	if (l_write_sigio_pid != -1)
+		return;
+
+	err = os_pipe(l_write_sigio_fds, 1, 1);
 	if(err < 0){
 		printk("write_sigio_workaround - os_pipe 1 failed, "
 		       "err = %d\n", -err);
-		goto out;
+		return;
 	}
-	err = os_pipe(sigio_private, 1, 1);
+	err = os_pipe(l_sigio_private, 1, 1);
 	if(err < 0){
-		printk("write_sigio_workaround - os_pipe 2 failed, "
+		printk("write_sigio_workaround - os_pipe 1 failed, "
 		       "err = %d\n", -err);
 		goto out_close1;
 	}
-	if(setup_initial_poll(sigio_private[1]))
+
+	p = setup_initial_poll(l_sigio_private[1]);
+	if(!p)
 		goto out_close2;
 
-	write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, 
+	sigio_lock();
+
+	/* Did we race? Don't try to optimize this, please, it's not so likely
+	 * to happen, and no more than once at the boot. */
+	if(write_sigio_pid != -1)
+		goto out_unlock;
+
+	write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
 					    CLONE_FILES | CLONE_VM, &stack, 0);
 
-	if(write_sigio_pid < 0) goto out_close2;
+	if (write_sigio_pid < 0)
+		goto out_clear;
 
-	if(write_sigio_irq(write_sigio_fds[0])) 
+	if (write_sigio_irq(l_write_sigio_fds[0]))
 		goto out_kill;
 
- out:
+	/* Success, finally. */
+	memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
+	memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
+
+	current_poll = ((struct pollfds) { .poll 	= p,
+					   .used 	= 1,
+					   .size 	= 1 });
+
 	sigio_unlock();
 	return;
 
  out_kill:
-	os_kill_process(write_sigio_pid, 1);
+	l_write_sigio_pid = write_sigio_pid;
 	write_sigio_pid = -1;
- out_close2:
-	os_close_file(sigio_private[0]);
-	os_close_file(sigio_private[1]);
- out_close1:
-	os_close_file(write_sigio_fds[0]);
-	os_close_file(write_sigio_fds[1]);
 	sigio_unlock();
+	/* Going to call waitpid, avoid holding the lock. */
+	os_kill_process(l_write_sigio_pid, 1);
+	goto out_free;
+
+ out_clear:
+	write_sigio_pid = -1;
+ out_unlock:
+	sigio_unlock();
+ out_free:
+	kfree(p);
+ out_close2:
+	os_close_file(l_sigio_private[0]);
+	os_close_file(l_sigio_private[1]);
+ out_close1:
+	os_close_file(l_write_sigio_fds[0]);
+	os_close_file(l_write_sigio_fds[1]);
+	return;
 }
 
 int read_sigio_fd(int fd)
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 7b0e0e8..da17b75 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -99,31 +99,46 @@
 	return err;
 }
 
-static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
+static int kern_do_signal(struct pt_regs *regs)
 {
 	struct k_sigaction ka_copy;
 	siginfo_t info;
+	sigset_t *oldset;
 	int sig, handled_sig = 0;
 
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
+		oldset = &current->blocked;
+
 	while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
 		handled_sig = 1;
 		/* Whee!  Actually deliver the signal.  */
-		if(!handle_signal(regs, sig, &ka_copy, &info, oldset))
+		if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
+			/* a signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
 			break;
+		}
 	}
 
 	/* Did we come from a system call? */
 	if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
 		/* Restart the system call - no handlers present */
-		if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND ||
-		   PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS ||
-		   PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){
+		switch(PT_REGS_SYSCALL_RET(regs)){
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
 			PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
 			PT_REGS_RESTART_SYSCALL(regs);
-		}
-		else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){
+			break;
+		case -ERESTART_RESTARTBLOCK:
 			PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
 			PT_REGS_RESTART_SYSCALL(regs);
+			break;
  		}
 	}
 
@@ -137,12 +152,19 @@
 	if(current->ptrace & PT_DTRACE)
 		current->thread.singlestep_syscall =
 			is_syscall(PT_REGS_IP(&current->thread.regs));
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back */
+	if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 	return(handled_sig);
 }
 
 int do_signal(void)
 {
-	return(kern_do_signal(&current->thread.regs, &current->blocked));
+	return(kern_do_signal(&current->thread.regs));
 }
 
 /*
@@ -150,63 +172,20 @@
  */
 long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-	sigset_t saveset;
-
 	mask &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if(kern_do_signal(&current->thread.regs, &saveset))
-			return(-EINTR);
-	}
-}
-
-long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
-{
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (kern_do_signal(&current->thread.regs, &saveset))
-			return(-EINTR);
-	}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
 }
 
 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
 {
 	return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 7a9fc16..57181a9 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -1,12 +1,12 @@
-# 
+#
 # Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
 # Licensed under the GPL
 #
 
-obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
+obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
 	syscall.o tlb.o uaccess.o
 
-USER_OBJS := process.o clone.o
+USER_OBJS := clone.o
 
 include arch/um/scripts/Makefile.rules
 
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
deleted file mode 100644
index 44110c5..0000000
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SKAS_MMU_H
-#define __SKAS_MMU_H
-
-#include "linux/config.h"
-#include "mm_id.h"
-#include "asm/ldt.h"
-
-struct mmu_context_skas {
-	struct mm_id id;
-        unsigned long last_page_table;
-#ifdef CONFIG_3_LEVEL_PGTABLES
-        unsigned long last_pmd;
-#endif
-	uml_ldt_t ldt;
-};
-
-extern void switch_mm_skas(struct mm_id * mm_idp);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h
deleted file mode 100644
index bcd26a6..0000000
--- a/arch/um/kernel/skas/include/mode-skas.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_SKAS_H__
-#define __MODE_SKAS_H__
-
-#include <sysdep/ptrace.h>
-
-extern unsigned long exec_regs[];
-extern unsigned long exec_fp_regs[];
-extern unsigned long exec_fpx_regs[];
-extern int have_fpx_regs;
-
-extern void sig_handler_common_skas(int sig, void *sc_ptr);
-extern void halt_skas(void);
-extern void reboot_skas(void);
-extern void kill_off_processes_skas(void);
-extern int is_skas_winch(int pid, int fd, void *data);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
deleted file mode 100644
index 01d489d..0000000
--- a/arch/um/kernel/skas/include/skas.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SKAS_H
-#define __SKAS_H
-
-#include "mm_id.h"
-#include "sysdep/ptrace.h"
-
-extern int userspace_pid[];
-extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
-extern int skas_needs_stub;
-
-extern void switch_threads(void *me, void *next);
-extern void thread_wait(void *sw, void *fb);
-extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
-                       void (*handler)(int));
-extern int start_idle_thread(void *stack, void *switch_buf_ptr, 
-			     void **fork_buf_ptr);
-extern int user_thread(unsigned long stack, int flags);
-extern void userspace(union uml_pt_regs *regs);
-extern void new_thread_proc(void *stack, void (*handler)(int sig));
-extern void new_thread_handler(int sig);
-extern void handle_syscall(union uml_pt_regs *regs);
-extern int map(struct mm_id * mm_idp, unsigned long virt,
-	       unsigned long len, int r, int w, int x, int phys_fd,
-	       unsigned long long offset, int done, void **data);
-extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
-		 int done, void **data);
-extern int protect(struct mm_id * mm_idp, unsigned long addr,
-		   unsigned long len, int r, int w, int x, int done,
-		   void **data);
-extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
-extern int new_mm(int from, unsigned long stack);
-extern int start_userspace(unsigned long stub_stack);
-extern int copy_context_skas0(unsigned long stack, int pid);
-extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
-extern long execute_syscall_skas(void *r);
-extern unsigned long current_stub_stack(void);
-extern long run_syscall_stub(struct mm_id * mm_idp,
-                             int syscall, unsigned long *args, long expected,
-                             void **addr, int done);
-extern long syscall_stub_data(struct mm_id * mm_idp,
-                              unsigned long *data, int data_count,
-                              void **addr, void **stub_addr);
-
-#endif
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
deleted file mode 100644
index 1d89640..0000000
--- a/arch/um/kernel/skas/mem_user.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/wait.h>
-#include <asm/page.h>
-#include <asm/unistd.h>
-#include "mem_user.h"
-#include "mem.h"
-#include "skas.h"
-#include "user.h"
-#include "os.h"
-#include "proc_mm.h"
-#include "ptrace_user.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "task.h"
-#include "registers.h"
-#include "uml-config.h"
-#include "sysdep/ptrace.h"
-#include "sysdep/stub.h"
-
-extern unsigned long batch_syscall_stub, __syscall_stub_start;
-
-extern void wait_stub_done(int pid, int sig, char * fname);
-
-static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
-					      unsigned long *stack)
-{
-	if(stack == NULL){
-		stack = (unsigned long *) mm_idp->stack + 2;
-		*stack = 0;
-	}
-	return stack;
-}
-
-extern int proc_mm;
-
-int single_count = 0;
-int multi_count = 0;
-int multi_op_count = 0;
-
-static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
-{
-	unsigned long regs[MAX_REG_NR];
-	unsigned long *data;
-	unsigned long *syscall;
-	long ret, offset;
-        int n, pid = mm_idp->u.pid;
-
-	if(proc_mm)
-#warning Need to look up userspace_pid by cpu
-		pid = userspace_pid[0];
-
-	multi_count++;
-
-        get_safe_registers(regs);
-        regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
-		((unsigned long) &batch_syscall_stub -
-                 (unsigned long) &__syscall_stub_start);
-	n = ptrace_setregs(pid, regs);
-	if(n < 0)
-		panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
-		      n);
-
-	wait_stub_done(pid, 0, "do_syscall_stub");
-
-	/* When the stub stops, we find the following values on the
-	 * beginning of the stack:
-	 * (long )return_value
-	 * (long )offset to failed sycall-data (0, if no error)
-	 */
-	ret = *((unsigned long *) mm_idp->stack);
-	offset = *((unsigned long *) mm_idp->stack + 1);
-	if (offset) {
-		data = (unsigned long *)(mm_idp->stack +
-					 offset - UML_CONFIG_STUB_DATA);
-		syscall = (unsigned long *)((unsigned long)data + data[0]);
-		printk("do_syscall_stub: syscall %ld failed, return value = "
-		       "0x%lx, expected return value = 0x%lx\n",
-		       syscall[0], ret, syscall[7]);
-		printk("    syscall parameters: "
-		       "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
-		       syscall[1], syscall[2], syscall[3],
-		       syscall[4], syscall[5], syscall[6]);
-		for(n = 1; n < data[0]/sizeof(long); n++) {
-			if(n == 1)
-				printk("    additional syscall data:");
-			if(n % 4 == 1)
-				printk("\n      ");
-			printk("  0x%lx", data[n]);
-		}
-		if(n > 1)
-			printk("\n");
-	}
-	else ret = 0;
-
-	*addr = check_init_stack(mm_idp, NULL);
-
-	return ret;
-}
-
-long run_syscall_stub(struct mm_id * mm_idp, int syscall,
-		      unsigned long *args, long expected, void **addr,
- 		      int done)
-{
- 	unsigned long *stack = check_init_stack(mm_idp, *addr);
-
-	if(done && *addr == NULL)
-		single_count++;
-
- 	*stack += sizeof(long);
-	stack += *stack / sizeof(long);
-
-        *stack++ = syscall;
-        *stack++ = args[0];
-        *stack++ = args[1];
-        *stack++ = args[2];
-        *stack++ = args[3];
-        *stack++ = args[4];
-        *stack++ = args[5];
-	*stack++ = expected;
-        *stack = 0;
-        multi_op_count++;
-
-        if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
-		     PAGE_SIZE - 10 * sizeof(long))){
-		*addr = stack;
-                return 0;
-        }
-
-	return do_syscall_stub(mm_idp, addr);
-}
-
-long syscall_stub_data(struct mm_id * mm_idp,
-		       unsigned long *data, int data_count,
-		       void **addr, void **stub_addr)
-{
-	unsigned long *stack;
-	int ret = 0;
-
-	/* If *addr still is uninitialized, it *must* contain NULL.
-	 * Thus in this case do_syscall_stub correctly won't be called.
-	 */
-	if((((unsigned long) *addr) & ~PAGE_MASK) >=
-	   PAGE_SIZE - (10 + data_count) * sizeof(long)) {
-		ret = do_syscall_stub(mm_idp, addr);
- 		/* in case of error, don't overwrite data on stack */
-		if(ret)
-			return ret;
-	}
-
-	stack = check_init_stack(mm_idp, *addr);
-	*addr = stack;
-
-	*stack = data_count * sizeof(long);
-
-	memcpy(stack + 1, data, data_count * sizeof(long));
-
-	*stub_addr = (void *)(((unsigned long)(stack + 1) & ~PAGE_MASK) +
-			      UML_CONFIG_STUB_DATA);
-
-	return 0;
-}
-
-int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
-	int r, int w, int x, int phys_fd, unsigned long long offset,
-	int done, void **data)
-{
-        int prot, ret;
-
-        prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
-                (x ? PROT_EXEC : 0);
-
-        if(proc_mm){
-                struct proc_mm_op map;
-                int fd = mm_idp->u.mm_fd;
-
-                map = ((struct proc_mm_op) { .op	= MM_MMAP,
-                                             .u		=
-                                             { .mmap	=
-                                               { .addr	= virt,
-                                                 .len	= len,
-                                                 .prot	= prot,
-                                                 .flags	= MAP_SHARED |
-                                                 MAP_FIXED,
-                                                 .fd	= phys_fd,
-                                                 .offset= offset
-                                               } } } );
-		ret = os_write_file(fd, &map, sizeof(map));
-		if(ret != sizeof(map))
-			printk("map : /proc/mm map failed, err = %d\n", -ret);
-		else ret = 0;
-        }
-        else {
-                unsigned long args[] = { virt, len, prot,
-                                         MAP_SHARED | MAP_FIXED, phys_fd,
-                                         MMAP_OFFSET(offset) };
-
-		ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
-				       data, done);
-        }
-
-	return ret;
-}
-
-int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
-	  void **data)
-{
-        int ret;
-
-        if(proc_mm){
-                struct proc_mm_op unmap;
-                int fd = mm_idp->u.mm_fd;
-
-                unmap = ((struct proc_mm_op) { .op	= MM_MUNMAP,
-                                               .u	=
-                                               { .munmap	=
-                                                 { .addr	=
-                                                   (unsigned long) addr,
-                                                   .len		= len } } } );
-		ret = os_write_file(fd, &unmap, sizeof(unmap));
-		if(ret != sizeof(unmap))
-			printk("unmap - proc_mm write returned %d\n", ret);
-		else ret = 0;
-        }
-        else {
-                unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
-                                         0 };
-
-		ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
-				       data, done);
-                if(ret < 0)
-                        printk("munmap stub failed, errno = %d\n", ret);
-        }
-
-        return ret;
-}
-
-int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
-	    int r, int w, int x, int done, void **data)
-{
-        struct proc_mm_op protect;
-        int prot, ret;
-
-        prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
-                (x ? PROT_EXEC : 0);
-
-        if(proc_mm){
-                int fd = mm_idp->u.mm_fd;
-                protect = ((struct proc_mm_op) { .op	= MM_MPROTECT,
-                                                 .u	=
-                                                 { .mprotect	=
-                                                   { .addr	=
-                                                     (unsigned long) addr,
-                                                     .len	= len,
-                                                     .prot	= prot } } } );
-
-                ret = os_write_file(fd, &protect, sizeof(protect));
-                if(ret != sizeof(protect))
-                        printk("protect failed, err = %d", -ret);
-                else ret = 0;
-        }
-        else {
-                unsigned long args[] = { addr, len, prot, 0, 0, 0 };
-
-                ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
-                                       data, done);
-        }
-
-        return ret;
-}
-
-void before_mem_skas(unsigned long unused)
-{
-}
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 677871f..c5c9885 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -78,7 +78,7 @@
  	struct mmu_context_skas *from_mm = NULL;
 	struct mmu_context_skas *to_mm = &mm->context.skas;
 	unsigned long stack = 0;
-	int from_fd, ret = -ENOMEM;
+	int ret = -ENOMEM;
 
 	if(skas_needs_stub){
 		stack = get_zeroed_page(GFP_KERNEL);
@@ -108,11 +108,7 @@
 		from_mm = &current->mm->context.skas;
 
 	if(proc_mm){
-		if(from_mm)
-			from_fd = from_mm->id.u.mm_fd;
-		else from_fd = -1;
-
-		ret = new_mm(from_fd, stack);
+		ret = new_mm(stack);
 		if(ret < 0){
 			printk("init_new_context_skas - new_mm failed, "
 			       "errno = %d\n", ret);
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index dc41c6d..3f70a2e 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -13,14 +13,12 @@
 #include "asm/uaccess.h"
 #include "asm/atomic.h"
 #include "kern_util.h"
-#include "time_user.h"
 #include "skas.h"
 #include "os.h"
 #include "user_util.h"
 #include "tlb.h"
 #include "kern.h"
 #include "mode.h"
-#include "proc_mm.h"
 #include "registers.h"
 
 void switch_to_skas(void *prev, void *next)
@@ -34,7 +32,7 @@
 	if(current->pid == 0)
 		switch_timers(0);
 
-	switch_threads(&from->thread.mode.skas.switch_buf, 
+	switch_threads(&from->thread.mode.skas.switch_buf,
 		       to->thread.mode.skas.switch_buf);
 
 	if(current->pid == 0)
@@ -50,8 +48,8 @@
 
 	fn = current->thread.request.u.thread.proc;
 	arg = current->thread.request.u.thread.arg;
-	change_sig(SIGUSR1, 1);
-	thread_wait(&current->thread.mode.skas.switch_buf, 
+	os_usr1_signal(1);
+	thread_wait(&current->thread.mode.skas.switch_buf,
 		    current->thread.mode.skas.fork_buf);
 
 	if(current->thread.prev_sched != NULL)
@@ -82,8 +80,8 @@
 
 void fork_handler(int sig)
 {
-        change_sig(SIGUSR1, 1);
- 	thread_wait(&current->thread.mode.skas.switch_buf, 
+	os_usr1_signal(1);
+	thread_wait(&current->thread.mode.skas.switch_buf,
 		    current->thread.mode.skas.fork_buf);
   	
 	force_flush_all();
@@ -93,13 +91,13 @@
 	schedule_tail(current->thread.prev_sched);
 	current->thread.prev_sched = NULL;
 
-	/* Handle any immediate reschedules or signals */
+/* Handle any immediate reschedules or signals */
 	interrupt_end();
 	userspace(&current->thread.regs.regs);
 }
 
 int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
-		     unsigned long stack_top, struct task_struct * p, 
+		     unsigned long stack_top, struct task_struct * p,
 		     struct pt_regs *regs)
 {
   	void (*handler)(int);
@@ -123,27 +121,14 @@
 	return(0);
 }
 
-extern void map_stub_pages(int fd, unsigned long code,
-			   unsigned long data, unsigned long stack);
-int new_mm(int from, unsigned long stack)
+int new_mm(unsigned long stack)
 {
-	struct proc_mm_op copy;
-	int n, fd;
+	int fd;
 
 	fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
 	if(fd < 0)
 		return(fd);
 
-	if(from != -1){
-		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
-					      .u 	=
-					      { .copy_segments	= from } } );
-		n = os_write_file(fd, &copy, sizeof(copy));
-		if(n != sizeof(copy))
-			printk("new_mm : /proc/mm copy_segments failed, "
-			       "err = %d\n", -n);
-	}
-
 	if(skas_needs_stub)
 		map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
 
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index a5a4752..5992c32 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -13,7 +13,7 @@
 #include "asm/pgtable.h"
 #include "asm/uaccess.h"
 #include "kern_util.h"
-#include "user_util.h"
+#include "os.h"
 
 extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
 			     pte_t *pte_out);
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 1429c13..1731d90 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -25,12 +25,12 @@
 	syscall_record[index].syscall = syscall;
 	syscall_record[index].pid = current_pid();
 	syscall_record[index].result = 0xdeadbeef;
-	syscall_record[index].start = os_usecs();
+	syscall_record[index].start = os_nsecs();
 	return(index);
 }
 
 void record_syscall_end(int index, long result)
 {
 	syscall_record[index].result = result;
-	syscall_record[index].end = os_usecs();
+	syscall_record[index].end = os_nsecs();
 }
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 020ca79..3c7626c 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -13,12 +13,12 @@
 #include "linux/interrupt.h"
 #include "linux/init.h"
 #include "linux/delay.h"
+#include "linux/hrtimer.h"
 #include "asm/irq.h"
 #include "asm/param.h"
 #include "asm/current.h"
 #include "kern_util.h"
 #include "user_util.h"
-#include "time_user.h"
 #include "mode.h"
 #include "os.h"
 
@@ -39,7 +39,7 @@
 int timer_irq_inited = 0;
 
 static int first_tick;
-static unsigned long long prev_usecs;
+static unsigned long long prev_nsecs;
 #ifdef CONFIG_UML_REAL_TIME_CLOCK
 static long long delta;   		/* Deviation per interval */
 #endif
@@ -58,23 +58,23 @@
 	if(first_tick){
 #ifdef CONFIG_UML_REAL_TIME_CLOCK
 		/* We've had 1 tick */
-		unsigned long long usecs = os_usecs();
+		unsigned long long nsecs = os_nsecs();
 
-		delta += usecs - prev_usecs;
-		prev_usecs = usecs;
+		delta += nsecs - prev_nsecs;
+		prev_nsecs = nsecs;
 
 		/* Protect against the host clock being set backwards */
 		if(delta < 0)
 			delta = 0;
 
-		ticks += (delta * HZ) / MILLION;
-		delta -= (ticks * MILLION) / HZ;
+		ticks += (delta * HZ) / BILLION;
+		delta -= (ticks * BILLION) / HZ;
 #else
 		ticks = 1;
 #endif
 	}
 	else {
-		prev_usecs = os_usecs();
+		prev_nsecs = os_nsecs();
 		first_tick = 1;
 	}
 
@@ -84,49 +84,102 @@
 	}
 }
 
-void boot_timer_handler(int sig)
+void do_boot_timer_handler(struct sigcontext * sc)
 {
 	struct pt_regs regs;
 
-	CHOOSE_MODE((void) 
-		    (UPT_SC(&regs.regs) = (struct sigcontext *) (&sig + 1)),
+	CHOOSE_MODE((void) (UPT_SC(&regs.regs) = sc),
 		    (void) (regs.regs.skas.is_user = 0));
 	do_timer(&regs);
 }
 
+static DEFINE_SPINLOCK(timer_spinlock);
+
+static unsigned long long local_offset = 0;
+
+static inline unsigned long long get_time(void)
+{
+	unsigned long long nsecs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&timer_spinlock, flags);
+	nsecs = os_nsecs();
+	nsecs += local_offset;
+	spin_unlock_irqrestore(&timer_spinlock, flags);
+
+	return nsecs;
+}
+
 irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
 {
+	unsigned long long nsecs;
 	unsigned long flags;
 
 	do_timer(regs);
+
 	write_seqlock_irqsave(&xtime_lock, flags);
-	timer();
+	nsecs = get_time() + local_offset;
+	xtime.tv_sec = nsecs / NSEC_PER_SEC;
+	xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
 	write_sequnlock_irqrestore(&xtime_lock, flags);
+
 	return(IRQ_HANDLED);
 }
 
 long um_time(int __user *tloc)
 {
-	struct timeval now;
+	long ret = get_time() / NSEC_PER_SEC;
 
-	do_gettimeofday(&now);
-	if (tloc) {
- 		if (put_user(now.tv_sec, tloc))
-			now.tv_sec = -EFAULT;
-	}
-	return now.tv_sec;
+	if((tloc != NULL) && put_user(ret, tloc))
+		return -EFAULT;
+
+	return ret;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long long nsecs = get_time();
+
+	tv->tv_sec = nsecs / NSEC_PER_SEC;
+	/* Careful about calculations here - this was originally done as
+	 * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
+	 * which gave bogus (> 1000000) values.  Dunno why, suspect gcc
+	 * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
+	 * problem that I missed.
+	 */
+	nsecs -= tv->tv_sec * NSEC_PER_SEC;
+	tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
+}
+
+static inline void set_time(unsigned long long nsecs)
+{
+	unsigned long long now;
+	unsigned long flags;
+
+	spin_lock_irqsave(&timer_spinlock, flags);
+	now = os_nsecs();
+	local_offset = nsecs - now;
+	spin_unlock_irqrestore(&timer_spinlock, flags);
+
+	clock_was_set();
 }
 
 long um_stime(int __user *tptr)
 {
 	int value;
-	struct timespec new;
 
 	if (get_user(value, tptr))
                 return -EFAULT;
-	new.tv_sec = value;
-	new.tv_nsec = 0;
-	do_settimeofday(&new);
+
+	set_time((unsigned long long) value * NSEC_PER_SEC);
+
+	return 0;
+}
+
+int do_settimeofday(struct timespec *tv)
+{
+	set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
+
 	return 0;
 }
 
@@ -134,29 +187,15 @@
 {
 	local_irq_disable();
 	irq_enter();
-	update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)),
-					 (regs)->skas.is_user));
+	update_process_times(CHOOSE_MODE(
+	                     (UPT_SC(regs) && user_context(UPT_SP(regs))),
+			     (regs)->skas.is_user));
 	irq_exit();
 	local_irq_enable();
 	if(current_thread->cpu == 0)
 		timer_irq(regs);
 }
 
-static DEFINE_SPINLOCK(timer_spinlock);
-
-unsigned long time_lock(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&timer_spinlock, flags);
-	return(flags);
-}
-
-void time_unlock(unsigned long flags)
-{
-	spin_unlock_irqrestore(&timer_spinlock, flags);
-}
-
 int __init timer_init(void)
 {
 	int err;
@@ -171,14 +210,3 @@
 }
 
 __initcall(timer_init);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index 8f40e48..5c1e4cc 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -13,7 +13,6 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "irq_user.h"
-#include "time_user.h"
 #include "mem_user.h"
 #include "os.h"
 #include "tlb.h"
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 37e22d7..786e4ed 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -20,6 +20,7 @@
 #include "user_util.h"
 #include "tt.h"
 #include "sysdep/thread.h"
+#include "os.h"
 
 extern int debugger_pid;
 extern int debugger_fd;
diff --git a/arch/um/kernel/tt/include/mmu-tt.h b/arch/um/kernel/tt/include/mmu-tt.h
deleted file mode 100644
index 0440510..0000000
--- a/arch/um/kernel/tt/include/mmu-tt.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TT_MMU_H
-#define __TT_MMU_H
-
-struct mmu_context_tt {
-};
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index 6253530..295c1ac 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -18,7 +18,6 @@
 #include "os.h"
 #include "kern.h"
 #include "sigcontext.h"
-#include "time_user.h"
 #include "mem_user.h"
 #include "tlb.h"
 #include "mode.h"
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
index 528a5fc..0377442 100644
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -20,6 +20,7 @@
 #include "kern_util.h"
 #include "ptrace_user.h"
 #include "tt.h"
+#include "os.h"
 
 long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
 		  long arg3, long arg4, pid_t child, int *ret)
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index a5f0e01..99f1783 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -15,6 +15,7 @@
 #include "ptrace_user.h"
 #include "user_util.h"
 #include "user.h"
+#include "os.h"
 
 int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, 
 		long *arg5)
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
index 3d29c90..3fda9a0 100644
--- a/arch/um/kernel/tt/syscall_kern.c
+++ b/arch/um/kernel/tt/syscall_kern.c
@@ -23,16 +23,20 @@
 	int syscall;
 #ifdef CONFIG_SYSCALL_DEBUG
 	int index;
-  	index = record_syscall_start(syscall);
 #endif
 	sc = UPT_SC(&regs->regs);
 	SC_START_SYSCALL(sc);
 
+	syscall = UPT_SYSCALL_NR(&regs->regs);
+
+#ifdef CONFIG_SYSCALL_DEBUG
+	index = record_syscall_start(syscall);
+#endif
+
 	syscall_trace(&regs->regs, 0);
 
 	current->thread.nsyscalls++;
 	nsyscalls++;
-	syscall = UPT_SYSCALL_NR(&regs->regs);
 
 	if((syscall >= NR_syscalls) || (syscall < 0))
 		result = -ENOSYS;
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index a414c52..b5d9d64 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -18,7 +18,7 @@
 {
 	struct sigcontext *sc = sc_ptr;
 	struct tt_regs save_regs, *r;
-	int save_errno = errno, is_user;
+	int save_errno = errno, is_user = 0;
 	void (*handler)(int, union uml_pt_regs *);
 
 	/* This is done because to allow SIGSEGV to be delivered inside a SEGV
@@ -35,7 +35,8 @@
                 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
         }
 	save_regs = *r;
-	is_user = user_context(SC_SP(sc));
+	if (sc)
+		is_user = user_context(SC_SP(sc));
 	r->sc = sc;
 	if(sig != SIGUSR2) 
 		r->syscall = -1;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index e2d3ca4..27cdf91 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -193,6 +193,24 @@
 "        root=/dev/ubd5\n\n"
 );
 
+#ifndef CONFIG_MODE_TT
+
+static int __init no_skas_debug_setup(char *line, int *add)
+{
+	printf("'debug' is not necessary to gdb UML in skas mode - run \n");
+	printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n");
+	printf("doesn't work as expected\n");
+
+	return 0;
+}
+
+__uml_setup("debug", no_skas_debug_setup,
+"debug\n"
+"    this flag is not needed to run gdb on UML in skas mode\n\n"
+);
+
+#endif
+
 #ifdef CONFIG_SMP
 static int __init uml_ncpus_setup(char *line, int *add)
 {
diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
deleted file mode 100644
index 4c23116..0000000
--- a/arch/um/kernel/user_util.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/* 
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#include <setjmp.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/utsname.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include "asm/types.h"
-#include <ctype.h>
-#include <signal.h>
-#include <wait.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <sched.h>
-#include <termios.h>
-#include <string.h>
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "mem_user.h"
-#include "init.h"
-#include "ptrace_user.h"
-#include "uml-config.h"
-
-void stop(void)
-{
-	while(1) sleep(1000000);
-}
-
-void stack_protections(unsigned long address)
-{
-	int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-
-        if(mprotect((void *) address, page_size(), prot) < 0)
-		panic("protecting stack failed, errno = %d", errno);
-}
-
-void task_protections(unsigned long address)
-{
-	unsigned long guard = address + page_size();
-	unsigned long stack = guard + page_size();
-	int prot = 0, pages;
-
-#ifdef notdef
-	if(mprotect((void *) stack, page_size(), prot) < 0)
-		panic("protecting guard page failed, errno = %d", errno);
-#endif
-	pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
-	prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-	if(mprotect((void *) stack, pages * page_size(), prot) < 0)
-		panic("protecting stack failed, errno = %d", errno);
-}
-
-int wait_for_stop(int pid, int sig, int cont_type, void *relay)
-{
-	sigset_t *relay_signals = relay;
-	int status, ret;
-
-	while(1){
-		CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
-		if((ret < 0) ||
-		   !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
-			if(ret < 0){
-				printk("wait failed, errno = %d\n",
-				       errno);
-			}
-			else if(WIFEXITED(status)) 
-				printk("process %d exited with status %d\n",
-				       pid, WEXITSTATUS(status));
-			else if(WIFSIGNALED(status))
-				printk("process %d exited with signal %d\n",
-				       pid, WTERMSIG(status));
-			else if((WSTOPSIG(status) == SIGVTALRM) ||
-				(WSTOPSIG(status) == SIGALRM) ||
-				(WSTOPSIG(status) == SIGIO) ||
-				(WSTOPSIG(status) == SIGPROF) ||
-				(WSTOPSIG(status) == SIGCHLD) ||
-				(WSTOPSIG(status) == SIGWINCH) ||
-				(WSTOPSIG(status) == SIGINT)){
-				ptrace(cont_type, pid, 0, WSTOPSIG(status));
-				continue;
-			}
-			else if((relay_signals != NULL) &&
-				sigismember(relay_signals, WSTOPSIG(status))){
-				ptrace(cont_type, pid, 0, WSTOPSIG(status));
-				continue;
-			}
-			else printk("process %d stopped with signal %d\n",
-				    pid, WSTOPSIG(status));
-			panic("wait_for_stop failed to wait for %d to stop "
-			      "with %d\n", pid, sig);
-		}
-		return(status);
-	}
-}
-
-int raw(int fd)
-{
-	struct termios tt;
-	int err;
-
-	CATCH_EINTR(err = tcgetattr(fd, &tt));
-	if(err < 0)
-		return -errno;
-
-	cfmakeraw(&tt);
-
- 	CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
-	if(err < 0)
-		return -errno;
-
-	/* XXX tcsetattr could have applied only some changes
-	 * (and cfmakeraw() is a set of changes) */
-	return(0);
-}
-
-void setup_machinename(char *machine_out)
-{
-	struct utsname host;
-
-	uname(&host);
-#if defined(UML_CONFIG_UML_X86) && !defined(UML_CONFIG_64BIT)
-	if (!strcmp(host.machine, "x86_64")) {
-		strcpy(machine_out, "i686");
-		return;
-	}
-#endif
-	strcpy(machine_out, host.machine);
-}
-
-char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1];
-
-void setup_hostinfo(void)
-{
-	struct utsname host;
-
-	uname(&host);
-	sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename,
-		host.release, host.version, host.machine);
-}
-
-int setjmp_wrapper(void (*proc)(void *, void *), ...)
-{
-        va_list args;
-	sigjmp_buf buf;
-	int n;
-
-	n = sigsetjmp(buf, 1);
-	if(n == 0){
-		va_start(args, proc);
-		(*proc)(&buf, &args);
-	}
-	va_end(args);
-	return(n);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 40c7d6b..08a4e62 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -5,12 +5,12 @@
 
 obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
 	start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \
-	drivers/ sys-$(SUBARCH)/
+	util.o drivers/ sys-$(SUBARCH)/
 
 obj-$(CONFIG_MODE_SKAS) += skas/
 
 USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
-	start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o
+	start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o util.o
 
 elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
 CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 5294533..87c3aa0 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -122,6 +122,7 @@
 		return(-EINVAL);
 	}
 	*fd_out = ((int *) CMSG_DATA(cmsg))[0];
+	os_set_exec_close(*fd_out, 1);
 	return(0);
 }
 
@@ -137,7 +138,8 @@
 		return(err);
 
 	if(pri->fixed_config){
-		pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0);
+		pri->fd = os_open_file("/dev/net/tun",
+				       of_cloexec(of_rdwr(OPENFLAGS())), 0);
 		if(pri->fd < 0){
 			printk("Failed to open /dev/net/tun, err = %d\n",
 			       -pri->fd);
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 36cc847..6490a4f 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -60,7 +60,7 @@
 
 	if((stack_out != NULL) && (*stack_out != 0))
 		stack = *stack_out;
-	else stack = alloc_stack(0, um_in_interrupt());
+	else stack = alloc_stack(0, __cant_sleep());
 	if(stack == 0)
 		return(-ENOMEM);
 
@@ -124,7 +124,7 @@
 	unsigned long stack, sp;
 	int pid, status, err;
 
-	stack = alloc_stack(stack_order, um_in_interrupt());
+	stack = alloc_stack(stack_order, __cant_sleep());
 	if(stack == 0) return(-ENOMEM);
 
 	sp = stack + (page_size() << stack_order) - sizeof(void *);
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 172c847..2878e89 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -16,7 +16,6 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "mem_user.h"
-#include "time_user.h"
 #include "irq_user.h"
 #include "user.h"
 #include "init.h"
@@ -82,20 +81,8 @@
 int main(int argc, char **argv, char **envp)
 {
 	char **new_argv;
-	sigset_t mask;
 	int ret, i, err;
 
-	/* Enable all signals except SIGIO - in some environments, we can
-	 * enter with some signals blocked
-	 */
-
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGIO);
-	if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
-		perror("sigprocmask");
-		exit(1);
-	}
-
 #ifdef UML_CONFIG_CMDLINE_ON_HOST
 	/* Allocate memory for thread command lines */
 	if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 39815c6..7f5e2da 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -18,6 +18,7 @@
 #include "process.h"
 #include "irq_user.h"
 #include "kern_util.h"
+#include "longjmp.h"
 
 #define ARBITRARY_ADDR -1
 #define FAILURE_PID    -1
@@ -205,24 +206,13 @@
 
 int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
 {
-       sigjmp_buf buf;
-       int n;
+	sigjmp_buf buf;
+	int n, enable;
 
-       *jmp_ptr = &buf;
-       n = sigsetjmp(buf, 1);
-       if(n != 0)
-               return(n);
-       (*fn)(arg);
-       return(0);
+	*jmp_ptr = &buf;
+	n = UML_SIGSETJMP(&buf, enable);
+	if(n != 0)
+		return(n);
+	(*fn)(arg);
+	return(0);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index c1f46a0f..f11b312 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -12,32 +12,66 @@
 #include <string.h>
 #include <sys/mman.h>
 #include "user_util.h"
-#include "kern_util.h"
 #include "user.h"
 #include "signal_kern.h"
 #include "sysdep/sigcontext.h"
 #include "sysdep/signal.h"
 #include "sigcontext.h"
-#include "time_user.h"
 #include "mode.h"
+#include "os.h"
+
+/* These are the asynchronous signals.  SIGVTALRM and SIGARLM are handled
+ * together under SIGVTALRM_BIT.  SIGPROF is excluded because we want to
+ * be able to profile all of UML, not just the non-critical sections.  If
+ * profiling is not thread-safe, then that is not my problem.  We can disable
+ * profiling when SMP is enabled in that case.
+ */
+#define SIGIO_BIT 0
+#define SIGIO_MASK (1 << SIGIO_BIT)
+
+#define SIGVTALRM_BIT 1
+#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
+
+#define SIGALRM_BIT 2
+#define SIGALRM_MASK (1 << SIGALRM_BIT)
+
+static int signals_enabled = 1;
+static int pending = 0;
 
 void sig_handler(ARCH_SIGHDLR_PARAM)
 {
 	struct sigcontext *sc;
+	int enabled;
+
+	/* Must be the first thing that this handler does - x86_64 stores
+	 * the sigcontext in %rdx, and we need to save it before it has a
+	 * chance to get trashed.
+	 */
 
 	ARCH_GET_SIGCONTEXT(sc, sig);
+
+	enabled = signals_enabled;
+	if(!enabled && (sig == SIGIO)){
+		pending |= SIGIO_MASK;
+		return;
+	}
+
+	block_signals();
+
 	CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
 			 sig, sc);
+
+	set_signals(enabled);
 }
 
 extern int timer_irq_inited;
 
-void alarm_handler(ARCH_SIGHDLR_PARAM)
+static void real_alarm_handler(int sig, struct sigcontext *sc)
 {
-	struct sigcontext *sc;
-
-	ARCH_GET_SIGCONTEXT(sc, sig);
-	if(!timer_irq_inited) return;
+	if(!timer_irq_inited){
+		signals_enabled = 1;
+		return;
+	}
 
 	if(sig == SIGALRM)
 		switch_timers(0);
@@ -47,6 +81,52 @@
 
 	if(sig == SIGALRM)
 		switch_timers(1);
+
+}
+
+void alarm_handler(ARCH_SIGHDLR_PARAM)
+{
+	struct sigcontext *sc;
+	int enabled;
+
+	ARCH_GET_SIGCONTEXT(sc, sig);
+
+	enabled = signals_enabled;
+	if(!signals_enabled){
+		if(sig == SIGVTALRM)
+			pending |= SIGVTALRM_MASK;
+		else pending |= SIGALRM_MASK;
+
+		return;
+	}
+
+	block_signals();
+
+	real_alarm_handler(sig, sc);
+	set_signals(enabled);
+}
+
+extern void do_boot_timer_handler(struct sigcontext * sc);
+
+void boot_timer_handler(ARCH_SIGHDLR_PARAM)
+{
+	struct sigcontext *sc;
+	int enabled;
+
+	ARCH_GET_SIGCONTEXT(sc, sig);
+
+	enabled = signals_enabled;
+	if(!enabled){
+		if(sig == SIGVTALRM)
+			pending |= SIGVTALRM_MASK;
+		else pending |= SIGALRM_MASK;
+		return;
+	}
+
+	block_signals();
+
+	do_boot_timer_handler(sc);
+	set_signals(enabled);
 }
 
 void set_sigstack(void *sig_stack, int size)
@@ -73,6 +153,7 @@
 {
 	struct sigaction action;
 	va_list ap;
+	sigset_t sig_mask;
 	int mask;
 
 	va_start(ap, flags);
@@ -85,7 +166,12 @@
 	action.sa_flags = flags;
 	action.sa_restorer = NULL;
 	if(sigaction(sig, &action, NULL) < 0)
-		panic("sigaction failed");
+		panic("sigaction failed - errno = %d\n", errno);
+
+	sigemptyset(&sig_mask);
+	sigaddset(&sig_mask, sig);
+	if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
+		panic("sigprocmask failed - errno = %d\n", errno);
 }
 
 int change_sig(int signal, int on)
@@ -98,89 +184,77 @@
 	return(!sigismember(&old, signal));
 }
 
-/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
- * disable profiling; it's safe because the profiling code does not interact
- * with the kernel code at all.*/
-
-static void change_signals(int type)
-{
-	sigset_t mask;
-
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGVTALRM);
-	sigaddset(&mask, SIGALRM);
-	sigaddset(&mask, SIGIO);
-	if(sigprocmask(type, &mask, NULL) < 0)
-		panic("Failed to change signal mask - errno = %d", errno);
-}
-
 void block_signals(void)
 {
-	change_signals(SIG_BLOCK);
+	signals_enabled = 0;
 }
 
 void unblock_signals(void)
 {
-	change_signals(SIG_UNBLOCK);
-}
+	int save_pending;
 
-/* These are the asynchronous signals.  SIGVTALRM and SIGARLM are handled
- * together under SIGVTALRM_BIT.  SIGPROF is excluded because we want to
- * be able to profile all of UML, not just the non-critical sections.  If
- * profiling is not thread-safe, then that is not my problem.  We can disable
- * profiling when SMP is enabled in that case.
- */
-#define SIGIO_BIT 0
-#define SIGVTALRM_BIT 1
+	if(signals_enabled == 1)
+		return;
 
-static int enable_mask(sigset_t *mask)
-{
-	int sigs;
+	/* We loop because the IRQ handler returns with interrupts off.  So,
+	 * interrupts may have arrived and we need to re-enable them and
+	 * recheck pending.
+	 */
+	while(1){
+		/* Save and reset save_pending after enabling signals.  This
+		 * way, pending won't be changed while we're reading it.
+		 */
+		signals_enabled = 1;
 
-	sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
-	sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
-	sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
-	return(sigs);
+		save_pending = pending;
+		if(save_pending == 0)
+			return;
+
+		pending = 0;
+
+		/* We have pending interrupts, so disable signals, as the
+		 * handlers expect them off when they are called.  They will
+		 * be enabled again above.
+		 */
+
+		signals_enabled = 0;
+
+		/* Deal with SIGIO first because the alarm handler might
+		 * schedule, leaving the pending SIGIO stranded until we come
+		 * back here.
+		 */
+		if(save_pending & SIGIO_MASK)
+			CHOOSE_MODE_PROC(sig_handler_common_tt,
+					 sig_handler_common_skas, SIGIO, NULL);
+
+		if(save_pending & SIGALRM_MASK)
+			real_alarm_handler(SIGALRM, NULL);
+
+		if(save_pending & SIGVTALRM_MASK)
+			real_alarm_handler(SIGVTALRM, NULL);
+	}
 }
 
 int get_signals(void)
 {
-	sigset_t mask;
-
-	if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
-		panic("Failed to get signal mask");
-	return(enable_mask(&mask));
+	return signals_enabled;
 }
 
 int set_signals(int enable)
 {
-	sigset_t mask;
 	int ret;
+	if(signals_enabled == enable)
+		return enable;
 
-	sigemptyset(&mask);
-	if(enable & (1 << SIGIO_BIT))
-		sigaddset(&mask, SIGIO);
-	if(enable & (1 << SIGVTALRM_BIT)){
-		sigaddset(&mask, SIGVTALRM);
-		sigaddset(&mask, SIGALRM);
-	}
+	ret = signals_enabled;
+	if(enable)
+		unblock_signals();
+	else block_signals();
 
-	/* This is safe - sigprocmask is guaranteed to copy locally the
-	 * value of new_set, do his work and then, at the end, write to
-	 * old_set.
-	 */
-	if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
-		panic("Failed to enable signals");
-	ret = enable_mask(&mask);
-	sigemptyset(&mask);
-	if((enable & (1 << SIGIO_BIT)) == 0)
-		sigaddset(&mask, SIGIO);
-	if((enable & (1 << SIGVTALRM_BIT)) == 0){
-		sigaddset(&mask, SIGVTALRM);
-		sigaddset(&mask, SIGALRM);
-	}
-	if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
-		panic("Failed to block signals");
+	return ret;
+}
 
-	return(ret);
+void os_usr1_signal(int on)
+{
+	change_sig(SIGUSR1, on);
 }
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
index eab5386..5fd8d4d 100644
--- a/arch/um/os-Linux/skas/Makefile
+++ b/arch/um/os-Linux/skas/Makefile
@@ -3,8 +3,8 @@
 # Licensed under the GPL
 #
 
-obj-y := trap.o
+obj-y := mem.o process.o trap.o
 
-USER_OBJS := trap.o
+USER_OBJS := mem.o process.o trap.o
 
 include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
new file mode 100644
index 0000000..fbb080c
--- /dev/null
+++ b/arch/um/os-Linux/skas/mem.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <asm/page.h>
+#include <asm/unistd.h>
+#include "mem_user.h"
+#include "mem.h"
+#include "skas.h"
+#include "user.h"
+#include "os.h"
+#include "proc_mm.h"
+#include "ptrace_user.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "task.h"
+#include "registers.h"
+#include "uml-config.h"
+#include "sysdep/ptrace.h"
+#include "sysdep/stub.h"
+
+extern unsigned long batch_syscall_stub, __syscall_stub_start;
+
+extern void wait_stub_done(int pid, int sig, char * fname);
+
+static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
+					      unsigned long *stack)
+{
+	if(stack == NULL) {
+		stack = (unsigned long *) mm_idp->stack + 2;
+		*stack = 0;
+	}
+	return stack;
+}
+
+extern int proc_mm;
+
+int single_count = 0;
+int multi_count = 0;
+int multi_op_count = 0;
+
+static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
+{
+	unsigned long regs[MAX_REG_NR];
+	int n;
+	long ret, offset;
+	unsigned long * data;
+	unsigned long * syscall;
+	int pid = mm_idp->u.pid;
+
+	if(proc_mm)
+#warning Need to look up userspace_pid by cpu
+		pid = userspace_pid[0];
+
+	multi_count++;
+
+	get_safe_registers(regs, NULL);
+	regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+		((unsigned long) &batch_syscall_stub -
+		 (unsigned long) &__syscall_stub_start);
+
+	n = ptrace_setregs(pid, regs);
+	if(n < 0)
+		panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
+		      n);
+
+	wait_stub_done(pid, 0, "do_syscall_stub");
+
+	/* When the stub stops, we find the following values on the
+	 * beginning of the stack:
+	 * (long )return_value
+	 * (long )offset to failed sycall-data (0, if no error)
+	 */
+	ret = *((unsigned long *) mm_idp->stack);
+	offset = *((unsigned long *) mm_idp->stack + 1);
+	if (offset) {
+		data = (unsigned long *)(mm_idp->stack +
+					 offset - UML_CONFIG_STUB_DATA);
+		printk("do_syscall_stub : ret = %d, offset = %d, "
+		       "data = 0x%x\n", ret, offset, data);
+		syscall = (unsigned long *)((unsigned long)data + data[0]);
+		printk("do_syscall_stub: syscall %ld failed, return value = "
+		       "0x%lx, expected return value = 0x%lx\n",
+		       syscall[0], ret, syscall[7]);
+		printk("    syscall parameters: "
+		       "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+		       syscall[1], syscall[2], syscall[3],
+		       syscall[4], syscall[5], syscall[6]);
+		for(n = 1; n < data[0]/sizeof(long); n++) {
+			if(n == 1)
+				printk("    additional syscall data:");
+			if(n % 4 == 1)
+				printk("\n      ");
+			printk("  0x%lx", data[n]);
+		}
+		if(n > 1)
+			printk("\n");
+	}
+	else ret = 0;
+
+	*addr = check_init_stack(mm_idp, NULL);
+
+	return ret;
+}
+
+long run_syscall_stub(struct mm_id * mm_idp, int syscall,
+		      unsigned long *args, long expected, void **addr,
+		      int done)
+{
+	unsigned long *stack = check_init_stack(mm_idp, *addr);
+
+	if(done && *addr == NULL)
+		single_count++;
+
+	*stack += sizeof(long);
+	stack += *stack / sizeof(long);
+
+	*stack++ = syscall;
+	*stack++ = args[0];
+	*stack++ = args[1];
+	*stack++ = args[2];
+	*stack++ = args[3];
+	*stack++ = args[4];
+	*stack++ = args[5];
+	*stack++ = expected;
+	*stack = 0;
+	multi_op_count++;
+
+	if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
+		     PAGE_SIZE - 10 * sizeof(long))){
+		*addr = stack;
+		return 0;
+	}
+
+	return do_syscall_stub(mm_idp, addr);
+}
+
+long syscall_stub_data(struct mm_id * mm_idp,
+		       unsigned long *data, int data_count,
+		       void **addr, void **stub_addr)
+{
+	unsigned long *stack;
+	int ret = 0;
+
+	/* If *addr still is uninitialized, it *must* contain NULL.
+	 * Thus in this case do_syscall_stub correctly won't be called.
+	 */
+	if((((unsigned long) *addr) & ~PAGE_MASK) >=
+	   PAGE_SIZE - (10 + data_count) * sizeof(long)) {
+		ret = do_syscall_stub(mm_idp, addr);
+		/* in case of error, don't overwrite data on stack */
+		if(ret)
+			return ret;
+	}
+
+	stack = check_init_stack(mm_idp, *addr);
+	*addr = stack;
+
+	*stack = data_count * sizeof(long);
+
+	memcpy(stack + 1, data, data_count * sizeof(long));
+
+	*stub_addr = (void *)(((unsigned long)(stack + 1) & ~PAGE_MASK) +
+			      UML_CONFIG_STUB_DATA);
+
+	return 0;
+}
+
+int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
+	int r, int w, int x, int phys_fd, unsigned long long offset,
+	int done, void **data)
+{
+	int prot, ret;
+
+	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+		(x ? PROT_EXEC : 0);
+
+	if(proc_mm){
+		struct proc_mm_op map;
+		int fd = mm_idp->u.mm_fd;
+
+		map = ((struct proc_mm_op) { .op	= MM_MMAP,
+				       .u		=
+				       { .mmap	=
+					 { .addr	= virt,
+					   .len	= len,
+					   .prot	= prot,
+					   .flags	= MAP_SHARED |
+					   MAP_FIXED,
+					   .fd	= phys_fd,
+					   .offset= offset
+					 } } } );
+		ret = os_write_file(fd, &map, sizeof(map));
+		if(ret != sizeof(map))
+			printk("map : /proc/mm map failed, err = %d\n", -ret);
+		else ret = 0;
+	}
+	else {
+		unsigned long args[] = { virt, len, prot,
+					 MAP_SHARED | MAP_FIXED, phys_fd,
+					 MMAP_OFFSET(offset) };
+
+		ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
+				       data, done);
+	}
+
+	return ret;
+}
+
+int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
+	  void **data)
+{
+	int ret;
+
+	if(proc_mm){
+		struct proc_mm_op unmap;
+		int fd = mm_idp->u.mm_fd;
+
+		unmap = ((struct proc_mm_op) { .op	= MM_MUNMAP,
+					 .u	=
+					 { .munmap	=
+					   { .addr	=
+					     (unsigned long) addr,
+					     .len		= len } } } );
+		ret = os_write_file(fd, &unmap, sizeof(unmap));
+		if(ret != sizeof(unmap))
+			printk("unmap - proc_mm write returned %d\n", ret);
+		else ret = 0;
+	}
+	else {
+		unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
+					 0 };
+
+		ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
+				       data, done);
+	}
+
+	return ret;
+}
+
+int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
+	    int r, int w, int x, int done, void **data)
+{
+	struct proc_mm_op protect;
+	int prot, ret;
+
+	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+		(x ? PROT_EXEC : 0);
+	if(proc_mm){
+		int fd = mm_idp->u.mm_fd;
+
+		protect = ((struct proc_mm_op) { .op	= MM_MPROTECT,
+					   .u	=
+					   { .mprotect	=
+					     { .addr	=
+					       (unsigned long) addr,
+					       .len	= len,
+					       .prot	= prot } } } );
+
+		ret = os_write_file(fd, &protect, sizeof(protect));
+		if(ret != sizeof(protect))
+			printk("protect failed, err = %d", -ret);
+		else ret = 0;
+	}
+	else {
+		unsigned long args[] = { addr, len, prot, 0, 0, 0 };
+
+		ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
+				       data, done);
+	}
+
+	return ret;
+}
+
+void before_mem_skas(unsigned long unused)
+{
+}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/os-Linux/skas/process.c
similarity index 72%
rename from arch/um/kernel/skas/process.c
rename to arch/um/os-Linux/skas/process.c
index 3b3955d..bbf34cb 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
@@ -10,6 +10,7 @@
 #include <signal.h>
 #include <setjmp.h>
 #include <sched.h>
+#include "ptrace_user.h"
 #include <sys/wait.h>
 #include <sys/mman.h>
 #include <sys/user.h>
@@ -17,8 +18,6 @@
 #include <asm/unistd.h>
 #include <asm/types.h>
 #include "user.h"
-#include "ptrace_user.h"
-#include "time_user.h"
 #include "sysdep/ptrace.h"
 #include "user_util.h"
 #include "kern_util.h"
@@ -35,10 +34,11 @@
 #include "mem.h"
 #include "uml-config.h"
 #include "process.h"
+#include "longjmp.h"
 
 int is_skas_winch(int pid, int fd, void *data)
 {
-        if(pid != os_getpgrp())
+	if(pid != os_getpgrp())
 		return(0);
 
 	register_winch_irq(-1, fd, -1, data);
@@ -47,28 +47,29 @@
 
 void wait_stub_done(int pid, int sig, char * fname)
 {
-        int n, status, err;
+	int n, status, err;
 
-        do {
-                if ( sig != -1 ) {
-                        err = ptrace(PTRACE_CONT, pid, 0, sig);
-                        if(err)
-                                panic("%s : continue failed, errno = %d\n",
-                                      fname, errno);
-                }
-                sig = 0;
+	do {
+		if ( sig != -1 ) {
+			err = ptrace(PTRACE_CONT, pid, 0, sig);
+			if(err)
+				panic("%s : continue failed, errno = %d\n",
+				      fname, errno);
+		}
+		sig = 0;
 
-                CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
-        } while((n >= 0) && WIFSTOPPED(status) &&
-                ((WSTOPSIG(status) == SIGVTALRM) ||
+		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+	} while((n >= 0) && WIFSTOPPED(status) &&
+	        ((WSTOPSIG(status) == SIGVTALRM) ||
 		 /* running UML inside a detached screen can cause
 		  * SIGWINCHes
 		  */
 		 (WSTOPSIG(status) == SIGWINCH)));
 
-        if((n < 0) || !WIFSTOPPED(status) ||
-           (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
+	if((n < 0) || !WIFSTOPPED(status) ||
+	   (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
 		unsigned long regs[HOST_FRAME_SIZE];
+
 		if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
 			printk("Failed to get registers from stub, "
 			       "errno = %d\n", errno);
@@ -79,42 +80,44 @@
 			for(i = 0; i < HOST_FRAME_SIZE; i++)
 				printk("\t%d - %lx\n", i, regs[i]);
 		}
-                panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
-                      "pid = %d, n = %d, errno = %d, status = 0x%x\n",
-                      fname, pid, n, errno, status);
-        }
+		panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
+		      "pid = %d, n = %d, errno = %d, status = 0x%x\n",
+		      fname, pid, n, errno, status);
+	}
 }
 
+extern unsigned long current_stub_stack(void);
+
 void get_skas_faultinfo(int pid, struct faultinfo * fi)
 {
-        int err;
+	int err;
 
-        if(ptrace_faultinfo){
-                err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
-                if(err)
-                        panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
-                              "errno = %d\n", errno);
+	if(ptrace_faultinfo){
+		err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
+		if(err)
+			panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
+			      "errno = %d\n", errno);
 
-                /* Special handling for i386, which has different structs */
-                if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
-                        memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
-                               sizeof(struct faultinfo) -
-                               sizeof(struct ptrace_faultinfo));
-        }
-        else {
-                wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
+		/* Special handling for i386, which has different structs */
+		if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
+			memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
+			       sizeof(struct faultinfo) -
+			       sizeof(struct ptrace_faultinfo));
+	}
+	else {
+		wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
 
-                /* faultinfo is prepared by the stub-segv-handler at start of
-                 * the stub stack page. We just have to copy it.
-                 */
-                memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
-        }
+		/* faultinfo is prepared by the stub-segv-handler at start of
+		 * the stub stack page. We just have to copy it.
+		 */
+		memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
+	}
 }
 
 static void handle_segv(int pid, union uml_pt_regs * regs)
 {
-        get_skas_faultinfo(pid, &regs->skas.faultinfo);
-        segv(regs->skas.faultinfo, 0, 1, NULL);
+	get_skas_faultinfo(pid, &regs->skas.faultinfo);
+	segv(regs->skas.faultinfo, 0, 1, NULL);
 }
 
 /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
@@ -127,7 +130,8 @@
 
 	if (!local_using_sysemu)
 	{
-		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+			     __NR_getpid);
 		if(err < 0)
 			panic("handle_trap - nullifying syscall failed errno = %d\n",
 			      errno);
@@ -148,8 +152,6 @@
 }
 
 extern int __syscall_stub_start;
-int stub_code_fd = -1;
-__u64 stub_code_offset;
 
 static int userspace_tramp(void *stack)
 {
@@ -164,31 +166,30 @@
 		/* This has a pte, but it can't be mapped in with the usual
 		 * tlb_flush mechanism because this is part of that mechanism
 		 */
+		int fd;
+		__u64 offset;
+		fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
 		addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(),
-			      PROT_EXEC, MAP_FIXED | MAP_PRIVATE,
-			      stub_code_fd, stub_code_offset);
+			      PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
 		if(addr == MAP_FAILED){
-			printk("mapping stub code failed, errno = %d\n",
+			printk("mapping mmap stub failed, errno = %d\n",
 			       errno);
 			exit(1);
 		}
 
 		if(stack != NULL){
-			int fd;
-			__u64 offset;
-
 			fd = phys_mapping(to_phys(stack), &offset);
 			addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(),
 				    PROT_READ | PROT_WRITE,
 				    MAP_FIXED | MAP_SHARED, fd, offset);
 			if(addr == MAP_FAILED){
-				printk("mapping stub stack failed, "
+				printk("mapping segfault stack failed, "
 				       "errno = %d\n", errno);
 				exit(1);
 			}
 		}
 	}
-	if(!ptrace_faultinfo){
+	if(!ptrace_faultinfo && (stack != NULL)){
 		unsigned long v = UML_CONFIG_STUB_CODE +
 				  (unsigned long) stub_segv_handler -
 				  (unsigned long) &__syscall_stub_start;
@@ -214,10 +215,6 @@
 	unsigned long sp;
 	int pid, status, n, flags;
 
-	if ( stub_code_fd == -1 )
-		stub_code_fd = phys_mapping(to_phys(&__syscall_stub_start),
-					    &stub_code_offset);
-
 	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	if(stack == MAP_FAILED)
@@ -233,7 +230,7 @@
 	do {
 		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 		if(n < 0)
-			panic("start_userspace : wait failed, errno = %d", 
+			panic("start_userspace : wait failed, errno = %d",
 			      errno);
 	} while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
 
@@ -242,7 +239,7 @@
 		      status);
 
 	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
-		panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n",
+		panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
 		      errno);
 
 	if(munmap(stack, PAGE_SIZE) < 0)
@@ -272,7 +269,7 @@
 
 		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
 		if(err < 0)
-			panic("userspace - waitpid failed, errno = %d\n", 
+			panic("userspace - waitpid failed, errno = %d\n",
 			      errno);
 
 		regs->skas.is_user = 1;
@@ -282,9 +279,9 @@
 		if(WIFSTOPPED(status)){
 		  	switch(WSTOPSIG(status)){
 			case SIGSEGV:
-                                if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
-                                        user_signal(SIGSEGV, regs, pid);
-                                else handle_segv(pid, regs);
+				if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
+					user_signal(SIGSEGV, regs, pid);
+				else handle_segv(pid, regs);
 				break;
 			case SIGTRAP + 0x80:
 			        handle_trap(pid, regs, local_using_sysemu);
@@ -298,7 +295,7 @@
 			case SIGBUS:
 			case SIGFPE:
 			case SIGWINCH:
-                                user_signal(WSTOPSIG(status), regs, pid);
+				user_signal(WSTOPSIG(status), regs, pid);
 				break;
 			default:
 			        printk("userspace - child stopped with signal "
@@ -308,21 +305,17 @@
 			interrupt_end();
 
 			/* Avoid -ERESTARTSYS handling in host */
-			PT_SYSCALL_NR(regs->skas.regs) = -1;
+			if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
+				PT_SYSCALL_NR(regs->skas.regs) = -1;
 		}
 	}
 }
-#define INIT_JMP_NEW_THREAD 0
-#define INIT_JMP_REMOVE_SIGSTACK 1
-#define INIT_JMP_CALLBACK 2
-#define INIT_JMP_HALT 3
-#define INIT_JMP_REBOOT 4
-
 
 int copy_context_skas0(unsigned long new_stack, int pid)
 {
 	int err;
-	unsigned long regs[MAX_REG_NR];
+	unsigned long regs[HOST_FRAME_SIZE];
+	unsigned long fp_regs[HOST_FP_SIZE];
 	unsigned long current_stack = current_stub_stack();
 	struct stub_data *data = (struct stub_data *) current_stack;
 	struct stub_data *child_data = (struct stub_data *) new_stack;
@@ -334,10 +327,10 @@
 	 */
 	*data = ((struct stub_data) { .offset	= MMAP_OFFSET(new_offset),
 				      .fd	= new_fd,
-				      .timer	= ((struct itimerval)
-					           { { 0, 1000000 / hz() },
-						     { 0, 1000000 / hz() }})});
-	get_safe_registers(regs);
+				      .timer    = ((struct itimerval)
+					            { { 0, 1000000 / hz() },
+						      { 0, 1000000 / hz() }})});
+	get_safe_registers(regs, fp_regs);
 
 	/* Set parent's instruction pointer to start of clone-stub */
 	regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
@@ -345,11 +338,19 @@
 				(unsigned long) &__syscall_stub_start;
 	regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
 		sizeof(void *);
+#ifdef __SIGNAL_FRAMESIZE
+	regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
+#endif
 	err = ptrace_setregs(pid, regs);
 	if(err < 0)
 		panic("copy_context_skas0 : PTRACE_SETREGS failed, "
 		      "pid = %d, errno = %d\n", pid, errno);
 
+	err = ptrace_setfpregs(pid, fp_regs);
+	if(err < 0)
+		panic("copy_context_skas0 : PTRACE_SETFPREGS failed, "
+		      "pid = %d, errno = %d\n", pid, errno);
+
 	/* set a well known return code for detection of child write failure */
 	child_data->err = 12345678;
 
@@ -373,7 +374,7 @@
 
 	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
 		   (void *)PTRACE_O_TRACESYSGOOD) < 0)
-		panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, "
+		panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
 		      "errno = %d\n", errno);
 
 	return pid;
@@ -389,6 +390,9 @@
 {
 	struct proc_mm_op mmop;
 	int n;
+	__u64 code_offset;
+	int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start),
+				   &code_offset);
 
 	mmop = ((struct proc_mm_op) { .op        = MM_MMAP,
 				      .u         =
@@ -397,8 +401,8 @@
 					  .len     = PAGE_SIZE,
 					  .prot    = PROT_EXEC,
 					  .flags   = MAP_FIXED | MAP_PRIVATE,
-					  .fd      = stub_code_fd,
-					  .offset  = stub_code_offset
+					  .fd      = code_fd,
+					  .offset  = code_offset
 	} } });
 	n = os_write_file(fd, &mmop, sizeof(mmop));
 	if(n != sizeof(mmop))
@@ -431,6 +435,7 @@
 {
 	unsigned long flags;
 	sigjmp_buf switch_buf, fork_buf;
+	int enable;
 
 	*switch_buf_ptr = &switch_buf;
 	*fork_buf_ptr = &fork_buf;
@@ -445,7 +450,7 @@
 	 */
 	flags = get_signals();
 	block_signals();
-	if(sigsetjmp(fork_buf, 1) == 0)
+	if(UML_SIGSETJMP(&fork_buf, enable) == 0)
 		new_thread_proc(stack, handler);
 
 	remove_sigstack();
@@ -453,23 +458,31 @@
 	set_signals(flags);
 }
 
+#define INIT_JMP_NEW_THREAD 0
+#define INIT_JMP_REMOVE_SIGSTACK 1
+#define INIT_JMP_CALLBACK 2
+#define INIT_JMP_HALT 3
+#define INIT_JMP_REBOOT 4
+
 void thread_wait(void *sw, void *fb)
 {
 	sigjmp_buf buf, **switch_buf = sw, *fork_buf;
+	int enable;
 
 	*switch_buf = &buf;
 	fork_buf = fb;
-	if(sigsetjmp(buf, 1) == 0)
+	if(UML_SIGSETJMP(&buf, enable) == 0)
 		siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
 }
 
 void switch_threads(void *me, void *next)
 {
 	sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
-	
+	int enable;
+
 	*me_ptr = &my_buf;
-	if(sigsetjmp(my_buf, 1) == 0)
-		siglongjmp(*next_buf, 1);
+	if(UML_SIGSETJMP(&my_buf, enable) == 0)
+		UML_SIGLONGJMP(next_buf, 1);
 }
 
 static sigjmp_buf initial_jmpbuf;
@@ -482,48 +495,49 @@
 int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
 {
 	sigjmp_buf **switch_buf = switch_buf_ptr;
-	int n;
+	int n, enable;
 
 	set_handler(SIGWINCH, (__sighandler_t) sig_handler,
 		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
 		    SIGVTALRM, -1);
 
 	*fork_buf_ptr = &initial_jmpbuf;
-	n = sigsetjmp(initial_jmpbuf, 1);
-        switch(n){
-        case INIT_JMP_NEW_THREAD:
-                new_thread_proc((void *) stack, new_thread_handler);
-                break;
-        case INIT_JMP_REMOVE_SIGSTACK:
-                remove_sigstack();
-                break;
-        case INIT_JMP_CALLBACK:
+	n = UML_SIGSETJMP(&initial_jmpbuf, enable);
+	switch(n){
+	case INIT_JMP_NEW_THREAD:
+		new_thread_proc((void *) stack, new_thread_handler);
+		break;
+	case INIT_JMP_REMOVE_SIGSTACK:
+		remove_sigstack();
+		break;
+	case INIT_JMP_CALLBACK:
 		(*cb_proc)(cb_arg);
-		siglongjmp(*cb_back, 1);
-                break;
-        case INIT_JMP_HALT:
+		UML_SIGLONGJMP(cb_back, 1);
+		break;
+	case INIT_JMP_HALT:
 		kmalloc_ok = 0;
 		return(0);
-        case INIT_JMP_REBOOT:
+	case INIT_JMP_REBOOT:
 		kmalloc_ok = 0;
 		return(1);
-        default:
-                panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
+	default:
+		panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
 	}
-	siglongjmp(**switch_buf, 1);
+	UML_SIGLONGJMP(*switch_buf, 1);
 }
 
 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 {
 	sigjmp_buf here;
+	int enable;
 
 	cb_proc = proc;
 	cb_arg = arg;
 	cb_back = &here;
 
 	block_signals();
-	if(sigsetjmp(here, 1) == 0)
-		siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK);
+	if(UML_SIGSETJMP(&here, enable) == 0)
+		UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
 	unblock_signals();
 
 	cb_proc = NULL;
@@ -534,13 +548,13 @@
 void halt_skas(void)
 {
 	block_signals();
-	siglongjmp(initial_jmpbuf, INIT_JMP_HALT);
+	UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
 }
 
 void reboot_skas(void)
 {
 	block_signals();
-	siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);
+	UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
 }
 
 void switch_mm_skas(struct mm_id *mm_idp)
@@ -557,14 +571,3 @@
 	}
 	else userspace_pid[0] = mm_idp->u.pid;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index b47e5e7..829d6b0 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -29,7 +29,6 @@
 #include "irq_user.h"
 #include "ptrace_user.h"
 #include "mem_user.h"
-#include "time_user.h"
 #include "init.h"
 #include "os.h"
 #include "uml-config.h"
@@ -50,6 +49,7 @@
 	int pid = os_getpid(), ppid = getppid();
 	int sc_result;
 
+	change_sig(SIGWINCH, 0);
 	if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
 		perror("ptrace");
 		os_kill_process(pid, 0);
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index aee4812..7a6f6b9 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -122,9 +122,12 @@
 		      err);
 }
 
-void get_safe_registers(unsigned long *regs)
+void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
 {
 	memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long));
+	if(fp_regs != NULL)
+		memcpy(fp_regs, exec_fp_regs,
+		       HOST_FP_SIZE * sizeof(unsigned long));
 }
 
 void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index 4b638dfb..001941f 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -70,9 +70,12 @@
 		      err);
 }
 
-void get_safe_registers(unsigned long *regs)
+void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
 {
 	memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long));
+	if(fp_regs != NULL)
+		memcpy(fp_regs, exec_fp_regs,
+		       HOST_FP_SIZE * sizeof(unsigned long));
 }
 
 void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index cf30a39..6f76267 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -1,21 +1,128 @@
-#include <stdlib.h>
-#include <sys/time.h>
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
 
-unsigned long long os_usecs(void)
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "process.h"
+#include "kern_constants.h"
+#include "os.h"
+
+/* XXX This really needs to be declared and initialized in a kernel file since
+ * it's in <linux/time.h>
+ */
+extern struct timespec wall_to_monotonic;
+
+static void set_interval(int timer_type)
+{
+	int usec = 1000000/hz();
+	struct itimerval interval = ((struct itimerval) { { 0, usec },
+							  { 0, usec } });
+
+	if(setitimer(timer_type, &interval, NULL) == -1)
+		panic("setitimer failed - errno = %d\n", errno);
+}
+
+void enable_timer(void)
+{
+	set_interval(ITIMER_VIRTUAL);
+}
+
+void disable_timer(void)
+{
+	struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
+	if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) ||
+	   (setitimer(ITIMER_REAL, &disable, NULL) < 0))
+		printk("disnable_timer - setitimer failed, errno = %d\n",
+		       errno);
+	/* If there are signals already queued, after unblocking ignore them */
+	set_handler(SIGALRM, SIG_IGN, 0, -1);
+	set_handler(SIGVTALRM, SIG_IGN, 0, -1);
+}
+
+void switch_timers(int to_real)
+{
+	struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
+	struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
+							{ 0, 1000000/hz() }});
+	int old, new;
+
+	if(to_real){
+		old = ITIMER_VIRTUAL;
+		new = ITIMER_REAL;
+	}
+	else {
+		old = ITIMER_REAL;
+		new = ITIMER_VIRTUAL;
+	}
+
+	if((setitimer(old, &disable, NULL) < 0) ||
+	   (setitimer(new, &enable, NULL)))
+		printk("switch_timers - setitimer failed, errno = %d\n",
+		       errno);
+}
+
+void uml_idle_timer(void)
+{
+	if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
+		panic("Couldn't unset SIGVTALRM handler");
+
+	set_handler(SIGALRM, (__sighandler_t) alarm_handler,
+		    SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
+	set_interval(ITIMER_REAL);
+}
+
+extern void ktime_get_ts(struct timespec *ts);
+#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
+
+void time_init(void)
+{
+	struct timespec now;
+
+	if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
+		panic("Couldn't set SIGVTALRM handler");
+	set_interval(ITIMER_VIRTUAL);
+
+	do_posix_clock_monotonic_gettime(&now);
+	wall_to_monotonic.tv_sec = -now.tv_sec;
+	wall_to_monotonic.tv_nsec = -now.tv_nsec;
+}
+
+unsigned long long os_nsecs(void)
 {
 	struct timeval tv;
 
 	gettimeofday(&tv, NULL);
-	return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec);
+	return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000);
 }
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+void idle_sleep(int secs)
+{
+	struct timespec ts;
+
+	ts.tv_sec = secs;
+	ts.tv_nsec = 0;
+	nanosleep(&ts, NULL);
+}
+
+/* XXX This partly duplicates init_irq_signals */
+
+void user_time_init(void)
+{
+	set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
+		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
+		    SIGALRM, SIGUSR2, -1);
+	set_handler(SIGALRM, (__sighandler_t) alarm_handler,
+		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
+		    SIGVTALRM, SIGUSR2, -1);
+	set_interval(ITIMER_VIRTUAL);
+}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 321e1c8e..a9f6b26 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -10,6 +10,7 @@
 #include "user_util.h"
 #include "os.h"
 #include "mode.h"
+#include "longjmp.h"
 
 void usr2_handler(int sig, union uml_pt_regs *regs)
 {
@@ -36,5 +37,5 @@
 {
 	sigjmp_buf *buf = b;
 
-	siglongjmp(*buf, val);
+	UML_SIGLONGJMP(buf, val);
 }
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index cb2648b..919d19f 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -27,7 +27,6 @@
 #include "sysdep/sigcontext.h"
 #include "irq_user.h"
 #include "ptrace_user.h"
-#include "time_user.h"
 #include "init.h"
 #include "os.h"
 #include "uml-config.h"
@@ -63,6 +62,54 @@
 	} while(1);
 }
 
+void stop(void)
+{
+	while(1) sleep(1000000);
+}
+
+int wait_for_stop(int pid, int sig, int cont_type, void *relay)
+{
+	sigset_t *relay_signals = relay;
+	int status, ret;
+
+	while(1){
+		CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
+		if((ret < 0) ||
+		   !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
+			if(ret < 0){
+				printk("wait failed, errno = %d\n",
+				       errno);
+			}
+			else if(WIFEXITED(status))
+				printk("process %d exited with status %d\n",
+				       pid, WEXITSTATUS(status));
+			else if(WIFSIGNALED(status))
+				printk("process %d exited with signal %d\n",
+				       pid, WTERMSIG(status));
+			else if((WSTOPSIG(status) == SIGVTALRM) ||
+				(WSTOPSIG(status) == SIGALRM) ||
+				(WSTOPSIG(status) == SIGIO) ||
+				(WSTOPSIG(status) == SIGPROF) ||
+				(WSTOPSIG(status) == SIGCHLD) ||
+				(WSTOPSIG(status) == SIGWINCH) ||
+				(WSTOPSIG(status) == SIGINT)){
+				ptrace(cont_type, pid, 0, WSTOPSIG(status));
+				continue;
+			}
+			else if((relay_signals != NULL) &&
+				sigismember(relay_signals, WSTOPSIG(status))){
+				ptrace(cont_type, pid, 0, WSTOPSIG(status));
+				continue;
+			}
+			else printk("process %d stopped with signal %d\n",
+				    pid, WSTOPSIG(status));
+			panic("wait_for_stop failed to wait for %d to stop "
+			      "with %d\n", pid, sig);
+		}
+		return(status);
+	}
+}
+
 /*
  *-------------------------
  * only for tt mode (will be deleted in future...)
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 38d7101..166fb66 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -6,6 +6,7 @@
 
 #include <setjmp.h>
 #include <string.h>
+#include "longjmp.h"
 
 unsigned long __do_user_copy(void *to, const void *from, int n,
 			     void **fault_addr, void **fault_catcher,
@@ -13,10 +14,11 @@
 					int n), int *faulted_out)
 {
 	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
+	int enable;
 
 	sigjmp_buf jbuf;
 	*fault_catcher = &jbuf;
-	if(sigsetjmp(jbuf, 1) == 0){
+	if(UML_SIGSETJMP(&jbuf, enable) == 0){
 		(*op)(to, from, n);
 		ret = 0;
 		*faulted_out = 0;
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
new file mode 100644
index 0000000..e32065e
--- /dev/null
+++ b/arch/um/os-Linux/util.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <setjmp.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include "asm/types.h"
+#include <ctype.h>
+#include <signal.h>
+#include <wait.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <sched.h>
+#include <termios.h>
+#include <string.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "mem_user.h"
+#include "init.h"
+#include "ptrace_user.h"
+#include "uml-config.h"
+#include "os.h"
+#include "longjmp.h"
+
+void stack_protections(unsigned long address)
+{
+	int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
+
+	if(mprotect((void *) address, page_size(), prot) < 0)
+		panic("protecting stack failed, errno = %d", errno);
+}
+
+void task_protections(unsigned long address)
+{
+	unsigned long guard = address + page_size();
+	unsigned long stack = guard + page_size();
+	int prot = 0, pages;
+
+#ifdef notdef
+	if(mprotect((void *) stack, page_size(), prot) < 0)
+		panic("protecting guard page failed, errno = %d", errno);
+#endif
+	pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
+	prot = PROT_READ | PROT_WRITE | PROT_EXEC;
+	if(mprotect((void *) stack, pages * page_size(), prot) < 0)
+		panic("protecting stack failed, errno = %d", errno);
+}
+
+int raw(int fd)
+{
+	struct termios tt;
+	int err;
+
+	CATCH_EINTR(err = tcgetattr(fd, &tt));
+	if(err < 0)
+		return -errno;
+
+	cfmakeraw(&tt);
+
+	CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
+	if(err < 0)
+		return -errno;
+
+	/* XXX tcsetattr could have applied only some changes
+	 * (and cfmakeraw() is a set of changes) */
+	return(0);
+}
+
+void setup_machinename(char *machine_out)
+{
+	struct utsname host;
+
+	uname(&host);
+#if defined(UML_CONFIG_UML_X86) && !defined(UML_CONFIG_64BIT)
+	if (!strcmp(host.machine, "x86_64")) {
+		strcpy(machine_out, "i686");
+		return;
+	}
+#endif
+	strcpy(machine_out, host.machine);
+}
+
+char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1];
+
+void setup_hostinfo(void)
+{
+	struct utsname host;
+
+	uname(&host);
+	sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename,
+		host.release, host.version, host.machine);
+}
+
+int setjmp_wrapper(void (*proc)(void *, void *), ...)
+{
+	va_list args;
+	sigjmp_buf buf;
+	int n;
+
+	n = sigsetjmp(buf, 1);
+	if(n == 0){
+		va_start(args, proc);
+		(*proc)(&buf, &args);
+	}
+	va_end(args);
+	return(n);
+}
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 17746b4..1fa09a7 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -16,6 +16,7 @@
 #include "choose-mode.h"
 #include "kern.h"
 #include "mode_kern.h"
+#include "os.h"
 
 extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
 
@@ -88,6 +89,7 @@
 #include "skas.h"
 #include "skas_ptrace.h"
 #include "asm/mmu_context.h"
+#include "proc_mm.h"
 
 long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
 		     void **addr, int done)
@@ -456,13 +458,14 @@
 	int i;
 	long page, err=0;
 	void *addr = NULL;
+	struct proc_mm_op copy;
 
-	memset(&desc, 0, sizeof(desc));
 
 	if(!ptrace_ldt)
 		init_MUTEX(&new_mm->ldt.semaphore);
 
 	if(!from_mm){
+		memset(&desc, 0, sizeof(desc));
 		/*
 		 * We have to initialize a clean ldt.
 		 */
@@ -494,8 +497,26 @@
 			}
 		}
 		new_mm->ldt.entry_count = 0;
+
+		goto out;
 	}
-	else if (!ptrace_ldt) {
+
+	if(proc_mm){
+		/* We have a valid from_mm, so we now have to copy the LDT of
+		 * from_mm to new_mm, because using proc_mm an new mm with
+		 * an empty/default LDT was created in new_mm()
+		 */
+		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
+					      .u 	=
+					      { .copy_segments =
+							from_mm->id.u.mm_fd } } );
+		i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
+		if(i != sizeof(copy))
+			printk("new_mm : /proc/mm copy_segments failed, "
+			       "err = %d\n", -i);
+	}
+
+	if(!ptrace_ldt) {
 		/* Our local LDT is used to supply the data for
 		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
 		 * i.e., we have to use the stub for modify_ldt, which
@@ -524,6 +545,7 @@
 		up(&from_mm->ldt.semaphore);
 	}
 
+    out:
 	return err;
 }
 
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
index 12e404c..b5f9c33 100644
--- a/arch/um/sys-x86_64/ptrace_user.c
+++ b/arch/um/sys-x86_64/ptrace_user.c
@@ -24,6 +24,13 @@
 	return(0);
 }
 
+int ptrace_setfpregs(long pid, unsigned long *regs)
+{
+	if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
+		return -errno;
+	return 0;
+}
+
 void ptrace_pokeuser(unsigned long addr, unsigned long data)
 {
 	panic("ptrace_pokeuser");
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
index 5a585bf..7bd54a9 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -57,7 +57,7 @@
 #endif
 
 	DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE);
-	DEFINE(HOST_FP_SIZE, 0);
+	DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
 	DEFINE(HOST_XFP_SIZE, 0);
 	DEFINE_LONGS(HOST_RBX, RBX);
 	DEFINE_LONGS(HOST_RCX, RCX);
diff --git a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c
index 7f0efaa..3975aa0 100644
--- a/arch/v850/kernel/simcons.c
+++ b/arch/v850/kernel/simcons.c
@@ -117,6 +117,7 @@
    tty driver.  */
 void simcons_poll_tty (struct tty_struct *tty)
 {
+	char buf[32];	/* Not the nicest way to do it but I need it correct first */
 	int flip = 0, send_break = 0;
 	struct pollfd pfd;
 	pfd.fd = 0;
@@ -124,21 +125,15 @@
 
 	if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) {
 		if (pfd.revents & POLLIN) {
-			int left = TTY_FLIPBUF_SIZE - tty->flip.count;
-
-			if (left > 0) {
-				unsigned char *buf = tty->flip.char_buf_ptr;
-				int rd = V850_SIM_SYSCALL (read, 0, buf, left);
-
-				if (rd > 0) {
-					tty->flip.count += rd;
-					tty->flip.char_buf_ptr += rd;
-					memset (tty->flip.flag_buf_ptr, 0, rd);
-					tty->flip.flag_buf_ptr += rd;
-					flip = 1;
-				} else
-					send_break = 1;
-			}
+			/* Real block hardware knows the transfer size before
+			   transfer so the new tty buffering doesn't try to handle
+			   this rather weird simulator specific case well */
+			int rd = V850_SIM_SYSCALL (read, 0, buf, 32);
+			if (rd > 0) {
+				tty_insert_flip_string(tty, buf, rd);
+				flip = 1;
+			} else
+				send_break = 1;
 		} else if (pfd.revents & POLLERR)
 			send_break = 1;
 	}
diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
index fcb06a5..ea31b4c 100644
--- a/arch/x86_64/Kconfig.debug
+++ b/arch/x86_64/Kconfig.debug
@@ -2,13 +2,6 @@
 
 source "lib/Kconfig.debug"
 
-config INIT_DEBUG
-	bool "Debug __init statements"
-	depends on DEBUG_KERNEL
-	help
-	  Fill __init and __initdata at the end of boot. This helps debugging
-	  illegal uses of __init and __initdata after initialization.
-
 config DEBUG_RODATA
        bool "Write protect kernel read-only data structures"
        depends on DEBUG_KERNEL
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 5231fe8..5683292 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-git12
-# Mon Jan 16 13:09:08 2006
+# Linux kernel version: 2.6.16-rc1-git2
+# Thu Jan 19 10:05:21 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -310,6 +310,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -319,11 +324,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -646,6 +646,7 @@
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
 # CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -1097,6 +1098,12 @@
 #
 
 #
+# EDAC - error detection and reporting (RAS)
+#
+# CONFIG_EDAC is not set
+# CONFIG_EDAC_POLL is not set
+
+#
 # Firmware Drivers
 #
 # CONFIG_EDD is not set
@@ -1289,6 +1296,7 @@
 # CONFIG_DEBUG_VM is not set
 # CONFIG_FRAME_POINTER is not set
 # CONFIG_FORCED_INLINING is not set
+# CONFIG_UNWIND_INFO is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_INIT_DEBUG=y
 # CONFIG_DEBUG_RODATA is not set
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 58f5bfb..00dee17 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -672,6 +672,22 @@
 	.quad sys_inotify_add_watch
 	.quad sys_inotify_rm_watch
 	.quad sys_migrate_pages
+	.quad compat_sys_openat		/* 295 */
+	.quad sys_mkdirat
+	.quad sys_mknodat
+	.quad sys_fchownat
+	.quad compat_sys_futimesat
+	.quad sys32_fstatat		/* 300 */
+	.quad sys_unlinkat
+	.quad sys_renameat
+	.quad sys_linkat
+	.quad sys_symlinkat
+	.quad sys_readlinkat		/* 305 */
+	.quad sys_fchmodat
+	.quad sys_faccessat
+	.quad sys_ni_syscall		/* pselect6 for now */
+	.quad sys_ni_syscall		/* ppoll for now */
+	.quad sys_unshare		/* 310 */
 ia32_syscall_end:		
 	.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
 		.quad ni_syscall
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 54481af..2bc55af 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -180,6 +180,28 @@
 	return ret;
 }
 
+asmlinkage long
+sys32_fstatat(unsigned int dfd, char __user *filename,
+	      struct stat64 __user* statbuf, int flag)
+{
+	struct kstat stat;
+	int error = -EINVAL;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat_fd(dfd, filename, &stat);
+	else
+		error = vfs_stat_fd(dfd, filename, &stat);
+
+	if (!error)
+		error = cp_stat64(statbuf, &stat);
+
+out:
+	return error;
+}
+
 /*
  * Linux/i386 didn't use to be able to handle more than
  * 4 system call parameters, so these system calls used a memory
diff --git a/arch/x86_64/kernel/acpi/Makefile b/arch/x86_64/kernel/acpi/Makefile
index 7da9ace..4fe9707 100644
--- a/arch/x86_64/kernel/acpi/Makefile
+++ b/arch/x86_64/kernel/acpi/Makefile
@@ -1,3 +1,8 @@
 obj-y			:= boot.o
 boot-y			:= ../../../i386/kernel/acpi/boot.o
 obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup.o
+
+ifneq ($(CONFIG_ACPI_PROCESSOR),)
+obj-y			+= processor.o
+endif
+
diff --git a/arch/x86_64/kernel/acpi/processor.c b/arch/x86_64/kernel/acpi/processor.c
new file mode 100644
index 0000000..3bdc2ba
--- /dev/null
+++ b/arch/x86_64/kernel/acpi/processor.c
@@ -0,0 +1,72 @@
+/*
+ * arch/x86_64/kernel/acpi/processor.c
+ *
+ * Copyright (C) 2005 Intel Corporation
+ * 	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * 	- Added _PDC for platforms with Intel CPUs
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+
+#include <acpi/processor.h>
+#include <asm/acpi.h>
+
+static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
+{
+	struct acpi_object_list *obj_list;
+	union acpi_object *obj;
+	u32 *buf;
+
+	/* allocate and initialize pdc. It will be used later. */
+	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
+	if (!obj_list) {
+		printk(KERN_ERR "Memory allocation error\n");
+		return;
+	}
+
+	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+	if (!obj) {
+		printk(KERN_ERR "Memory allocation error\n");
+		kfree(obj_list);
+		return;
+	}
+
+	buf = kmalloc(12, GFP_KERNEL);
+	if (!buf) {
+		printk(KERN_ERR "Memory allocation error\n");
+		kfree(obj);
+		kfree(obj_list);
+		return;
+	}
+
+	buf[0] = ACPI_PDC_REVISION_ID;
+	buf[1] = 1;
+	buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
+
+	obj->type = ACPI_TYPE_BUFFER;
+	obj->buffer.length = 12;
+	obj->buffer.pointer = (u8 *) buf;
+	obj_list->count = 1;
+	obj_list->pointer = obj;
+	pr->pdc = obj_list;
+
+	return;
+}
+
+/* Initialize _PDC data based on the CPU vendor */
+void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
+{
+	unsigned int cpu = pr->id;
+	struct cpuinfo_x86 *c = cpu_data + cpu;
+
+	pr->pdc = NULL;
+	if (c->x86_vendor == X86_VENDOR_INTEL && cpu_has(c, X86_FEATURE_EST))
+		init_intel_pdc(pr, c);
+
+	return;
+}
+
+EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 5d3c5b0..7a0a3e8 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -35,8 +35,12 @@
 #include <asm/mach_apic.h>
 #include <asm/nmi.h>
 #include <asm/idle.h>
+#include <asm/proto.h>
+#include <asm/timex.h>
 
 int apic_verbosity;
+int apic_runs_main_timer;
+int apic_calibrate_pmtmr __initdata;
 
 int disable_apic_timer __initdata;
 
@@ -68,6 +72,26 @@
 	return maxlvt;
 }
 
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+	printk("unexpected IRQ trap at vector %02x\n", irq);
+	/*
+	 * Currently unexpected vectors happen only on SMP and APIC.
+	 * We _must_ ack these because every local APIC has only N
+	 * irq slots per priority level, and a 'hanging, unacked' IRQ
+	 * holds up an irq slot - in excessive cases (when multiple
+	 * unexpected vectors occur) that might lock up the APIC
+	 * completely.
+  	 * But don't ack when the APIC is disabled. -AK
+	 */
+	if (!disable_apic)
+		ack_APIC_irq();
+}
+
 void clear_local_APIC(void)
 {
 	int maxlvt;
@@ -684,7 +708,7 @@
 	local_irq_save(flags);
 
 	/* wait for irq slice */
- 	if (vxtime.hpet_address) {
+ 	if (vxtime.hpet_address && hpet_use_timer) {
  		int trigger = hpet_readl(HPET_T0_CMP);
  		while (hpet_readl(HPET_COUNTER) >= trigger)
  			/* do nothing */ ;
@@ -702,9 +726,17 @@
 			c2 |= inb_p(0x40) << 8;
 		} while (c2 - c1 < 300);
 	}
-
 	__setup_APIC_LVTT(clocks);
-
+	/* Turn off PIT interrupt if we use APIC timer as main timer.
+	   Only works with the PM timer right now
+	   TBD fix it for HPET too. */
+	if (vxtime.mode == VXTIME_PMTMR &&
+		smp_processor_id() == boot_cpu_id &&
+		apic_runs_main_timer == 1 &&
+		!cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) {
+		stop_timer_interrupt();
+		apic_runs_main_timer++;
+	}
 	local_irq_restore(flags);
 }
 
@@ -735,14 +767,27 @@
 	__setup_APIC_LVTT(1000000000);
 
 	apic_start = apic_read(APIC_TMCCT);
-	rdtscl(tsc_start);
-
-	do {
+#ifdef CONFIG_X86_PM_TIMER
+	if (apic_calibrate_pmtmr && pmtmr_ioport) {
+		pmtimer_wait(5000);  /* 5ms wait */
 		apic = apic_read(APIC_TMCCT);
-		rdtscl(tsc);
-	} while ((tsc - tsc_start) < TICK_COUNT && (apic - apic_start) < TICK_COUNT);
+		result = (apic_start - apic) * 1000L / 5;
+	} else
+#endif
+	{
+		rdtscl(tsc_start);
 
-	result = (apic_start - apic) * 1000L * cpu_khz / (tsc - tsc_start);
+		do {
+			apic = apic_read(APIC_TMCCT);
+			rdtscl(tsc);
+		} while ((tsc - tsc_start) < TICK_COUNT &&
+				(apic - apic_start) < TICK_COUNT);
+
+		result = (apic_start - apic) * 1000L * cpu_khz /
+					(tsc - tsc_start);
+	}
+	printk("result %d\n", result);
+
 
 	printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n",
 		result / 1000 / 1000, result / 1000 % 1000);
@@ -872,6 +917,8 @@
 #ifdef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
+	if (apic_runs_main_timer > 1 && smp_processor_id() == boot_cpu_id)
+		main_timer_handler(regs);
 	/*
 	 * We take the 'long' return path, and there every subsystem
 	 * grabs the appropriate locks (kernel lock/ irq lock).
@@ -924,7 +971,7 @@
  * multi-chassis. Use available data to take a good guess.
  * If in doubt, go HPET.
  */
-__init int oem_force_hpet_timer(void)
+__cpuinit int oem_force_hpet_timer(void)
 {
 	int i, clusters, zeros;
 	unsigned id;
@@ -1081,10 +1128,34 @@
 
 static __init int setup_noapictimer(char *str) 
 { 
+	if (str[0] != ' ' && str[0] != 0)
+		return -1;
 	disable_apic_timer = 1;
 	return 0;
 } 
 
+static __init int setup_apicmaintimer(char *str)
+{
+	apic_runs_main_timer = 1;
+	nohpet = 1;
+	return 0;
+}
+__setup("apicmaintimer", setup_apicmaintimer);
+
+static __init int setup_noapicmaintimer(char *str)
+{
+	apic_runs_main_timer = -1;
+	return 0;
+}
+__setup("noapicmaintimer", setup_noapicmaintimer);
+
+static __init int setup_apicpmtimer(char *s)
+{
+	apic_calibrate_pmtmr = 1;
+	return setup_apicmaintimer(NULL);
+}
+__setup("apicpmtimer", setup_apicpmtimer);
+
 /* dummy parsing: see setup.c */
 
 __setup("disableapic", setup_disableapic); 
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index dbdba56..b150c87 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -499,7 +499,9 @@
 	movq %gs:pda_irqstackptr,%rax
 	cmoveq %rax,%rsp /*todo This needs CFI annotation! */
 	pushq %rdi			# save old stack	
+#ifndef CONFIG_DEBUG_INFO
 	CFI_ADJUST_CFA_OFFSET	8
+#endif
 	call \func
 	.endm
 
@@ -509,7 +511,9 @@
 	/* 0(%rsp): oldrsp-ARGOFFSET */
 ret_from_intr:
 	popq  %rdi
+#ifndef CONFIG_DEBUG_INFO
 	CFI_ADJUST_CFA_OFFSET	-8
+#endif
 	cli	
 	decl %gs:pda_irqcount
 #ifdef CONFIG_DEBUG_INFO
@@ -922,7 +926,7 @@
 	.previous .text
 
 	/* runs on exception stack */	
-ENTRY(nmi)
+KPROBE_ENTRY(nmi)
 	INTR_FRAME
 	pushq $-1
 	CFI_ADJUST_CFA_OFFSET 8
@@ -969,6 +973,7 @@
 	cli
 	jmp paranoid_userspace
 	CFI_ENDPROC
+	.previous .text
 
 KPROBE_ENTRY(int3)
  	INTR_FRAME
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index e8cf44e..4282d72 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -304,6 +304,14 @@
 #endif
 					/* RED-PEN skip them on mptables too? */
 					return;
+				case PCI_VENDOR_ID_ATI:
+					if (apic_runs_main_timer != 0)
+						break;
+					printk(KERN_INFO
+	     "ATI board detected. Using APIC/PM timer.\n");
+					apic_runs_main_timer = 1;
+					nohpet = 1;
+					return;
 				} 
 
 				/* No multi-function device? */
@@ -2027,7 +2035,7 @@
 }
 
 
-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
+int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
 {
 	struct IO_APIC_route_entry entry;
 	unsigned long flags;
@@ -2049,8 +2057,8 @@
 	entry.delivery_mode = INT_DELIVERY_MODE;
 	entry.dest_mode = INT_DEST_MODE;
 	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
-	entry.trigger = edge_level;
-	entry.polarity = active_high_low;
+	entry.trigger = triggering;
+	entry.polarity = polarity;
 	entry.mask = 1;					 /* Disabled (masked) */
 
 	irq = gsi_irq_sharing(irq);
@@ -2065,9 +2073,9 @@
 	apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
 		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
 	       mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
-	       edge_level, active_high_low);
+	       triggering, polarity);
 
-	ioapic_register_intr(irq, entry.vector, edge_level);
+	ioapic_register_intr(irq, entry.vector, triggering);
 
 	if (!ioapic && (irq < 16))
 		disable_8259A_irq(irq);
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 13a2ead..b8b9529 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -380,7 +380,7 @@
  */
 void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
 {
-	static cpumask_t mce_cpus __initdata = CPU_MASK_NONE;
+	static cpumask_t mce_cpus = CPU_MASK_NONE;
 
 	mce_cpu_quirks(c); 
 
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 1105250..dc49bfb 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -915,7 +915,7 @@
 
 #define MAX_GSI_NUM	4096
 
-int mp_register_gsi(u32 gsi, int edge_level, int active_high_low)
+int mp_register_gsi(u32 gsi, int triggering, int polarity)
 {
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
@@ -964,7 +964,7 @@
 
 	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 
-	if (edge_level) {
+	if (triggering == ACPI_LEVEL_SENSITIVE) {
 		/*
 		 * For PCI devices assign IRQs in order, avoiding gaps
 		 * due to unused I/O APIC pins.
@@ -986,8 +986,8 @@
 	}
 
 	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
-		edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
-		active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
+		triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+		polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
 	return gsi;
 }
 
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 5fae6f0..8be407a 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -24,6 +24,7 @@
 #include <linux/sysdev.h>
 #include <linux/nmi.h>
 #include <linux/sysctl.h>
+#include <linux/kprobes.h>
 
 #include <asm/smp.h>
 #include <asm/mtrr.h>
@@ -468,7 +469,7 @@
  	touch_softlockup_watchdog();
 }
 
-void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
+void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
 {
 	int sum;
 	int touched = 0;
@@ -512,14 +513,14 @@
 	}
 }
 
-static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
+static __kprobes int dummy_nmi_callback(struct pt_regs * regs, int cpu)
 {
 	return 0;
 }
  
 static nmi_callback_t nmi_callback = dummy_nmi_callback;
  
-asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
+asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code)
 {
 	int cpu = safe_smp_processor_id();
 
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 2f5d832..4ed391e 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -107,6 +107,9 @@
 				goto again;
 			}
 
+			/* Let low level make its own zone decisions */
+			gfp &= ~(GFP_DMA32|GFP_DMA);
+
 			if (dma_ops->alloc_coherent)
 				return dma_ops->alloc_coherent(dev, size,
 							   dma_handle, gfp);
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index c37fc77..dd0718d 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -310,7 +310,7 @@
 
 	for (i = 0; i < nents; i++) {
 		struct scatterlist *s = &sg[i];
-		if (!s->dma_length || !s->length)
+		if (!s->dma_length)
 			break;
 		dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
 	}
@@ -364,7 +364,6 @@
 		
 		BUG_ON(i > start && s->offset);
 		if (i == start) {
-			*sout = *s; 
 			sout->dma_address = iommu_bus_base;
 			sout->dma_address += iommu_page*PAGE_SIZE + s->offset;
 			sout->dma_length = s->length;
@@ -379,7 +378,7 @@
 			SET_LEAK(iommu_page);
 			addr += PAGE_SIZE;
 			iommu_page++;
-	} 
+		}
 	} 
 	BUG_ON(iommu_page - iommu_start != pages);	
 	return 0;
@@ -391,7 +390,6 @@
 {
 	if (!need) { 
 		BUG_ON(stopat - start != 1);
-		*sout = sg[start]; 
 		sout->dma_length = sg[start].length; 
 		return 0;
 	} 
@@ -457,9 +455,12 @@
 error:
 	flush_gart(NULL);
 	gart_unmap_sg(dev, sg, nents, dir);
-	/* When it was forced try again unforced */
-	if (force_iommu) 
-		return dma_map_sg_nonforce(dev, sg, nents, dir);
+	/* When it was forced or merged try again in a dumb way */
+	if (force_iommu || iommu_merge) {
+		out = dma_map_sg_nonforce(dev, sg, nents, dir);
+		if (out > 0)
+			return out;
+	}
 	if (panic_on_overflow)
 		panic("dma_map_sg: overflow on %lu pages\n", pages);
 	iommu_full(dev, pages << PAGE_SHIFT, dir);
@@ -642,9 +643,18 @@
 	    (no_agp && init_k8_gatt(&info) < 0)) {
 		no_iommu = 1;
 		no_iommu_init();
+		printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
+		if (end_pfn > MAX_DMA32_PFN) {
+			printk(KERN_ERR "WARNING more than 4GB of memory "
+					"but IOMMU not compiled in.\n"
+			       KERN_ERR "WARNING 32bit PCI may malfunction.\n"
+			       KERN_ERR "You might want to enable "
+					"CONFIG_GART_IOMMU\n");
+		}
 		return -1;
 	}
 
+	printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
 	aper_size = info.aper_size * 1024 * 1024;	
 	iommu_size = check_iommu_size(info.aper_base, aper_size); 
 	iommu_pages = iommu_size >> PAGE_SHIFT; 
@@ -718,7 +728,6 @@
 		     
 	flush_gart(NULL);
 
-	printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
 	dma_ops = &gart_dma_ops;
 
 	return 0;
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index e415649..44adcc2 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -88,12 +88,5 @@
 {
 	if (dma_ops)
 		return;
-	printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
 	dma_ops = &nommu_dma_ops;
-	if (end_pfn > MAX_DMA32_PFN) {
-		printk(KERN_ERR
-		       "WARNING more than 4GB of memory but IOMMU not compiled in.\n"
-		       KERN_ERR "WARNING 32bit PCI may malfunction.\n"
-		       KERN_ERR "You might want to enable CONFIG_GART_IOMMU\n");
-	}
 }
diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c
index 3569a25..990ed67 100644
--- a/arch/x86_64/kernel/pci-swiotlb.c
+++ b/arch/x86_64/kernel/pci-swiotlb.c
@@ -35,8 +35,8 @@
 	    (end_pfn > MAX_DMA32_PFN || force_iommu))
 	       swiotlb = 1;
 	if (swiotlb) {
-		swiotlb_init();
 		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
+		swiotlb_init();
 		dma_ops = &swiotlb_dma_ops;
 	}
 }
diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c
index feb5f10..5c51d10 100644
--- a/arch/x86_64/kernel/pmtimer.c
+++ b/arch/x86_64/kernel/pmtimer.c
@@ -80,6 +80,31 @@
 	return lost - 1;
 }
 
+static unsigned pmtimer_wait_tick(void)
+{
+	u32 a, b;
+	for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK;
+	     a == b;
+	     b = inl(pmtmr_ioport) & ACPI_PM_MASK)
+		;
+	return b;
+}
+
+/* note: wait time is rounded up to one tick */
+void pmtimer_wait(unsigned us)
+{
+	u32 a, b;
+	a = pmtimer_wait_tick();
+	do {
+		b = inl(pmtmr_ioport);
+	} while (cyc2us(b - a) < us);
+}
+
+void pmtimer_resume(void)
+{
+	last_pmtmr_tick = inl(pmtmr_ioport);
+}
+
 unsigned int do_gettimeoffset_pm(void)
 {
 	u32 now, offset, delta = 0;
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 8ded407..22a05de 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -516,8 +516,10 @@
  * This could still be optimized: 
  * - fold all the options into a flag word and test it with a single test.
  * - could test fs/gs bitsliced
+ *
+ * Kprobes not supported here. Set the probe on schedule instead.
  */
-struct task_struct *
+__kprobes struct task_struct *
 __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 {
 	struct thread_struct *prev = &prev_p->thread,
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 28895c0..9435ab7 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -94,7 +94,6 @@
 /*
  * Setup options
  */
-struct drive_info_struct { char dummy[32]; } drive_info;
 struct screen_info screen_info;
 struct sys_desc_table_struct {
 	unsigned short length;
@@ -572,7 +571,6 @@
 	unsigned long kernel_end;
 
  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
- 	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
 	edid_info = EDID_INFO;
 	saved_video_mode = SAVED_VIDEO_MODE;
@@ -741,7 +739,7 @@
 	e820_setup_gap();
 
 #ifdef CONFIG_GART_IOMMU
-       iommu_hole_init();
+	iommu_hole_init();
 #endif
 
 #ifdef CONFIG_VT
@@ -877,6 +875,7 @@
 static int __init init_amd(struct cpuinfo_x86 *c)
 {
 	int r;
+	unsigned level;
 
 #ifdef CONFIG_SMP
 	unsigned long value;
@@ -899,6 +898,11 @@
 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
 	clear_bit(0*32+31, &c->x86_capability);
 	
+	/* On C+ stepping K8 rep microcode works well for copy/memset */
+	level = cpuid_eax(1);
+	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
+		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+
 	r = get_model_name(c);
 	if (!r) { 
 		switch (c->x86) { 
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 8ac4db0..70f1bb8 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -146,7 +146,7 @@
 	pda->irqstackptr += IRQSTACKSIZE-64;
 } 
 
-char boot_exception_stacks[(N_EXCEPTION_STACKS - 2) * EXCEPTION_STKSZ + DEBUG_STKSZ]
+char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]
 __attribute__((section(".bss.page_aligned")));
 
 /* May not be marked __init: used by software suspend */
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index a28756e..67e4e28 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -59,6 +59,7 @@
 #include <asm/nmi.h>
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
+#include <asm/numa.h>
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
@@ -890,6 +891,7 @@
 	if (boot_error) {
 		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
 		clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
+		clear_node_cpumask(cpu); /* was set by numa_add_cpu */
 		cpu_clear(cpu, cpu_present_map);
 		cpu_clear(cpu, cpu_possible_map);
 		x86_cpu_to_apicid[cpu] = BAD_APICID;
@@ -1187,6 +1189,7 @@
 	cpu_clear(cpu, cpu_callout_map);
 	cpu_clear(cpu, cpu_callin_map);
 	clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
+	clear_node_cpumask(cpu);
 }
 
 int __cpu_disable(void)
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index f8c47c6..3c58c30 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -51,7 +51,7 @@
 DEFINE_SPINLOCK(rtc_lock);
 DEFINE_SPINLOCK(i8253_lock);
 
-static int nohpet __initdata = 0;
+int nohpet __initdata = 0;
 static int notsc __initdata = 0;
 
 #undef HPET_HACK_ENABLE_DANGEROUS
@@ -59,7 +59,7 @@
 unsigned int cpu_khz;					/* TSC clocks / usec, not used here */
 static unsigned long hpet_period;			/* fsecs / HPET clock */
 unsigned long hpet_tick;				/* HPET clocks / interrupt */
-static int hpet_use_timer;				/* Use counter of hpet for time keeping, otherwise PIT */
+int hpet_use_timer;				/* Use counter of hpet for time keeping, otherwise PIT */
 unsigned long vxtime_hz = PIT_TICK_RATE;
 int report_lost_ticks;				/* command line option */
 unsigned long long monotonic_base;
@@ -326,7 +326,10 @@
 	    print_symbol("rip %s\n", regs->rip);
 	    if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
 		    printk(KERN_WARNING "Falling back to HPET\n");
-		    vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
+		    if (hpet_use_timer)
+		    	vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
+		    else
+		    	vxtime.last = hpet_readl(HPET_COUNTER);
 		    vxtime.mode = VXTIME_HPET;
 		    do_gettimeoffset = do_gettimeoffset_hpet;
 	    }
@@ -345,7 +348,7 @@
 #endif
 }
 
-static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+void main_timer_handler(struct pt_regs *regs)
 {
 	static unsigned long rtc_update = 0;
 	unsigned long tsc;
@@ -458,12 +461,17 @@
 	}
  
 	write_sequnlock(&xtime_lock);
+}
 
+static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	if (apic_runs_main_timer > 1)
+		return IRQ_HANDLED;
+	main_timer_handler(regs);
 #ifdef CONFIG_X86_LOCAL_APIC
 	if (using_apic_timer)
 		smp_send_timer_broadcast_ipi();
 #endif
-
 	return IRQ_HANDLED;
 }
 
@@ -743,7 +751,7 @@
 	 * Timer0 and Timer1 is used by platform.
 	 */
 	hd.hd_phys_address = vxtime.hpet_address;
-	hd.hd_address = (void *)fix_to_virt(FIX_HPET_BASE);
+	hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE);
 	hd.hd_nirqs = ntimer;
 	hd.hd_flags = HPET_DATA_PLATFORM;
 	hpet_reserve_timer(&hd, 0);
@@ -843,17 +851,43 @@
 	return hpet_timer_stop_set_go(hpet_tick);
 }
 
-void __init pit_init(void)
+#define PIT_MODE 0x43
+#define PIT_CH0  0x40
+
+static void __init __pit_init(int val, u8 mode)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&i8253_lock, flags);
-	outb_p(0x34, 0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
-	outb_p(LATCH & 0xff, 0x40);	/* LSB */
-	outb_p(LATCH >> 8, 0x40);	/* MSB */
+	outb_p(mode, PIT_MODE);
+	outb_p(val & 0xff, PIT_CH0);	/* LSB */
+	outb_p(val >> 8, PIT_CH0);	/* MSB */
 	spin_unlock_irqrestore(&i8253_lock, flags);
 }
 
+void __init pit_init(void)
+{
+	__pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
+}
+
+void __init pit_stop_interrupt(void)
+{
+	__pit_init(0, 0x30); /* mode 0 */
+}
+
+void __init stop_timer_interrupt(void)
+{
+	char *name;
+	if (vxtime.hpet_address) {
+		name = "HPET";
+		hpet_timer_stop_set_go(0);
+	} else {
+		name = "PIT";
+		pit_stop_interrupt();
+	}
+	printk(KERN_INFO "timer: %s interrupt stopped.\n", name);
+}
+
 int __init time_setup(char *str)
 {
 	report_lost_ticks = 1;
@@ -932,7 +966,7 @@
  * Make an educated guess if the TSC is trustworthy and synchronized
  * over all CPUs.
  */
-__init int unsynchronized_tsc(void)
+__cpuinit int unsynchronized_tsc(void)
 {
 #ifdef CONFIG_SMP
 	if (oem_force_hpet_timer())
@@ -957,7 +991,10 @@
 		notsc = 1;
 	if (vxtime.hpet_address && notsc) {
 		timetype = hpet_use_timer ? "HPET" : "PIT/HPET";
-		vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
+		if (hpet_use_timer)
+			vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
+		else
+			vxtime.last = hpet_readl(HPET_COUNTER);
 		vxtime.mode = VXTIME_HPET;
 		do_gettimeoffset = do_gettimeoffset_hpet;
 #ifdef CONFIG_X86_PM_TIMER
@@ -1016,9 +1053,21 @@
 	write_seqlock_irqsave(&xtime_lock,flags);
 	xtime.tv_sec = sec;
 	xtime.tv_nsec = 0;
+	if (vxtime.mode == VXTIME_HPET) {
+		if (hpet_use_timer)
+			vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
+		else
+			vxtime.last = hpet_readl(HPET_COUNTER);
+#ifdef CONFIG_X86_PM_TIMER
+	} else if (vxtime.mode == VXTIME_PMTMR) {
+		pmtimer_resume();
+#endif
+	} else
+		vxtime.last_tsc = get_cycles_sync();
 	write_sequnlock_irqrestore(&xtime_lock,flags);
 	jiffies += sleep_length;
 	wall_jiffies += sleep_length;
+	monotonic_base += sleep_length * (NSEC_PER_SEC/HZ);
 	touch_softlockup_watchdog();
 	return 0;
 }
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 8bb0aed..28d50dc 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -90,6 +90,20 @@
 		local_irq_enable();
 }
 
+static inline void preempt_conditional_sti(struct pt_regs *regs)
+{
+	preempt_disable();
+	if (regs->eflags & X86_EFLAGS_IF)
+		local_irq_enable();
+}
+
+static inline void preempt_conditional_cli(struct pt_regs *regs)
+{
+	if (regs->eflags & X86_EFLAGS_IF)
+		local_irq_disable();
+	preempt_enable_no_resched();
+}
+
 static int kstack_depth_to_print = 10;
 
 #ifdef CONFIG_KALLSYMS
@@ -372,7 +386,7 @@
 static DEFINE_SPINLOCK(die_lock);
 static int die_owner = -1;
 
-unsigned long oops_begin(void)
+unsigned __kprobes long oops_begin(void)
 {
 	int cpu = safe_smp_processor_id();
 	unsigned long flags;
@@ -391,7 +405,7 @@
 	return flags;
 }
 
-void oops_end(unsigned long flags)
+void __kprobes oops_end(unsigned long flags)
 { 
 	die_owner = -1;
 	bust_spinlocks(0);
@@ -400,7 +414,7 @@
 		panic("Oops");
 }
 
-void __die(const char * str, struct pt_regs * regs, long err)
+void __kprobes __die(const char * str, struct pt_regs * regs, long err)
 {
 	static int die_counter;
 	printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter);
@@ -432,7 +446,7 @@
 	do_exit(SIGSEGV); 
 }
 
-void die_nmi(char *str, struct pt_regs *regs)
+void __kprobes die_nmi(char *str, struct pt_regs *regs)
 {
 	unsigned long flags = oops_begin();
 
@@ -575,7 +589,8 @@
 	}
 }
 
-static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
+static __kprobes void
+mem_parity_error(unsigned char reason, struct pt_regs * regs)
 {
 	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
 	printk("You probably have a hardware problem with your RAM chips\n");
@@ -585,7 +600,8 @@
 	outb(reason, 0x61);
 }
 
-static void io_check_error(unsigned char reason, struct pt_regs * regs)
+static __kprobes void
+io_check_error(unsigned char reason, struct pt_regs * regs)
 {
 	printk("NMI: IOCK error (debug interrupt?)\n");
 	show_registers(regs);
@@ -598,7 +614,8 @@
 	outb(reason, 0x61);
 }
 
-static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+static __kprobes void
+unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
 {	printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
 	printk("Dazed and confused, but trying to continue\n");
 	printk("Do you have a strange power saving mode enabled?\n");
@@ -606,7 +623,7 @@
 
 /* Runs on IST stack. This code must keep interrupts off all the time.
    Nested NMIs are prevented by the CPU. */
-asmlinkage void default_do_nmi(struct pt_regs *regs)
+asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
 {
 	unsigned char reason = 0;
 	int cpu;
@@ -658,7 +675,7 @@
 /* Help handler running on IST stack to switch back to user stack
    for scheduling or signal handling. The actual stack switch is done in
    entry.S */
-asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs)
+asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
 {
 	struct pt_regs *regs = eregs;
 	/* Did already sync */
@@ -690,7 +707,7 @@
 						SIGTRAP) == NOTIFY_STOP)
 		return;
 
-	conditional_sti(regs);
+	preempt_conditional_sti(regs);
 
 	/* Mask out spurious debug traps due to lazy DR7 setting */
 	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
@@ -735,11 +752,13 @@
 
 clear_dr7:
 	set_debugreg(0UL, 7);
+	preempt_conditional_cli(regs);
 	return;
 
 clear_TF_reenable:
 	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
 	regs->eflags &= ~TF_MASK;
+	preempt_conditional_cli(regs);
 }
 
 static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index b0eed1f..74db006 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -172,13 +172,15 @@
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
-  __initramfs_end = .;	
-  . = ALIGN(32);
+  __initramfs_end = .;
+  /* temporary here to work around NR_CPUS. If you see this comment in 2.6.17+
+   complain */
+  . = ALIGN(4096);	
+  __init_end = .;	
+  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   __per_cpu_start = .;
   .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
   __per_cpu_end = .;
-  . = ALIGN(4096);
-  __init_end = .;
 
   . = ALIGN(4096);
   __nosave_begin = .;
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index b614d54..3496abc 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -39,11 +39,6 @@
 extern void __read_lock_failed(rwlock_t *rw);
 #endif
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
-extern struct drive_info_struct drive_info;
-EXPORT_SYMBOL(drive_info);
-#endif
-
 /* platform dependent support */
 EXPORT_SYMBOL(boot_cpu_data);
 //EXPORT_SYMBOL(dump_fpu);
diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile
index bba5db6..ccef6ae 100644
--- a/arch/x86_64/lib/Makefile
+++ b/arch/x86_64/lib/Makefile
@@ -4,7 +4,7 @@
 
 CFLAGS_csum-partial.o := -funroll-loops
 
-obj-y := io.o
+obj-y := io.o iomap_copy.o
 
 lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
 	usercopy.o getuser.o putuser.o  \
diff --git a/arch/x86_64/lib/clear_page.S b/arch/x86_64/lib/clear_page.S
index 43d9fa1..1f81b79 100644
--- a/arch/x86_64/lib/clear_page.S
+++ b/arch/x86_64/lib/clear_page.S
@@ -5,8 +5,46 @@
 	.globl clear_page
 	.p2align 4
 clear_page:
+	xorl   %eax,%eax
+	movl   $4096/64,%ecx
+	.p2align 4
+.Lloop:
+	decl	%ecx
+#define PUT(x) movq %rax,x*8(%rdi)
+	movq %rax,(%rdi)
+	PUT(1)
+	PUT(2)
+	PUT(3)
+	PUT(4)
+	PUT(5)
+	PUT(6)
+	PUT(7)
+	leaq	64(%rdi),%rdi
+	jnz	.Lloop
+	nop
+	ret
+clear_page_end:
+
+	/* Some CPUs run faster using the string instructions.
+	   It is also a lot simpler. Use this when possible */
+
+#include <asm/cpufeature.h>
+
+	.section .altinstructions,"a"
+	.align 8
+	.quad  clear_page
+	.quad  clear_page_c
+	.byte  X86_FEATURE_REP_GOOD
+	.byte  clear_page_end-clear_page
+	.byte  clear_page_c_end-clear_page_c
+	.previous
+
+	.section .altinstr_replacement,"ax"
+clear_page_c:
 	movl $4096/8,%ecx
 	xorl %eax,%eax
 	rep 
 	stosq
 	ret
+clear_page_c_end:
+	.previous
diff --git a/arch/x86_64/lib/copy_page.S b/arch/x86_64/lib/copy_page.S
index 621a197..8fa19d9 100644
--- a/arch/x86_64/lib/copy_page.S
+++ b/arch/x86_64/lib/copy_page.S
@@ -8,7 +8,94 @@
 	.globl copy_page
 	.p2align 4
 copy_page:
+	subq	$3*8,%rsp
+	movq	%rbx,(%rsp)
+	movq	%r12,1*8(%rsp)
+	movq	%r13,2*8(%rsp)
+
+	movl	$(4096/64)-5,%ecx
+	.p2align 4
+.Loop64:
+  	dec     %rcx
+
+	movq        (%rsi), %rax
+	movq      8 (%rsi), %rbx
+	movq     16 (%rsi), %rdx
+	movq     24 (%rsi), %r8
+	movq     32 (%rsi), %r9
+	movq     40 (%rsi), %r10
+	movq     48 (%rsi), %r11
+	movq     56 (%rsi), %r12
+
+	prefetcht0 5*64(%rsi)
+
+	movq     %rax,    (%rdi)
+	movq     %rbx,  8 (%rdi)
+	movq     %rdx, 16 (%rdi)
+	movq     %r8,  24 (%rdi)
+	movq     %r9,  32 (%rdi)
+	movq     %r10, 40 (%rdi)
+	movq     %r11, 48 (%rdi)
+	movq     %r12, 56 (%rdi)
+
+	leaq    64 (%rsi), %rsi
+	leaq    64 (%rdi), %rdi
+
+	jnz     .Loop64
+
+	movl	$5,%ecx
+	.p2align 4
+.Loop2:
+	decl   %ecx
+
+	movq        (%rsi), %rax
+	movq      8 (%rsi), %rbx
+	movq     16 (%rsi), %rdx
+	movq     24 (%rsi), %r8
+	movq     32 (%rsi), %r9
+	movq     40 (%rsi), %r10
+	movq     48 (%rsi), %r11
+	movq     56 (%rsi), %r12
+
+	movq     %rax,    (%rdi)
+	movq     %rbx,  8 (%rdi)
+	movq     %rdx, 16 (%rdi)
+	movq     %r8,  24 (%rdi)
+	movq     %r9,  32 (%rdi)
+	movq     %r10, 40 (%rdi)
+	movq     %r11, 48 (%rdi)
+	movq     %r12, 56 (%rdi)
+
+	leaq	64(%rdi),%rdi
+	leaq	64(%rsi),%rsi
+
+	jnz	.Loop2
+
+	movq	(%rsp),%rbx
+	movq	1*8(%rsp),%r12
+	movq	2*8(%rsp),%r13
+	addq	$3*8,%rsp
+	ret
+
+	/* Some CPUs run faster using the string copy instructions.
+	   It is also a lot simpler. Use this when possible */
+
+#include <asm/cpufeature.h>
+
+	.section .altinstructions,"a"
+	.align 8
+	.quad  copy_page
+	.quad  copy_page_c
+	.byte  X86_FEATURE_REP_GOOD
+	.byte  copy_page_c_end-copy_page_c
+	.byte  copy_page_c_end-copy_page_c
+	.previous
+
+	.section .altinstr_replacement,"ax"
+copy_page_c:
 	movl $4096/8,%ecx
 	rep 
 	movsq 
 	ret
+copy_page_c_end:
+	.previous
diff --git a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S
index 79422b6..f64569b 100644
--- a/arch/x86_64/lib/copy_user.S
+++ b/arch/x86_64/lib/copy_user.S
@@ -4,9 +4,12 @@
  * Functions to copy from and to user space.		
  */		 
 
+#define FIX_ALIGNMENT 1
+
 	#include <asm/current.h>
 	#include <asm/asm-offsets.h>
 	#include <asm/thread_info.h>
+	#include <asm/cpufeature.h>
 
 /* Standard copy_to_user with segment limit checking */		
 	.globl copy_to_user
@@ -18,7 +21,23 @@
 	jc  bad_to_user
 	cmpq threadinfo_addr_limit(%rax),%rcx
 	jae bad_to_user
-	jmp copy_user_generic
+2:
+	.byte 0xe9	/* 32bit jump */
+	.long .Lcug-1f
+1:
+
+	.section .altinstr_replacement,"ax"
+3:	.byte 0xe9			/* replacement jmp with 8 bit immediate */
+	.long copy_user_generic_c-1b	/* offset */
+	.previous
+	.section .altinstructions,"a"
+	.align 8
+	.quad  2b
+	.quad  3b
+	.byte  X86_FEATURE_REP_GOOD
+	.byte  5
+	.byte  5
+	.previous
 
 /* Standard copy_from_user with segment limit checking */	
 	.globl copy_from_user
@@ -53,44 +72,230 @@
  * rsi source
  * rdx count
  *
- * Only 4GB of copy is supported. This shouldn't be a problem
- * because the kernel normally only writes from/to page sized chunks
- * even if user space passed a longer buffer.
- * And more would be dangerous because both Intel and AMD have
- * errata with rep movsq > 4GB. If someone feels the need to fix
- * this please consider this.
- *
  * Output:		
  * eax uncopied bytes or 0 if successful.
  */
-
 	.globl copy_user_generic
+	.p2align 4
 copy_user_generic:
+	.byte 0x66,0x66,0x90	/* 5 byte nop for replacement jump */
+	.byte 0x66,0x90
+1:
+	.section .altinstr_replacement,"ax"
+2:	.byte 0xe9	             /* near jump with 32bit immediate */
+	.long copy_user_generic_c-1b /* offset */
+	.previous
+	.section .altinstructions,"a"
+	.align 8
+	.quad  copy_user_generic
+	.quad  2b
+	.byte  X86_FEATURE_REP_GOOD
+	.byte  5
+	.byte  5
+	.previous
+.Lcug:
+	pushq %rbx
+	xorl %eax,%eax		/*zero for the exception handler */
+
+#ifdef FIX_ALIGNMENT
+	/* check for bad alignment of destination */
+	movl %edi,%ecx
+	andl $7,%ecx
+	jnz  .Lbad_alignment
+.Lafter_bad_alignment:
+#endif
+
+	movq %rdx,%rcx
+
+	movl $64,%ebx
+	shrq $6,%rdx
+	decq %rdx
+	js   .Lhandle_tail
+
+	.p2align 4
+.Lloop:
+.Ls1:	movq (%rsi),%r11
+.Ls2:	movq 1*8(%rsi),%r8
+.Ls3:	movq 2*8(%rsi),%r9
+.Ls4:	movq 3*8(%rsi),%r10
+.Ld1:	movq %r11,(%rdi)
+.Ld2:	movq %r8,1*8(%rdi)
+.Ld3:	movq %r9,2*8(%rdi)
+.Ld4:	movq %r10,3*8(%rdi)
+
+.Ls5:	movq 4*8(%rsi),%r11
+.Ls6:	movq 5*8(%rsi),%r8
+.Ls7:	movq 6*8(%rsi),%r9
+.Ls8:	movq 7*8(%rsi),%r10
+.Ld5:	movq %r11,4*8(%rdi)
+.Ld6:	movq %r8,5*8(%rdi)
+.Ld7:	movq %r9,6*8(%rdi)
+.Ld8:	movq %r10,7*8(%rdi)
+
+	decq %rdx
+
+	leaq 64(%rsi),%rsi
+	leaq 64(%rdi),%rdi
+
+	jns  .Lloop
+
+	.p2align 4
+.Lhandle_tail:
+	movl %ecx,%edx
+	andl $63,%ecx
+	shrl $3,%ecx
+	jz   .Lhandle_7
+	movl $8,%ebx
+	.p2align 4
+.Lloop_8:
+.Ls9:	movq (%rsi),%r8
+.Ld9:	movq %r8,(%rdi)
+	decl %ecx
+	leaq 8(%rdi),%rdi
+	leaq 8(%rsi),%rsi
+	jnz .Lloop_8
+
+.Lhandle_7:
+	movl %edx,%ecx
+	andl $7,%ecx
+	jz   .Lende
+	.p2align 4
+.Lloop_1:
+.Ls10:	movb (%rsi),%bl
+.Ld10:	movb %bl,(%rdi)
+	incq %rdi
+	incq %rsi
+	decl %ecx
+	jnz .Lloop_1
+
+.Lende:
+	popq %rbx
+	ret
+
+#ifdef FIX_ALIGNMENT
+	/* align destination */
+	.p2align 4
+.Lbad_alignment:
+	movl $8,%r9d
+	subl %ecx,%r9d
+	movl %r9d,%ecx
+	cmpq %r9,%rdx
+	jz   .Lhandle_7
+	js   .Lhandle_7
+.Lalign_1:
+.Ls11:	movb (%rsi),%bl
+.Ld11:	movb %bl,(%rdi)
+	incq %rsi
+	incq %rdi
+	decl %ecx
+	jnz .Lalign_1
+	subq %r9,%rdx
+	jmp .Lafter_bad_alignment
+#endif
+
+	/* table sorted by exception address */
+	.section __ex_table,"a"
+	.align 8
+	.quad .Ls1,.Ls1e
+	.quad .Ls2,.Ls2e
+	.quad .Ls3,.Ls3e
+	.quad .Ls4,.Ls4e
+	.quad .Ld1,.Ls1e
+	.quad .Ld2,.Ls2e
+	.quad .Ld3,.Ls3e
+	.quad .Ld4,.Ls4e
+	.quad .Ls5,.Ls5e
+	.quad .Ls6,.Ls6e
+	.quad .Ls7,.Ls7e
+	.quad .Ls8,.Ls8e
+	.quad .Ld5,.Ls5e
+	.quad .Ld6,.Ls6e
+	.quad .Ld7,.Ls7e
+	.quad .Ld8,.Ls8e
+	.quad .Ls9,.Le_quad
+	.quad .Ld9,.Le_quad
+	.quad .Ls10,.Le_byte
+	.quad .Ld10,.Le_byte
+#ifdef FIX_ALIGNMENT
+	.quad .Ls11,.Lzero_rest
+	.quad .Ld11,.Lzero_rest
+#endif
+	.quad .Le5,.Le_zero
+	.previous
+
+	/* compute 64-offset for main loop. 8 bytes accuracy with error on the
+	   pessimistic side. this is gross. it would be better to fix the
+	   interface. */
+	/* eax: zero, ebx: 64 */
+.Ls1e: 	addl $8,%eax
+.Ls2e: 	addl $8,%eax
+.Ls3e: 	addl $8,%eax
+.Ls4e: 	addl $8,%eax
+.Ls5e: 	addl $8,%eax
+.Ls6e: 	addl $8,%eax
+.Ls7e: 	addl $8,%eax
+.Ls8e: 	addl $8,%eax
+	addq %rbx,%rdi	/* +64 */
+	subq %rax,%rdi  /* correct destination with computed offset */
+
+	shlq $6,%rdx	/* loop counter * 64 (stride length) */
+	addq %rax,%rdx	/* add offset to loopcnt */
+	andl $63,%ecx	/* remaining bytes */
+	addq %rcx,%rdx	/* add them */
+	jmp .Lzero_rest
+
+	/* exception on quad word loop in tail handling */
+	/* ecx:	loopcnt/8, %edx: length, rdi: correct */
+.Le_quad:
+	shll $3,%ecx
+	andl $7,%edx
+	addl %ecx,%edx
+	/* edx: bytes to zero, rdi: dest, eax:zero */
+.Lzero_rest:
+	movq %rdx,%rcx
+.Le_byte:
+	xorl %eax,%eax
+.Le5:	rep
+	stosb
+	/* when there is another exception while zeroing the rest just return */
+.Le_zero:
+	movq %rdx,%rax
+	jmp .Lende
+
+	/* Some CPUs run faster using the string copy instructions.
+	   This is also a lot simpler. Use them when possible.
+	   Patch in jmps to this code instead of copying it fully
+	   to avoid unwanted aliasing in the exception tables. */
+
+ /* rdi	destination
+  * rsi source
+  * rdx count
+  *
+  * Output:
+  * eax uncopied bytes or 0 if successfull.
+  *
+  * Only 4GB of copy is supported. This shouldn't be a problem
+  * because the kernel normally only writes from/to page sized chunks
+  * even if user space passed a longer buffer.
+  * And more would be dangerous because both Intel and AMD have
+  * errata with rep movsq > 4GB. If someone feels the need to fix
+  * this please consider this.
+   */
+copy_user_generic_c:
 	movl %edx,%ecx
 	shrl $3,%ecx
 	andl $7,%edx	
-	jz   5f
 1:	rep 
 	movsq 
 	movl %edx,%ecx
-	xor %eax,%eax
 2:	rep
 	movsb
-	ret
-	/* align here? */
-5: 	xorl %eax,%eax
-6:	rep movsq
-	ret
-
-	.section .fixup,"ax"
-3:	lea (%rdx,%rcx,8),%rax
-	ret
 4:	movl %ecx,%eax
 	ret
-	.previous
+3:	lea (%rdx,%rcx,8),%rax
+	ret
 
 	.section __ex_table,"a"
 	.quad 1b,3b
 	.quad 2b,4b
-	.quad 6b,4b
 	.previous
diff --git a/arch/x86_64/lib/iomap_copy.S b/arch/x86_64/lib/iomap_copy.S
new file mode 100644
index 0000000..8bbade5
--- /dev/null
+++ b/arch/x86_64/lib/iomap_copy.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 PathScale, Inc.  All Rights Reserved.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * override generic version in lib/iomap_copy.c
+ */
+ 	.globl __iowrite32_copy
+	.p2align 4
+__iowrite32_copy:
+	movl %edx,%ecx
+	rep movsd
+	ret
diff --git a/arch/x86_64/lib/memcpy.S b/arch/x86_64/lib/memcpy.S
index 92dd805..5554948 100644
--- a/arch/x86_64/lib/memcpy.S
+++ b/arch/x86_64/lib/memcpy.S
@@ -11,8 +11,6 @@
  * 
  * Output:
  * rax original destination
- * 
- * TODO: check best memcpy for PSC
  */	
 
  	.globl __memcpy
@@ -20,6 +18,95 @@
 	.p2align 4
 __memcpy:
 memcpy:		
+	pushq %rbx
+	movq %rdi,%rax
+
+	movl %edx,%ecx
+	shrl $6,%ecx
+	jz .Lhandle_tail
+
+	.p2align 4
+.Lloop_64:
+	decl %ecx
+
+	movq (%rsi),%r11
+	movq 8(%rsi),%r8
+
+	movq %r11,(%rdi)
+	movq %r8,1*8(%rdi)
+
+	movq 2*8(%rsi),%r9
+	movq 3*8(%rsi),%r10
+
+	movq %r9,2*8(%rdi)
+	movq %r10,3*8(%rdi)
+
+	movq 4*8(%rsi),%r11
+	movq 5*8(%rsi),%r8
+
+	movq %r11,4*8(%rdi)
+	movq %r8,5*8(%rdi)
+
+	movq 6*8(%rsi),%r9
+	movq 7*8(%rsi),%r10
+
+	movq %r9,6*8(%rdi)
+	movq %r10,7*8(%rdi)
+
+	leaq 64(%rsi),%rsi
+	leaq 64(%rdi),%rdi
+	jnz  .Lloop_64
+
+.Lhandle_tail:
+	movl %edx,%ecx
+	andl $63,%ecx
+	shrl $3,%ecx
+	jz   .Lhandle_7
+	.p2align 4
+.Lloop_8:
+	decl %ecx
+	movq (%rsi),%r8
+	movq %r8,(%rdi)
+	leaq 8(%rdi),%rdi
+	leaq 8(%rsi),%rsi
+	jnz  .Lloop_8
+
+.Lhandle_7:
+	movl %edx,%ecx
+	andl $7,%ecx
+	jz .Lende
+	.p2align 4
+.Lloop_1:
+	movb (%rsi),%r8b
+	movb %r8b,(%rdi)
+	incq %rdi
+	incq %rsi
+	decl %ecx
+	jnz .Lloop_1
+
+.Lende:
+	popq %rbx
+	ret
+.Lfinal:
+
+	/* Some CPUs run faster using the string copy instructions.
+	   It is also a lot simpler. Use this when possible */
+
+	.section .altinstructions,"a"
+	.align 8
+	.quad  memcpy
+	.quad  memcpy_c
+	.byte  X86_FEATURE_REP_GOOD
+	.byte  .Lfinal-memcpy
+	.byte  memcpy_c_end-memcpy_c
+	.previous
+
+	.section .altinstr_replacement,"ax"
+ /* rdi	destination
+  * rsi source
+  * rdx count
+  */
+memcpy_c:
 	movq %rdi,%rax
 	movl %edx,%ecx
 	shrl $3,%ecx
@@ -30,3 +117,5 @@
 	rep
 	movsb
 	ret
+memcpy_c_end:
+	.previous
diff --git a/arch/x86_64/lib/memset.S b/arch/x86_64/lib/memset.S
index 2aa48f2..ad397f2 100644
--- a/arch/x86_64/lib/memset.S
+++ b/arch/x86_64/lib/memset.S
@@ -13,6 +13,98 @@
 	.p2align 4
 memset:	
 __memset:
+	movq %rdi,%r10
+	movq %rdx,%r11
+
+	/* expand byte value  */
+	movzbl %sil,%ecx
+	movabs $0x0101010101010101,%rax
+	mul    %rcx		/* with rax, clobbers rdx */
+
+	/* align dst */
+	movl  %edi,%r9d
+	andl  $7,%r9d
+	jnz  .Lbad_alignment
+.Lafter_bad_alignment:
+
+	movl %r11d,%ecx
+	shrl $6,%ecx
+	jz	 .Lhandle_tail
+
+	.p2align 4
+.Lloop_64:
+	decl   %ecx
+	movq  %rax,(%rdi)
+	movq  %rax,8(%rdi)
+	movq  %rax,16(%rdi)
+	movq  %rax,24(%rdi)
+	movq  %rax,32(%rdi)
+	movq  %rax,40(%rdi)
+	movq  %rax,48(%rdi)
+	movq  %rax,56(%rdi)
+	leaq  64(%rdi),%rdi
+	jnz    .Lloop_64
+
+	/* Handle tail in loops. The loops should be faster than hard
+	   to predict jump tables. */
+	.p2align 4
+.Lhandle_tail:
+	movl	%r11d,%ecx
+	andl    $63&(~7),%ecx
+	jz 		.Lhandle_7
+	shrl	$3,%ecx
+	.p2align 4
+.Lloop_8:
+	decl   %ecx
+	movq  %rax,(%rdi)
+	leaq  8(%rdi),%rdi
+	jnz    .Lloop_8
+
+.Lhandle_7:
+	movl	%r11d,%ecx
+	andl	$7,%ecx
+	jz      .Lende
+	.p2align 4
+.Lloop_1:
+	decl    %ecx
+	movb 	%al,(%rdi)
+	leaq	1(%rdi),%rdi
+	jnz     .Lloop_1
+
+.Lende:
+	movq	%r10,%rax
+	ret
+
+.Lbad_alignment:
+	cmpq $7,%r11
+	jbe	.Lhandle_7
+	movq %rax,(%rdi)	/* unaligned store */
+	movq $8,%r8
+	subq %r9,%r8
+	addq %r8,%rdi
+	subq %r8,%r11
+	jmp .Lafter_bad_alignment
+
+	/* Some CPUs run faster using the string instructions.
+	   It is also a lot simpler. Use this when possible */
+
+#include <asm/cpufeature.h>
+
+	.section .altinstructions,"a"
+	.align 8
+	.quad  memset
+	.quad  memset_c
+	.byte  X86_FEATURE_REP_GOOD
+	.byte  memset_c_end-memset_c
+	.byte  memset_c_end-memset_c
+	.previous
+
+	.section .altinstr_replacement,"ax"
+ /* rdi	destination
+  * rsi value
+  * rdx count
+  */
+memset_c:
 	movq %rdi,%r9
 	movl %edx,%r8d
 	andl $7,%r8d		
@@ -29,3 +121,5 @@
 	stosb
 	movq %r9,%rax
 	ret
+memset_c_end:
+	.previous
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 26eac19..2e7c3c8 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -33,7 +33,6 @@
 #include <asm/proto.h>
 #include <asm/kdebug.h>
 #include <asm-generic/sections.h>
-#include <asm/kdebug.h>
 
 /* Page fault error code bits */
 #define PF_PROT	(1<<0)		/* or no page found */
@@ -157,8 +156,8 @@
 
 	pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK); 
 	pgd += pgd_index(address);
-	printk("PGD %lx ", pgd_val(*pgd));
 	if (bad_address(pgd)) goto bad;
+	printk("PGD %lx ", pgd_val(*pgd));
 	if (!pgd_present(*pgd)) goto ret; 
 
 	pud = __pud_offset_k((pud_t *)pgd_page(*pgd), address);
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 8b7f856..cd25300 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -26,6 +26,10 @@
 static struct node nodes[MAX_NUMNODES] __initdata;
 static u8 pxm2node[256] = { [0 ... 255] = 0xff };
 
+/* Too small nodes confuse the VM badly. Usually they result
+   from BIOS bugs. */
+#define NODE_MIN_SIZE (4*1024*1024)
+
 static int node_to_pxm(int n);
 
 int pxm_to_node(int pxm)
@@ -131,7 +135,12 @@
 acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
 {
 	int pxm, node;
-	if (srat_disabled() || pa->flags.enabled == 0)
+	if (srat_disabled())
+		return;
+	if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) {		bad_srat();
+		return;
+	}
+	if (pa->flags.enabled == 0)
 		return;
 	pxm = pa->proximity_domain;
 	node = setup_node(pxm);
@@ -155,8 +164,16 @@
 	int node, pxm;
 	int i;
 
-	if (srat_disabled() || ma->flags.enabled == 0)
+	if (srat_disabled())
 		return;
+	if (ma->header.length != sizeof(struct acpi_table_memory_affinity)) {
+		bad_srat();
+		return;
+	}
+	if (ma->flags.enabled == 0)
+		return;
+	start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32);
+	end = start + (ma->length_lo | ((u64)ma->length_hi << 32));
 	pxm = ma->proximity_domain;
 	node = setup_node(pxm);
 	if (node < 0) {
@@ -164,8 +181,6 @@
 		bad_srat();
 		return;
 	}
-	start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32);
-	end = start + (ma->length_lo | ((u64)ma->length_hi << 32));
 	/* It is fine to add this area to the nodes data it will be used later*/
 	if (ma->flags.hot_pluggable == 1)
 		printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n",
@@ -223,6 +238,16 @@
 	return 1;
 }
 
+static void unparse_node(int node)
+{
+	int i;
+	node_clear(node, nodes_parsed);
+	for (i = 0; i < MAX_LOCAL_APIC; i++) {
+		if (apicid_to_node[i] == node)
+			apicid_to_node[i] = NUMA_NO_NODE;
+	}
+}
+
 void __init acpi_numa_arch_fixup(void) {}
 
 /* Use the information discovered above to actually set up the nodes. */
@@ -230,16 +255,16 @@
 {
 	int i;
 
+	/* First clean up the node list */
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		cutoff_node(i, start, end);
+		if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE)
+			unparse_node(i);
+	}
+
 	if (acpi_numa <= 0)
 		return -1;
 
-	/* First clean up the node list */
-	for_each_node_mask(i, nodes_parsed) {
-		cutoff_node(i, start, end);
-		if (nodes[i].start == nodes[i].end)
-			node_clear(i, nodes_parsed);
-	}
-
 	if (!nodes_cover_memory()) {
 		bad_srat();
 		return -1;
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index f16c0d5..18f371f 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -29,11 +29,8 @@
 
 	while (1) {
 		++cfg_num;
-		if (cfg_num >= pci_mmcfg_config_num) {
-			/* Not found - fall back to type 1. This happens
-			   e.g. on the internal devices of a K8 northbridge. */
-			return NULL;
-		}
+		if (cfg_num >= pci_mmcfg_config_num)
+			break;
 		cfg = pci_mmcfg_virt[cfg_num].cfg;
 		if (cfg->pci_segment_group_number != seg)
 			continue;
@@ -41,6 +38,18 @@
 		    (cfg->end_bus_number >= bus))
 			return pci_mmcfg_virt[cfg_num].virt;
 	}
+
+	/* Handle more broken MCFG tables on Asus etc.
+	   They only contain a single entry for bus 0-0. Assume
+ 	   this applies to all busses. */
+	cfg = &pci_mmcfg_config[0];
+	if (pci_mmcfg_config_num == 1 &&
+		cfg->pci_segment_group_number == 0 &&
+		(cfg->start_bus_number | cfg->end_bus_number) == 0)
+		return pci_mmcfg_virt[0].virt;
+
+	/* Fall back to type 0 */
+	return NULL;
 }
 
 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c
index 4fbddf9..94fdfe4 100644
--- a/arch/xtensa/platform-iss/console.c
+++ b/arch/xtensa/platform-iss/console.c
@@ -128,9 +128,7 @@
 
 	while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){
 		__simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0);
-		tty->flip.count++;
-		*tty->flip.char_buf_ptr++ = c;
-		*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
+		tty_insert_flip_char(tty, c, TTY_NORMAL);
 		i++;
 	}
 
diff --git a/block/elevator.c b/block/elevator.c
index c9f424d..24b702d 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -139,35 +139,16 @@
 
 static char chosen_elevator[16];
 
-static void elevator_setup_default(void)
+static int __init elevator_setup(char *str)
 {
-	struct elevator_type *e;
-
-	/*
-	 * If default has not been set, use the compiled-in selection.
-	 */
-	if (!chosen_elevator[0])
-		strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED);
-
 	/*
 	 * Be backwards-compatible with previous kernels, so users
 	 * won't get the wrong elevator.
 	 */
-	if (!strcmp(chosen_elevator, "as"))
+	if (!strcmp(str, "as"))
 		strcpy(chosen_elevator, "anticipatory");
-
- 	/*
- 	 * If the given scheduler is not available, fall back to the default
- 	 */
- 	if ((e = elevator_find(chosen_elevator)))
-		elevator_put(e);
 	else
- 		strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED);
-}
-
-static int __init elevator_setup(char *str)
-{
-	strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1);
+		strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1);
 	return 0;
 }
 
@@ -184,15 +165,17 @@
 	q->end_sector = 0;
 	q->boundary_rq = NULL;
 
-	elevator_setup_default();
-
-	if (!name)
-		name = chosen_elevator;
-
-	e = elevator_get(name);
-	if (!e)
+	if (name && !(e = elevator_get(name)))
 		return -EINVAL;
 
+	if (!e && *chosen_elevator && !(e = elevator_get(chosen_elevator)))
+		printk("I/O scheduler %s not found\n", chosen_elevator);
+
+	if (!e && !(e = elevator_get(CONFIG_DEFAULT_IOSCHED))) {
+		printk("Default I/O scheduler not found, using no-op\n");
+		e = elevator_get("noop");
+	}
+
 	eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL);
 	if (!eq) {
 		elevator_put(e);
@@ -310,7 +293,7 @@
 
 	rq->flags &= ~REQ_STARTED;
 
-	__elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE, 0);
+	elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE);
 }
 
 static void elv_drain_elevator(request_queue_t *q)
@@ -327,40 +310,11 @@
 	}
 }
 
-void __elv_add_request(request_queue_t *q, struct request *rq, int where,
-		       int plug)
+void elv_insert(request_queue_t *q, struct request *rq, int where)
 {
 	struct list_head *pos;
 	unsigned ordseq;
 
-	if (q->ordcolor)
-		rq->flags |= REQ_ORDERED_COLOR;
-
-	if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
-		/*
-		 * toggle ordered color
-		 */
-		q->ordcolor ^= 1;
-
-		/*
-		 * barriers implicitly indicate back insertion
-		 */
-		if (where == ELEVATOR_INSERT_SORT)
-			where = ELEVATOR_INSERT_BACK;
-
-		/*
-		 * this request is scheduling boundary, update end_sector
-		 */
-		if (blk_fs_request(rq)) {
-			q->end_sector = rq_end_sector(rq);
-			q->boundary_rq = rq;
-		}
-	} else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
-		where = ELEVATOR_INSERT_BACK;
-
-	if (plug)
-		blk_plug_device(q);
-
 	rq->q = q;
 
 	switch (where) {
@@ -441,6 +395,42 @@
 	}
 }
 
+void __elv_add_request(request_queue_t *q, struct request *rq, int where,
+		       int plug)
+{
+	if (q->ordcolor)
+		rq->flags |= REQ_ORDERED_COLOR;
+
+	if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
+		/*
+		 * toggle ordered color
+		 */
+		if (blk_barrier_rq(rq))
+			q->ordcolor ^= 1;
+
+		/*
+		 * barriers implicitly indicate back insertion
+		 */
+		if (where == ELEVATOR_INSERT_SORT)
+			where = ELEVATOR_INSERT_BACK;
+
+		/*
+		 * this request is scheduling boundary, update
+		 * end_sector
+		 */
+		if (blk_fs_request(rq)) {
+			q->end_sector = rq_end_sector(rq);
+			q->boundary_rq = rq;
+		}
+	} else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
+		where = ELEVATOR_INSERT_BACK;
+
+	if (plug)
+		blk_plug_device(q);
+
+	elv_insert(q, rq, where);
+}
+
 void elv_add_request(request_queue_t *q, struct request *rq, int where,
 		     int plug)
 {
@@ -669,8 +659,10 @@
 	spin_unlock_irq(&elv_list_lock);
 
 	printk(KERN_INFO "io scheduler %s registered", e->elevator_name);
-	if (!strcmp(e->elevator_name, chosen_elevator))
-		printk(" (default)");
+	if (!strcmp(e->elevator_name, chosen_elevator) ||
+			(!*chosen_elevator &&
+			 !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED)))
+				printk(" (default)");
 	printk("\n");
 	return 0;
 }
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 8e27d0a..03d9c82 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -304,6 +304,7 @@
  * blk_queue_ordered - does this queue support ordered writes
  * @q:        the request queue
  * @ordered:  one of QUEUE_ORDERED_*
+ * @prepare_flush_fn: rq setup helper for cache flush ordered writes
  *
  * Description:
  *   For journalled file systems, doing ordered writes on a commit
@@ -332,6 +333,7 @@
 		return -EINVAL;
 	}
 
+	q->ordered = ordered;
 	q->next_ordered = ordered;
 	q->prepare_flush_fn = prepare_flush_fn;
 
@@ -452,7 +454,7 @@
 	rq->end_io = end_io;
 	q->prepare_flush_fn(q, rq);
 
-	__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
+	elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
 }
 
 static inline struct request *start_ordered(request_queue_t *q,
@@ -488,7 +490,7 @@
 	else
 		q->ordseq |= QUEUE_ORDSEQ_POSTFLUSH;
 
-	__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
+	elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
 
 	if (q->ordered & QUEUE_ORDERED_PREFLUSH) {
 		queue_flush(q, QUEUE_ORDERED_PREFLUSH);
@@ -506,7 +508,7 @@
 
 int blk_do_ordered(request_queue_t *q, struct request **rqp)
 {
-	struct request *rq = *rqp, *allowed_rq;
+	struct request *rq = *rqp;
 	int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq);
 
 	if (!q->ordseq) {
@@ -530,32 +532,26 @@
 		}
 	}
 
+	/*
+	 * Ordered sequence in progress
+	 */
+
+	/* Special requests are not subject to ordering rules. */
+	if (!blk_fs_request(rq) &&
+	    rq != &q->pre_flush_rq && rq != &q->post_flush_rq)
+		return 1;
+
 	if (q->ordered & QUEUE_ORDERED_TAG) {
+		/* Ordered by tag.  Blocking the next barrier is enough. */
 		if (is_barrier && rq != &q->bar_rq)
 			*rqp = NULL;
-		return 1;
+	} else {
+		/* Ordered by draining.  Wait for turn. */
+		WARN_ON(blk_ordered_req_seq(rq) < blk_ordered_cur_seq(q));
+		if (blk_ordered_req_seq(rq) > blk_ordered_cur_seq(q))
+			*rqp = NULL;
 	}
 
-	switch (blk_ordered_cur_seq(q)) {
-	case QUEUE_ORDSEQ_PREFLUSH:
-		allowed_rq = &q->pre_flush_rq;
-		break;
-	case QUEUE_ORDSEQ_BAR:
-		allowed_rq = &q->bar_rq;
-		break;
-	case QUEUE_ORDSEQ_POSTFLUSH:
-		allowed_rq = &q->post_flush_rq;
-		break;
-	default:
-		allowed_rq = NULL;
-		break;
-	}
-
-	if (rq != allowed_rq &&
-	    (blk_fs_request(rq) || rq == &q->pre_flush_rq ||
-	     rq == &q->post_flush_rq))
-		*rqp = NULL;
-
 	return 1;
 }
 
@@ -662,7 +658,7 @@
  *    Enables a low level driver to set an upper limit on the size of
  *    received requests.
  **/
-void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors)
+void blk_queue_max_sectors(request_queue_t *q, unsigned int max_sectors)
 {
 	if ((max_sectors << 9) < PAGE_CACHE_SIZE) {
 		max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
@@ -2577,6 +2573,8 @@
 	disk->stamp = now;
 }
 
+EXPORT_SYMBOL_GPL(disk_round_stats);
+
 /*
  * queue lock must be held
  */
@@ -2632,6 +2630,7 @@
 /**
  * blk_end_sync_rq - executes a completion event on a request
  * @rq: request to complete
+ * @error: end io status of the request
  */
 void blk_end_sync_rq(struct request *rq, int error)
 {
@@ -3153,7 +3152,7 @@
 	if (blk_fs_request(req) && req->rq_disk) {
 		const int rw = rq_data_dir(req);
 
-		__disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9);
+		disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9);
 	}
 
 	total_bytes = bio_nbytes = 0;
@@ -3448,7 +3447,7 @@
 	iocontext_cachep = kmem_cache_create("blkdev_ioc",
 			sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL);
 
-	for (i = 0; i < NR_CPUS; i++)
+	for_each_cpu(i)
 		INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
 
 	open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index cc72210..24f7af9 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -310,6 +310,8 @@
 	if (!rq->timeout)
 		rq->timeout = BLK_DEFAULT_TIMEOUT;
 
+	rq->retries = 0;
+
 	start_time = jiffies;
 
 	/* ignore return value. All information is passed back to caller
@@ -427,6 +429,7 @@
 	rq->data = buffer;
 	rq->data_len = bytes;
 	rq->flags |= REQ_BLOCK_PC;
+	rq->retries = 0;
 
 	blk_execute_rq(q, bd_disk, rq, 0);
 	err = rq->errors & 0xff;	/* only 8 bit SCSI status */
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index 47ac90e..2953e2c 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -17,7 +17,6 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
-#include <asm/bug.h>
 #include <asm/scatterlist.h>
 #include "internal.h"
 #include "scatterwalk.h"
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 283c089..bddf431 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -68,4 +68,6 @@
 
 source "drivers/sn/Kconfig"
 
+source "drivers/edac/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 7c45050..5c69b86 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -63,12 +63,13 @@
 obj-$(CONFIG_MD)		+= md/
 obj-$(CONFIG_BT)		+= bluetooth/
 obj-$(CONFIG_ISDN)		+= isdn/
+obj-$(CONFIG_EDAC)		+= edac/
 obj-$(CONFIG_MCA)		+= mca/
 obj-$(CONFIG_EISA)		+= eisa/
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
 obj-$(CONFIG_MMC)		+= mmc/
 obj-$(CONFIG_INFINIBAND)	+= infiniband/
-obj-$(CONFIG_SGI_IOC4)		+= sn/
+obj-$(CONFIG_SGI_SN)		+= sn/
 obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
 obj-$(CONFIG_SUPERH)		+= sh/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 6d61945..0cce28c 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -267,7 +267,6 @@
 
 config ACPI_EC
 	bool
-	depends on X86
 	default y
 	help
 	  This driver is required on some systems for the proper operation of
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 2143609..d882bf8 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -71,8 +71,8 @@
 struct acpi_memory_device {
 	acpi_handle handle;
 	unsigned int state;	/* State of the memory device */
-	unsigned short cache_attribute;	/* memory cache attribute */
-	unsigned short read_write_attribute;	/* memory read/write attribute */
+	unsigned short caching;	/* memory cache attribute */
+	unsigned short write_protect;	/* memory read/write attribute */
 	u64 start_addr;		/* Memory Range start physical addr */
 	u64 end_addr;		/* Memory Range end physical addr */
 };
@@ -97,12 +97,12 @@
 	if (ACPI_SUCCESS(status)) {
 		if (address64.resource_type == ACPI_MEMORY_RANGE) {
 			/* Populate the structure */
-			mem_device->cache_attribute =
-			    address64.attribute.memory.cache_attribute;
-			mem_device->read_write_attribute =
-			    address64.attribute.memory.read_write_attribute;
-			mem_device->start_addr = address64.min_address_range;
-			mem_device->end_addr = address64.max_address_range;
+			mem_device->caching =
+			    address64.info.mem.caching;
+			mem_device->write_protect =
+			    address64.info.mem.write_protect;
+			mem_device->start_addr = address64.minimum;
+			mem_device->end_addr = address64.maximum;
 		}
 	}
 
@@ -250,7 +250,6 @@
 	int result;
 	u64 start = mem_device->start_addr;
 	u64 len = mem_device->end_addr - start + 1;
-	unsigned long attr = mem_device->read_write_attribute;
 
 	ACPI_FUNCTION_TRACE("acpi_memory_disable_device");
 
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index fec895a..f4c8775 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -78,9 +78,9 @@
 static uid_t asus_uid;
 static gid_t asus_gid;
 module_param(asus_uid, uint, 0);
-MODULE_PARM_DESC(uid, "UID for entries in /proc/acpi/asus.\n");
+MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus.\n");
 module_param(asus_gid, uint, 0);
-MODULE_PARM_DESC(gid, "GID for entries in /proc/acpi/asus.\n");
+MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus.\n");
 
 /* For each model, all features implemented, 
  * those marked with R are relative to HOTK, A for absolute */
@@ -302,7 +302,7 @@
 	 .brightness_set = "SPLV",
 	 .brightness_get = "GPLV",
 	 .display_set = "SDSP",
-	 .display_get = "\\SSTE"},
+	 .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
 	{
 	 .name = "M6R",
 	 .mt_mled = "MLED",
@@ -851,6 +851,8 @@
 		mode = S_IFREG | S_IRUGO | S_IWUGO;
 	} else {
 		mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
+		printk(KERN_WARNING "  asus_uid and asus_gid parameters are "
+		       "deprecated, use chown and chmod instead!\n");
 	}
 
 	acpi_device_dir(device) = asus_proc_dir;
@@ -987,9 +989,21 @@
 		printk(KERN_NOTICE "  BSTS called, 0x%02x returned\n",
 		       bsts_result);
 
-	/* Samsung P30 has a device with a valid _HID whose INIT does not 
-	 * return anything. Catch this one and any similar here */
-	if (buffer.pointer == NULL) {
+	/* This is unlikely with implicit return */
+	if (buffer.pointer == NULL)
+		return -EINVAL;
+
+	model = (union acpi_object *) buffer.pointer;
+	/*
+	 * Samsung P30 has a device with a valid _HID whose INIT does not 
+	 * return anything. It used to be possible to catch this exception,
+	 * but the implicit return code will now happily confuse the 
+	 * driver. We assume that every ACPI_TYPE_STRING is a valid model
+	 * identifier but it's still possible to get completely bogus data.
+	 */
+	if (model->type == ACPI_TYPE_STRING) {
+		printk(KERN_NOTICE "  %s model detected, ", model->string.pointer);
+	} else {
 		if (asus_info &&	/* Samsung P30 */
 		    strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
 			hotk->model = P30;
@@ -1002,13 +1016,10 @@
 			       "the developers with your DSDT\n");
 		}
 		hotk->methods = &model_conf[hotk->model];
-		return AE_OK;
-	}
+		
+		acpi_os_free(model);
 
-	model = (union acpi_object *)buffer.pointer;
-	if (model->type == ACPI_TYPE_STRING) {
-		printk(KERN_NOTICE "  %s model detected, ",
-		       model->string.pointer);
+		return AE_OK;
 	}
 
 	hotk->model = END_MODEL;
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
index 2022aea..76bc046 100644
--- a/drivers/acpi/dispatcher/dsfield.c
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -128,7 +128,7 @@
 				   ACPI_IMODE_LOAD_PASS1, flags, walk_state,
 				   &(node));
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_NSERROR(arg->common.value.string, status);
+			ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
 			return_ACPI_STATUS(status);
 		}
 	}
@@ -232,7 +232,8 @@
 			    + (acpi_integer) arg->common.value.size;
 
 			if (position > ACPI_UINT32_MAX) {
-				ACPI_REPORT_ERROR(("Bit offset within field too large (> 0xFFFFFFFF)\n"));
+				ACPI_ERROR((AE_INFO,
+					    "Bit offset within field too large (> 0xFFFFFFFF)"));
 				return_ACPI_STATUS(AE_SUPPORT);
 			}
 
@@ -268,8 +269,8 @@
 						ACPI_NS_DONT_OPEN_SCOPE,
 						walk_state, &info->field_node);
 			if (ACPI_FAILURE(status)) {
-				ACPI_REPORT_NSERROR((char *)&arg->named.name,
-						    status);
+				ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
+						     status);
 				if (status != AE_ALREADY_EXISTS) {
 					return_ACPI_STATUS(status);
 				}
@@ -293,7 +294,11 @@
 			    + (acpi_integer) arg->common.value.size;
 
 			if (position > ACPI_UINT32_MAX) {
-				ACPI_REPORT_ERROR(("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n", (char *)&info->field_node->name));
+				ACPI_ERROR((AE_INFO,
+					    "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
+					    ACPI_CAST_PTR(char,
+							  &info->field_node->
+							  name)));
 				return_ACPI_STATUS(AE_SUPPORT);
 			}
 
@@ -302,9 +307,9 @@
 
 		default:
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Invalid opcode in field list: %X\n",
-					  arg->common.aml_opcode));
+			ACPI_ERROR((AE_INFO,
+				    "Invalid opcode in field list: %X",
+				    arg->common.aml_opcode));
 			return_ACPI_STATUS(AE_AML_BAD_OPCODE);
 		}
 
@@ -349,7 +354,7 @@
 				   ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
 				   walk_state, &region_node);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_NSERROR(arg->common.value.name, status);
+			ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
 			return_ACPI_STATUS(status);
 		}
 	}
@@ -431,8 +436,8 @@
 						ACPI_NS_ERROR_IF_FOUND,
 						walk_state, &node);
 			if (ACPI_FAILURE(status)) {
-				ACPI_REPORT_NSERROR((char *)&arg->named.name,
-						    status);
+				ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
+						     status);
 				if (status != AE_ALREADY_EXISTS) {
 					return_ACPI_STATUS(status);
 				}
@@ -488,7 +493,7 @@
 				   ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
 				   walk_state, &region_node);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_NSERROR(arg->common.value.name, status);
+			ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
 			return_ACPI_STATUS(status);
 		}
 	}
@@ -502,7 +507,7 @@
 			   ACPI_NS_SEARCH_PARENT, walk_state,
 			   &info.register_node);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_NSERROR(arg->common.value.string, status);
+		ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
 		return_ACPI_STATUS(status);
 	}
 
@@ -560,7 +565,7 @@
 			   ACPI_NS_SEARCH_PARENT, walk_state,
 			   &info.register_node);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_NSERROR(arg->common.value.string, status);
+		ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
 		return_ACPI_STATUS(status);
 	}
 
@@ -573,7 +578,7 @@
 			   ACPI_NS_SEARCH_PARENT, walk_state,
 			   &info.data_register_node);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_NSERROR(arg->common.value.string, status);
+		ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
 		return_ACPI_STATUS(status);
 	}
 
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
index 8693c70..e65a07a 100644
--- a/drivers/acpi/dispatcher/dsinit.c
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -84,7 +84,7 @@
 	acpi_object_type type;
 	acpi_status status;
 
-	ACPI_FUNCTION_NAME("ds_init_one_object");
+	ACPI_FUNCTION_ENTRY();
 
 	/*
 	 * We are only interested in NS nodes owned by the table that
@@ -105,11 +105,10 @@
 
 		status = acpi_ds_initialize_region(obj_handle);
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Region %p [%4.4s] - Init failure, %s\n",
-					  obj_handle,
-					  acpi_ut_get_node_name(obj_handle),
-					  acpi_format_exception(status)));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"During Region initialization %p [%4.4s]",
+					obj_handle,
+					acpi_ut_get_node_name(obj_handle)));
 		}
 
 		info->op_region_count++;
@@ -118,14 +117,6 @@
 	case ACPI_TYPE_METHOD:
 
 		/*
-		 * Print a dot for each method unless we are going to print
-		 * the entire pathname
-		 */
-		if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
-			ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
-		}
-
-		/*
 		 * Set the execution data width (32 or 64) based upon the
 		 * revision number of the parent ACPI table.
 		 * TBD: This is really for possible future support of integer width
@@ -134,6 +125,21 @@
 		if (info->table_desc->pointer->revision == 1) {
 			node->flags |= ANOBJ_DATA_WIDTH_32;
 		}
+#ifdef ACPI_INIT_PARSE_METHODS
+		/*
+		 * Note 11/2005: Removed this code to parse all methods during table
+		 * load because it causes problems if there are any errors during the
+		 * parse. Also, it seems like overkill and we probably don't want to
+		 * abort a table load because of an issue with a single method.
+		 */
+
+		/*
+		 * Print a dot for each method unless we are going to print
+		 * the entire pathname
+		 */
+		if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
+			ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
+		}
 
 		/*
 		 * Always parse methods to detect errors, we will delete
@@ -141,15 +147,15 @@
 		 */
 		status = acpi_ds_parse_method(obj_handle);
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "\n+Method %p [%4.4s] - parse failure, %s\n",
-					  obj_handle,
-					  acpi_ut_get_node_name(obj_handle),
-					  acpi_format_exception(status)));
+			ACPI_ERROR((AE_INFO,
+				    "Method %p [%4.4s] - parse failure, %s",
+				    obj_handle,
+				    acpi_ut_get_node_name(obj_handle),
+				    acpi_format_exception(status)));
 
 			/* This parse failed, but we will continue parsing more methods */
 		}
-
+#endif
 		info->method_count++;
 		break;
 
@@ -207,8 +213,7 @@
 	status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
 				     acpi_ds_init_one_object, &info, NULL);
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed, %s\n",
-				  acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
 	}
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 36c1ca0..c475546 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,135 +47,66 @@
 #include <acpi/acdispat.h>
 #include <acpi/acinterp.h>
 #include <acpi/acnamesp.h>
+#include <acpi/acdisasm.h>
 
 #define _COMPONENT          ACPI_DISPATCHER
 ACPI_MODULE_NAME("dsmethod")
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ds_parse_method
+ * FUNCTION:    acpi_ds_method_error
  *
- * PARAMETERS:  Node        - Method node
+ * PARAMETERS:  Status          - Execution status
+ *              walk_state      - Current state
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Parse the AML that is associated with the method.
+ * DESCRIPTION: Called on method error. Invoke the global exception handler if
+ *              present, dump the method data if the disassembler is configured
  *
- * MUTEX:       Assumes parser is locked
+ *              Note: Allows the exception handler to change the status code
  *
  ******************************************************************************/
-acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
+acpi_status
+acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
 {
-	acpi_status status;
-	union acpi_operand_object *obj_desc;
-	union acpi_parse_object *op;
-	struct acpi_walk_state *walk_state;
+	ACPI_FUNCTION_ENTRY();
 
-	ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
+	/* Ignore AE_OK and control exception codes */
 
-	/* Parameter Validation */
-
-	if (!node) {
-		return_ACPI_STATUS(AE_NULL_ENTRY);
+	if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) {
+		return (status);
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-			  "**** Parsing [%4.4s] **** named_obj=%p\n",
-			  acpi_ut_get_node_name(node), node));
+	/* Invoke the global exception handler */
 
-	/* Extract the method object from the method Node */
+	if (acpi_gbl_exception_handler) {
+		/* Exit the interpreter, allow handler to execute methods */
 
-	obj_desc = acpi_ns_get_attached_object(node);
-	if (!obj_desc) {
-		return_ACPI_STATUS(AE_NULL_OBJECT);
+		acpi_ex_exit_interpreter();
+
+		/*
+		 * Handler can map the exception code to anything it wants, including
+		 * AE_OK, in which case the executing method will not be aborted.
+		 */
+		status = acpi_gbl_exception_handler(status,
+						    walk_state->method_node ?
+						    walk_state->method_node->
+						    name.integer : 0,
+						    walk_state->opcode,
+						    walk_state->aml_offset,
+						    NULL);
+		(void)acpi_ex_enter_interpreter();
 	}
-
-	/* Create a mutex for the method if there is a concurrency limit */
-
-	if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
-	    (!obj_desc->method.semaphore)) {
-		status = acpi_os_create_semaphore(obj_desc->method.concurrency,
-						  obj_desc->method.concurrency,
-						  &obj_desc->method.semaphore);
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
-
-	/*
-	 * Allocate a new parser op to be the root of the parsed
-	 * method tree
-	 */
-	op = acpi_ps_alloc_op(AML_METHOD_OP);
-	if (!op) {
-		return_ACPI_STATUS(AE_NO_MEMORY);
-	}
-
-	/* Init new op with the method name and pointer back to the Node */
-
-	acpi_ps_set_name(op, node->name.integer);
-	op->common.node = node;
-
-	/*
-	 * Get a new owner_id for objects created by this method. Namespace
-	 * objects (such as Operation Regions) can be created during the
-	 * first pass parse.
-	 */
-	status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
+#ifdef ACPI_DISASSEMBLER
 	if (ACPI_FAILURE(status)) {
-		goto cleanup;
+		/* Display method locals/args if disassembler is present */
+
+		acpi_dm_dump_method_info(status, walk_state, walk_state->op);
 	}
+#endif
 
-	/* Create and initialize a new walk state */
-
-	walk_state =
-	    acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
-				      NULL);
-	if (!walk_state) {
-		status = AE_NO_MEMORY;
-		goto cleanup2;
-	}
-
-	status = acpi_ds_init_aml_walk(walk_state, op, node,
-				       obj_desc->method.aml_start,
-				       obj_desc->method.aml_length, NULL, 1);
-	if (ACPI_FAILURE(status)) {
-		acpi_ds_delete_walk_state(walk_state);
-		goto cleanup2;
-	}
-
-	/*
-	 * Parse the method, first pass
-	 *
-	 * The first pass load is where newly declared named objects are added into
-	 * the namespace.  Actual evaluation of the named objects (what would be
-	 * called a "second pass") happens during the actual execution of the
-	 * method so that operands to the named objects can take on dynamic
-	 * run-time values.
-	 */
-	status = acpi_ps_parse_aml(walk_state);
-	if (ACPI_FAILURE(status)) {
-		goto cleanup2;
-	}
-
-	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-			  "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
-			  acpi_ut_get_node_name(node), node, op));
-
-	/*
-	 * Delete the parse tree. We simply re-parse the method for every
-	 * execution since there isn't much overhead (compared to keeping lots
-	 * of parse trees around)
-	 */
-	acpi_ns_delete_namespace_subtree(node);
-	acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
-
-      cleanup2:
-	acpi_ut_release_owner_id(&obj_desc->method.owner_id);
-
-      cleanup:
-	acpi_ps_delete_parse_tree(op);
-	return_ACPI_STATUS(status);
+	return (status);
 }
 
 /*******************************************************************************
@@ -195,9 +126,9 @@
  ******************************************************************************/
 
 acpi_status
-acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
-			       union acpi_operand_object *obj_desc,
-			       struct acpi_namespace_node *calling_method_node)
+acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
+			       union acpi_operand_object * obj_desc,
+			       struct acpi_namespace_node * calling_method_node)
 {
 	acpi_status status = AE_OK;
 
@@ -210,7 +141,8 @@
 	/* Prevent wraparound of thread count */
 
 	if (obj_desc->method.thread_count == ACPI_UINT8_MAX) {
-		ACPI_REPORT_ERROR(("Method reached maximum reentrancy limit (255)\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Method reached maximum reentrancy limit (255)"));
 		return_ACPI_STATUS(AE_AML_METHOD_LIMIT);
 	}
 
@@ -539,22 +471,61 @@
 		    acpi_os_signal_semaphore(walk_state->method_desc->method.
 					     semaphore, 1);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("Could not signal method semaphore\n"));
+			ACPI_ERROR((AE_INFO,
+				    "Could not signal method semaphore"));
 
 			/* Ignore error and continue cleanup */
 		}
 	}
 
+	/*
+	 * There are no more threads executing this method.  Perform
+	 * additional cleanup.
+	 *
+	 * The method Node is stored in the walk state
+	 */
+	method_node = walk_state->method_node;
+
+	/* Lock namespace for possible update */
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		goto exit;
+	}
+
+	/*
+	 * Delete any namespace entries created immediately underneath
+	 * the method
+	 */
+	if (method_node->child) {
+		acpi_ns_delete_namespace_subtree(method_node);
+	}
+
+	/*
+	 * Delete any namespace entries created anywhere else within
+	 * the namespace by the execution of this method
+	 */
+	acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method.
+					  owner_id);
+	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
+	/* Are there any other threads currently executing this method? */
+
 	if (walk_state->method_desc->method.thread_count) {
+		/*
+		 * Additional threads. Do not release the owner_id in this case,
+		 * we immediately reuse it for the next thread executing this method
+		 */
 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "*** Not deleting method namespace, there are still %d threads\n",
+				  "*** Completed execution of one thread, %d threads remaining\n",
 				  walk_state->method_desc->method.
 				  thread_count));
-	} else {		/* This is the last executing thread */
+	} else {
+		/* This is the only executing thread for this method */
 
 		/*
 		 * Support to dynamically change a method from not_serialized to
-		 * Serialized if it appears that the method is written foolishly and
+		 * Serialized if it appears that the method is incorrectly written and
 		 * does not support multiple thread execution.  The best example of this
 		 * is if such a method creates namespace objects and blocks.  A second
 		 * thread will fail with an AE_ALREADY_EXISTS exception
@@ -570,34 +541,8 @@
 							  semaphore);
 		}
 
-		/*
-		 * There are no more threads executing this method.  Perform
-		 * additional cleanup.
-		 *
-		 * The method Node is stored in the walk state
-		 */
-		method_node = walk_state->method_node;
+		/* No more threads, we can free the owner_id */
 
-		/*
-		 * Delete any namespace entries created immediately underneath
-		 * the method
-		 */
-		status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-		if (ACPI_FAILURE(status)) {
-			goto exit;
-		}
-
-		if (method_node->child) {
-			acpi_ns_delete_namespace_subtree(method_node);
-		}
-
-		/*
-		 * Delete any namespace entries created anywhere else within
-		 * the namespace
-		 */
-		acpi_ns_delete_namespace_by_owner(walk_state->method_desc->
-						  method.owner_id);
-		status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 		acpi_ut_release_owner_id(&walk_state->method_desc->method.
 					 owner_id);
 	}
@@ -606,3 +551,140 @@
 	(void)acpi_ut_release_mutex(ACPI_MTX_PARSER);
 	return_VOID;
 }
+
+#ifdef ACPI_INIT_PARSE_METHODS
+	/*
+	 * Note 11/2005: Removed this code to parse all methods during table
+	 * load because it causes problems if there are any errors during the
+	 * parse. Also, it seems like overkill and we probably don't want to
+	 * abort a table load because of an issue with a single method.
+	 */
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_parse_method
+ *
+ * PARAMETERS:  Node        - Method node
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Parse the AML that is associated with the method.
+ *
+ * MUTEX:       Assumes parser is locked
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
+{
+	acpi_status status;
+	union acpi_operand_object *obj_desc;
+	union acpi_parse_object *op;
+	struct acpi_walk_state *walk_state;
+
+	ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
+
+	/* Parameter Validation */
+
+	if (!node) {
+		return_ACPI_STATUS(AE_NULL_ENTRY);
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+			  "**** Parsing [%4.4s] **** named_obj=%p\n",
+			  acpi_ut_get_node_name(node), node));
+
+	/* Extract the method object from the method Node */
+
+	obj_desc = acpi_ns_get_attached_object(node);
+	if (!obj_desc) {
+		return_ACPI_STATUS(AE_NULL_OBJECT);
+	}
+
+	/* Create a mutex for the method if there is a concurrency limit */
+
+	if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
+	    (!obj_desc->method.semaphore)) {
+		status = acpi_os_create_semaphore(obj_desc->method.concurrency,
+						  obj_desc->method.concurrency,
+						  &obj_desc->method.semaphore);
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+	}
+
+	/*
+	 * Allocate a new parser op to be the root of the parsed
+	 * method tree
+	 */
+	op = acpi_ps_alloc_op(AML_METHOD_OP);
+	if (!op) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	/* Init new op with the method name and pointer back to the Node */
+
+	acpi_ps_set_name(op, node->name.integer);
+	op->common.node = node;
+
+	/*
+	 * Get a new owner_id for objects created by this method. Namespace
+	 * objects (such as Operation Regions) can be created during the
+	 * first pass parse.
+	 */
+	status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
+	if (ACPI_FAILURE(status)) {
+		goto cleanup;
+	}
+
+	/* Create and initialize a new walk state */
+
+	walk_state =
+	    acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
+				      NULL);
+	if (!walk_state) {
+		status = AE_NO_MEMORY;
+		goto cleanup2;
+	}
+
+	status = acpi_ds_init_aml_walk(walk_state, op, node,
+				       obj_desc->method.aml_start,
+				       obj_desc->method.aml_length, NULL, 1);
+	if (ACPI_FAILURE(status)) {
+		acpi_ds_delete_walk_state(walk_state);
+		goto cleanup2;
+	}
+
+	/*
+	 * Parse the method, first pass
+	 *
+	 * The first pass load is where newly declared named objects are added into
+	 * the namespace.  Actual evaluation of the named objects (what would be
+	 * called a "second pass") happens during the actual execution of the
+	 * method so that operands to the named objects can take on dynamic
+	 * run-time values.
+	 */
+	status = acpi_ps_parse_aml(walk_state);
+	if (ACPI_FAILURE(status)) {
+		goto cleanup2;
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+			  "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
+			  acpi_ut_get_node_name(node), node, op));
+
+	/*
+	 * Delete the parse tree. We simply re-parse the method for every
+	 * execution since there isn't much overhead (compared to keeping lots
+	 * of parse trees around)
+	 */
+	acpi_ns_delete_namespace_subtree(node);
+	acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
+
+      cleanup2:
+	acpi_ut_release_owner_id(&obj_desc->method.owner_id);
+
+      cleanup:
+	acpi_ps_delete_parse_tree(op);
+	return_ACPI_STATUS(status);
+}
+#endif
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
index 4095ce7..c025674 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -260,9 +260,9 @@
 	case AML_LOCAL_OP:
 
 		if (index > ACPI_METHOD_MAX_LOCAL) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Local index %d is invalid (max %d)\n",
-					  index, ACPI_METHOD_MAX_LOCAL));
+			ACPI_ERROR((AE_INFO,
+				    "Local index %d is invalid (max %d)",
+				    index, ACPI_METHOD_MAX_LOCAL));
 			return_ACPI_STATUS(AE_AML_INVALID_INDEX);
 		}
 
@@ -274,9 +274,9 @@
 	case AML_ARG_OP:
 
 		if (index > ACPI_METHOD_MAX_ARG) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Arg index %d is invalid (max %d)\n",
-					  index, ACPI_METHOD_MAX_ARG));
+			ACPI_ERROR((AE_INFO,
+				    "Arg index %d is invalid (max %d)",
+				    index, ACPI_METHOD_MAX_ARG));
 			return_ACPI_STATUS(AE_AML_INVALID_INDEX);
 		}
 
@@ -286,8 +286,7 @@
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Opcode %d is invalid\n",
-				  opcode));
+		ACPI_ERROR((AE_INFO, "Opcode %d is invalid", opcode));
 		return_ACPI_STATUS(AE_AML_BAD_OPCODE);
 	}
 
@@ -378,8 +377,7 @@
 	/* Validate the object descriptor */
 
 	if (!dest_desc) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Null object descriptor pointer\n"));
+		ACPI_ERROR((AE_INFO, "Null object descriptor pointer"));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -424,23 +422,24 @@
 			switch (opcode) {
 			case AML_ARG_OP:
 
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Uninitialized Arg[%d] at node %p\n",
-						  index, node));
+				ACPI_ERROR((AE_INFO,
+					    "Uninitialized Arg[%d] at node %p",
+					    index, node));
 
 				return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
 
 			case AML_LOCAL_OP:
 
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Uninitialized Local[%d] at node %p\n",
-						  index, node));
+				ACPI_ERROR((AE_INFO,
+					    "Uninitialized Local[%d] at node %p",
+					    index, node));
 
 				return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
 
 			default:
-				ACPI_REPORT_ERROR(("Not Arg/Local opcode: %X\n",
-						   opcode));
+				ACPI_ERROR((AE_INFO,
+					    "Not a Arg/Local opcode: %X",
+					    opcode));
 				return_ACPI_STATUS(AE_AML_INTERNAL);
 			}
 	}
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index 8ac0cd9..8b21f0f 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -51,6 +51,7 @@
 #define _COMPONENT          ACPI_DISPATCHER
 ACPI_MODULE_NAME("dsobject")
 
+/* Local prototypes */
 static acpi_status
 acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
 			      union acpi_parse_object *op,
@@ -85,7 +86,7 @@
 	*obj_desc_ptr = NULL;
 	if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
 		/*
-		 * This is an named object reference.  If this name was
+		 * This is a named object reference. If this name was
 		 * previously looked up in the namespace, it was stored in this op.
 		 * Otherwise, go ahead and look it up now
 		 */
@@ -96,18 +97,48 @@
 						ACPI_IMODE_EXECUTE,
 						ACPI_NS_SEARCH_PARENT |
 						ACPI_NS_DONT_OPEN_SCOPE, NULL,
-						(struct acpi_namespace_node **)
-						&(op->common.node));
-
+						ACPI_CAST_INDIRECT_PTR(struct
+								       acpi_namespace_node,
+								       &(op->
+									 common.
+									 node)));
 			if (ACPI_FAILURE(status)) {
-				ACPI_REPORT_NSERROR(op->common.value.string,
-						    status);
+				/* Check if we are resolving a named reference within a package */
+
+				if ((status == AE_NOT_FOUND)
+				    && (acpi_gbl_enable_interpreter_slack)
+				    &&
+				    ((op->common.parent->common.aml_opcode ==
+				      AML_PACKAGE_OP)
+				     || (op->common.parent->common.aml_opcode ==
+					 AML_VAR_PACKAGE_OP))) {
+					/*
+					 * We didn't find the target and we are populating elements
+					 * of a package - ignore if slack enabled. Some ASL code
+					 * contains dangling invalid references in packages and
+					 * expects that no exception will be issued. Leave the
+					 * element as a null element. It cannot be used, but it
+					 * can be overwritten by subsequent ASL code - this is
+					 * typically the case.
+					 */
+					ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+							  "Ignoring unresolved reference in package [%4.4s]\n",
+							  walk_state->
+							  scope_info->scope.
+							  node->name.ascii));
+
+					return_ACPI_STATUS(AE_OK);
+				} else {
+					ACPI_ERROR_NAMESPACE(op->common.value.
+							     string, status);
+				}
+
 				return_ACPI_STATUS(status);
 			}
 		}
 	}
 
-	/* Create and init the internal ACPI object */
+	/* Create and init a new internal ACPI object */
 
 	obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
 						   (op->common.aml_opcode))->
@@ -157,13 +188,13 @@
 
 	ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj");
 
+	/*
+	 * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
+	 * The buffer object already exists (from the NS node), otherwise it must
+	 * be created.
+	 */
 	obj_desc = *obj_desc_ptr;
-	if (obj_desc) {
-		/*
-		 * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
-		 * The buffer object already exists (from the NS node)
-		 */
-	} else {
+	if (!obj_desc) {
 		/* Create a new buffer object */
 
 		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
@@ -183,10 +214,9 @@
 	byte_list = arg->named.next;
 	if (byte_list) {
 		if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Expecting bytelist, got AML opcode %X in op %p\n",
-					  byte_list->common.aml_opcode,
-					  byte_list));
+			ACPI_ERROR((AE_INFO,
+				    "Expecting bytelist, got AML opcode %X in op %p",
+				    byte_list->common.aml_opcode, byte_list));
 
 			acpi_ut_remove_reference(obj_desc);
 			return (AE_TYPE);
@@ -259,7 +289,7 @@
 	union acpi_operand_object *obj_desc = NULL;
 	u32 package_list_length;
 	acpi_status status = AE_OK;
-	u32 i;
+	acpi_native_uint i;
 
 	ACPI_FUNCTION_TRACE("ds_build_internal_package_obj");
 
@@ -271,13 +301,12 @@
 		parent = parent->common.parent;
 	}
 
+	/*
+	 * If we are evaluating a Named package object "Name (xxxx, Package)",
+	 * the package object already exists, otherwise it must be created.
+	 */
 	obj_desc = *obj_desc_ptr;
-	if (obj_desc) {
-		/*
-		 * We are evaluating a Named package object "Name (xxxx, Package)".
-		 * Get the existing package object from the NS node
-		 */
-	} else {
+	if (!obj_desc) {
 		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
 		*obj_desc_ptr = obj_desc;
 		if (!obj_desc) {
@@ -291,11 +320,9 @@
 
 	/* Count the number of items in the package list */
 
-	package_list_length = 0;
 	arg = op->common.value.arg;
 	arg = arg->common.next;
-	while (arg) {
-		package_list_length++;
+	for (package_list_length = 0; arg; package_list_length++) {
 		arg = arg->common.next;
 	}
 
@@ -322,12 +349,11 @@
 	}
 
 	/*
-	 * Now init the elements of the package
+	 * Initialize all elements of the package
 	 */
-	i = 0;
 	arg = op->common.value.arg;
 	arg = arg->common.next;
-	while (arg) {
+	for (i = 0; arg; i++) {
 		if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
 			/* Object (package or buffer) is already built */
 
@@ -340,8 +366,6 @@
 							       package.
 							       elements[i]);
 		}
-
-		i++;
 		arg = arg->common.next;
 	}
 
@@ -518,9 +542,9 @@
 
 			default:
 
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Unknown constant opcode %X\n",
-						  opcode));
+				ACPI_ERROR((AE_INFO,
+					    "Unknown constant opcode %X",
+					    opcode));
 				status = AE_AML_OPERAND_TYPE;
 				break;
 			}
@@ -535,9 +559,8 @@
 			break;
 
 		default:
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Unknown Integer type %X\n",
-					  op_info->type));
+			ACPI_ERROR((AE_INFO, "Unknown Integer type %X",
+				    op_info->type));
 			status = AE_AML_OPERAND_TYPE;
 			break;
 		}
@@ -615,9 +638,8 @@
 
 	default:
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unimplemented data type: %X\n",
-				  ACPI_GET_OBJECT_TYPE(obj_desc)));
+		ACPI_ERROR((AE_INFO, "Unimplemented data type: %X",
+			    ACPI_GET_OBJECT_TYPE(obj_desc)));
 
 		status = AE_AML_OPERAND_TYPE;
 		break;
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 939d167..6229c10 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -245,7 +245,9 @@
 
 	node = obj_desc->buffer.node;
 	if (!node) {
-		ACPI_REPORT_ERROR(("No pointer back to NS node in buffer obj %p\n", obj_desc));
+		ACPI_ERROR((AE_INFO,
+			    "No pointer back to NS node in buffer obj %p",
+			    obj_desc));
 		return_ACPI_STATUS(AE_AML_INTERNAL);
 	}
 
@@ -287,8 +289,9 @@
 
 	node = obj_desc->package.node;
 	if (!node) {
-		ACPI_REPORT_ERROR(("No pointer back to NS node in package %p\n",
-				   obj_desc));
+		ACPI_ERROR((AE_INFO,
+			    "No pointer back to NS node in package %p",
+			    obj_desc));
 		return_ACPI_STATUS(AE_AML_INTERNAL);
 	}
 
@@ -413,9 +416,9 @@
 	/* Host object must be a Buffer */
 
 	if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Target of Create Field is not a Buffer object - %s\n",
-				  acpi_ut_get_object_type_name(buffer_desc)));
+		ACPI_ERROR((AE_INFO,
+			    "Target of Create Field is not a Buffer object - %s",
+			    acpi_ut_get_object_type_name(buffer_desc)));
 
 		status = AE_AML_OPERAND_TYPE;
 		goto cleanup;
@@ -427,10 +430,10 @@
 	 * after resolution in acpi_ex_resolve_operands().
 	 */
 	if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "(%s) destination not a NS Node [%s]\n",
-				  acpi_ps_get_opcode_name(aml_opcode),
-				  acpi_ut_get_descriptor_name(result_desc)));
+		ACPI_ERROR((AE_INFO,
+			    "(%s) destination not a NS Node [%s]",
+			    acpi_ps_get_opcode_name(aml_opcode),
+			    acpi_ut_get_descriptor_name(result_desc)));
 
 		status = AE_AML_OPERAND_TYPE;
 		goto cleanup;
@@ -453,8 +456,8 @@
 		/* Must have a valid (>0) bit count */
 
 		if (bit_count == 0) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Attempt to create_field of length 0\n"));
+			ACPI_ERROR((AE_INFO,
+				    "Attempt to create_field of length zero"));
 			status = AE_AML_OPERAND_VALUE;
 			goto cleanup;
 		}
@@ -507,9 +510,8 @@
 
 	default:
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unknown field creation opcode %02x\n",
-				  aml_opcode));
+		ACPI_ERROR((AE_INFO,
+			    "Unknown field creation opcode %02x", aml_opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
@@ -517,13 +519,12 @@
 	/* Entire field must fit within the current length of the buffer */
 
 	if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n",
-				  acpi_ut_get_node_name(result_desc),
-				  bit_offset + bit_count,
-				  acpi_ut_get_node_name(buffer_desc->buffer.
-							node),
-				  8 * (u32) buffer_desc->buffer.length));
+		ACPI_ERROR((AE_INFO,
+			    "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)",
+			    acpi_ut_get_node_name(result_desc),
+			    bit_offset + bit_count,
+			    acpi_ut_get_node_name(buffer_desc->buffer.node),
+			    8 * (u32) buffer_desc->buffer.length));
 		status = AE_AML_BUFFER_LIMIT;
 		goto cleanup;
 	}
@@ -629,9 +630,9 @@
 			   "after acpi_ex_resolve_operands");
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n",
-				  acpi_ps_get_opcode_name(op->common.
-							  aml_opcode), status));
+		ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
+			    acpi_ps_get_opcode_name(op->common.aml_opcode),
+			    status));
 
 		return_ACPI_STATUS(status);
 	}
@@ -1155,9 +1156,8 @@
 
 	default:
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unknown control opcode=%X Op=%p\n",
-				  op->common.aml_opcode, op));
+		ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p",
+			    op->common.aml_opcode, op));
 
 		status = AE_AML_BAD_OPCODE;
 		break;
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index 83ae1c1..53356a5 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -176,8 +176,8 @@
 	/* Must have both an Op and a Result Object */
 
 	if (!op) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n"));
-		return_VALUE(TRUE);
+		ACPI_ERROR((AE_INFO, "Null Op"));
+		return_UINT8(TRUE);
 	}
 
 	/*
@@ -208,7 +208,7 @@
 				  "At Method level, result of [%s] not used\n",
 				  acpi_ps_get_opcode_name(op->common.
 							  aml_opcode)));
-		return_VALUE(FALSE);
+		return_UINT8(FALSE);
 	}
 
 	/* Get info on the parent. The root_op is AML_SCOPE */
@@ -216,9 +216,8 @@
 	parent_info =
 	    acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
 	if (parent_info->class == AML_CLASS_UNKNOWN) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unknown parent opcode. Op=%p\n", op));
-		return_VALUE(FALSE);
+		ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
+		return_UINT8(FALSE);
 	}
 
 	/*
@@ -304,7 +303,7 @@
 			  acpi_ps_get_opcode_name(op->common.parent->common.
 						  aml_opcode), op));
 
-	return_VALUE(TRUE);
+	return_UINT8(TRUE);
 
       result_not_used:
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
@@ -313,7 +312,7 @@
 			  acpi_ps_get_opcode_name(op->common.parent->common.
 						  aml_opcode), op));
 
-	return_VALUE(FALSE);
+	return_UINT8(FALSE);
 }
 
 /*******************************************************************************
@@ -344,7 +343,7 @@
 	ACPI_FUNCTION_TRACE_PTR("ds_delete_result_if_not_used", result_obj);
 
 	if (!op) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n"));
+		ACPI_ERROR((AE_INFO, "Null Op"));
 		return_VOID;
 	}
 
@@ -567,7 +566,7 @@
 			}
 
 			if (ACPI_FAILURE(status)) {
-				ACPI_REPORT_NSERROR(name_string, status);
+				ACPI_ERROR_NAMESPACE(name_string, status);
 			}
 		}
 
@@ -616,7 +615,7 @@
 
 		if (op_info->flags & AML_HAS_RETVAL) {
 			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-					  "Argument previously created, already stacked \n"));
+					  "Argument previously created, already stacked\n"));
 
 			ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
 					   (walk_state->
@@ -635,10 +634,8 @@
 				 * Only error is underflow, and this indicates
 				 * a missing or null operand!
 				 */
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Missing or null operand, %s\n",
-						  acpi_format_exception
-						  (status)));
+				ACPI_EXCEPTION((AE_INFO, status,
+						"Missing or null operand"));
 				return_ACPI_STATUS(status);
 			}
 		} else {
@@ -730,7 +727,7 @@
 	 */
 	(void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
-			  (arg_count + 1), acpi_format_exception(status)));
+	ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d",
+			(arg_count + 1)));
 	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index e522763..f1af655 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -100,9 +100,8 @@
 	if (result_obj) {
 		status = acpi_ds_result_pop(&obj_desc, walk_state);
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Could not get result from predicate evaluation, %s\n",
-					  acpi_format_exception(status)));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Could not get result from predicate evaluation"));
 
 			return_ACPI_STATUS(status);
 		}
@@ -123,9 +122,9 @@
 	}
 
 	if (!obj_desc) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "No predicate obj_desc=%p State=%p\n",
-				  obj_desc, walk_state));
+		ACPI_ERROR((AE_INFO,
+			    "No predicate obj_desc=%p State=%p",
+			    obj_desc, walk_state));
 
 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
 	}
@@ -140,10 +139,10 @@
 	}
 
 	if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
-				  obj_desc, walk_state,
-				  ACPI_GET_OBJECT_TYPE(obj_desc)));
+		ACPI_ERROR((AE_INFO,
+			    "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X",
+			    obj_desc, walk_state,
+			    ACPI_GET_OBJECT_TYPE(obj_desc)));
 
 		status = AE_AML_OPERAND_TYPE;
 		goto cleanup;
@@ -314,12 +313,13 @@
 
 	case AML_CLASS_EXECUTE:
 	case AML_CLASS_CREATE:
-
 		/*
 		 * Most operators with arguments.
 		 * Start a new result/operand state
 		 */
-		status = acpi_ds_result_stack_push(walk_state);
+		if (walk_state->opcode != AML_CREATE_FIELD_OP) {
+			status = acpi_ds_result_stack_push(walk_state);
+		}
 		break;
 
 	default:
@@ -361,8 +361,8 @@
 	op_class = walk_state->op_info->class;
 
 	if (op_class == AML_CLASS_UNKNOWN) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown opcode %X\n",
-				  op->common.aml_opcode));
+		ACPI_ERROR((AE_INFO, "Unknown opcode %X",
+			    op->common.aml_opcode));
 		return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
 	}
 
@@ -452,12 +452,10 @@
 				walk_state->operands[1]->reference.offset)) {
 				status = AE_OK;
 			} else {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "[%s]: Could not resolve operands, %s\n",
-						  acpi_ps_get_opcode_name
-						  (walk_state->opcode),
-						  acpi_format_exception
-						  (status)));
+				ACPI_EXCEPTION((AE_INFO, status,
+						"While resolving operands for [%s]",
+						acpi_ps_get_opcode_name
+						(walk_state->opcode)));
 			}
 		}
 
@@ -676,8 +674,8 @@
 
 		case AML_TYPE_UNDEFINED:
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Undefined opcode type Op=%p\n", op));
+			ACPI_ERROR((AE_INFO,
+				    "Undefined opcode type Op=%p", op));
 			return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
 
 		case AML_TYPE_BOGUS:
@@ -689,10 +687,10 @@
 
 		default:
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n",
-					  op_class, op_type,
-					  op->common.aml_opcode, op));
+			ACPI_ERROR((AE_INFO,
+				    "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p",
+				    op_class, op_type, op->common.aml_opcode,
+				    op));
 
 			status = AE_NOT_IMPLEMENTED;
 			break;
@@ -723,20 +721,6 @@
 
       cleanup:
 
-	/* Invoke exception handler on error */
-
-	if (ACPI_FAILURE(status) &&
-	    acpi_gbl_exception_handler && !(status & AE_CODE_CONTROL)) {
-		acpi_ex_exit_interpreter();
-		status = acpi_gbl_exception_handler(status,
-						    walk_state->method_node->
-						    name.integer,
-						    walk_state->opcode,
-						    walk_state->aml_offset,
-						    NULL);
-		(void)acpi_ex_enter_interpreter();
-	}
-
 	if (walk_state->result_obj) {
 		/* Break to debugger to display result */
 
@@ -758,18 +742,14 @@
 	}
 #endif
 
+	/* Invoke exception handler on error */
+
+	if (ACPI_FAILURE(status)) {
+		status = acpi_ds_method_error(status, walk_state);
+	}
+
 	/* Always clear the object stack */
 
 	walk_state->num_operands = 0;
-
-#ifdef ACPI_DISASSEMBLER
-
-	/* On error, display method locals/args */
-
-	if (ACPI_FAILURE(status)) {
-		acpi_dm_dump_method_info(status, walk_state, op);
-	}
-#endif
-
 	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index 4117312..d3d24da 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -127,7 +127,7 @@
 	char *path;
 	u32 flags;
 
-	ACPI_FUNCTION_NAME("ds_load1_begin_op");
+	ACPI_FUNCTION_TRACE("ds_load1_begin_op");
 
 	op = walk_state->op;
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -138,14 +138,14 @@
 	if (op) {
 		if (!(walk_state->op_info->flags & AML_NAMED)) {
 			*out_op = op;
-			return (AE_OK);
+			return_ACPI_STATUS(AE_OK);
 		}
 
 		/* Check if this object has already been installed in the namespace */
 
 		if (op->common.node) {
 			*out_op = op;
-			return (AE_OK);
+			return_ACPI_STATUS(AE_OK);
 		}
 	}
 
@@ -187,8 +187,8 @@
 		}
 #endif
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_NSERROR(path, status);
-			return (status);
+			ACPI_ERROR_NAMESPACE(path, status);
+			return_ACPI_STATUS(status);
 		}
 
 		/*
@@ -233,9 +233,11 @@
 
 			/* All other types are an error */
 
-			ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n", acpi_ut_get_type_name(node->type), path));
+			ACPI_ERROR((AE_INFO,
+				    "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)",
+				    acpi_ut_get_type_name(node->type), path));
 
-			return (AE_AML_OPERAND_TYPE);
+			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 		break;
 
@@ -257,6 +259,7 @@
 		 *       buffer_field, or Package), the name of the object is already
 		 *       in the namespace.
 		 */
+
 		if (walk_state->deferred_node) {
 			/* This name is already in the namespace, get the node */
 
@@ -265,6 +268,16 @@
 			break;
 		}
 
+		/*
+		 * If we are executing a method, do not create any namespace objects
+		 * during the load phase, only during execution.
+		 */
+		if (walk_state->method_node) {
+			node = NULL;
+			status = AE_OK;
+			break;
+		}
+
 		flags = ACPI_NS_NO_UPSEARCH;
 		if ((walk_state->opcode != AML_SCOPE_OP) &&
 		    (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
@@ -289,8 +302,8 @@
 				   ACPI_IMODE_LOAD_PASS1, flags, walk_state,
 				   &(node));
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_NSERROR(path, status);
-			return (status);
+			ACPI_ERROR_NAMESPACE(path, status);
+			return_ACPI_STATUS(status);
 		}
 		break;
 	}
@@ -302,28 +315,29 @@
 
 		op = acpi_ps_alloc_op(walk_state->opcode);
 		if (!op) {
-			return (AE_NO_MEMORY);
+			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
 	}
 
-	/* Initialize */
-
-	op->named.name = node->name.integer;
+	/* Initialize the op */
 
 #if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
-	op->named.path = (u8 *) path;
+	op->named.path = ACPI_CAST_PTR(u8, path);
 #endif
 
-	/*
-	 * Put the Node in the "op" object that the parser uses, so we
-	 * can get it again quickly when this scope is closed
-	 */
-	op->common.node = node;
+	if (node) {
+		/*
+		 * Put the Node in the "op" object that the parser uses, so we
+		 * can get it again quickly when this scope is closed
+		 */
+		op->common.node = node;
+		op->named.name = node->name.integer;
+	}
+
 	acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),
 			   op);
-
 	*out_op = op;
-	return (status);
+	return_ACPI_STATUS(status);
 }
 
 /*******************************************************************************
@@ -339,13 +353,13 @@
  *
  ******************************************************************************/
 
-acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state)
+acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
 {
 	union acpi_parse_object *op;
 	acpi_object_type object_type;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_NAME("ds_load1_end_op");
+	ACPI_FUNCTION_TRACE("ds_load1_end_op");
 
 	op = walk_state->op;
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -354,7 +368,7 @@
 	/* We are only interested in opcodes that have an associated name */
 
 	if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
-		return (AE_OK);
+		return_ACPI_STATUS(AE_OK);
 	}
 
 	/* Get the object type to determine if we should pop the scope */
@@ -363,21 +377,37 @@
 
 #ifndef ACPI_NO_METHOD_EXECUTION
 	if (walk_state->op_info->flags & AML_FIELD) {
-		if (walk_state->opcode == AML_FIELD_OP ||
-		    walk_state->opcode == AML_BANK_FIELD_OP ||
-		    walk_state->opcode == AML_INDEX_FIELD_OP) {
-			status = acpi_ds_init_field_objects(op, walk_state);
+		/*
+		 * If we are executing a method, do not create any namespace objects
+		 * during the load phase, only during execution.
+		 */
+		if (!walk_state->method_node) {
+			if (walk_state->opcode == AML_FIELD_OP ||
+			    walk_state->opcode == AML_BANK_FIELD_OP ||
+			    walk_state->opcode == AML_INDEX_FIELD_OP) {
+				status =
+				    acpi_ds_init_field_objects(op, walk_state);
+			}
 		}
-		return (status);
+		return_ACPI_STATUS(status);
 	}
 
-	if (op->common.aml_opcode == AML_REGION_OP) {
-		status = acpi_ex_create_region(op->named.data, op->named.length,
-					       (acpi_adr_space_type)
-					       ((op->common.value.arg)->common.
-						value.integer), walk_state);
-		if (ACPI_FAILURE(status)) {
-			return (status);
+	/*
+	 * If we are executing a method, do not create any namespace objects
+	 * during the load phase, only during execution.
+	 */
+	if (!walk_state->method_node) {
+		if (op->common.aml_opcode == AML_REGION_OP) {
+			status =
+			    acpi_ex_create_region(op->named.data,
+						  op->named.length,
+						  (acpi_adr_space_type)
+						  ((op->common.value.arg)->
+						   common.value.integer),
+						  walk_state);
+			if (ACPI_FAILURE(status)) {
+				return_ACPI_STATUS(status);
+			}
 		}
 	}
 #endif
@@ -391,47 +421,63 @@
 							       common.
 							       aml_opcode))->
 			    object_type;
-			op->common.node->type = (u8) object_type;
-		}
-	}
 
-	if (op->common.aml_opcode == AML_METHOD_OP) {
-		/*
-		 * method_op pkg_length name_string method_flags term_list
-		 *
-		 * Note: We must create the method node/object pair as soon as we
-		 * see the method declaration.  This allows later pass1 parsing
-		 * of invocations of the method (need to know the number of
-		 * arguments.)
-		 */
-		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "LOADING-Method: State=%p Op=%p named_obj=%p\n",
-				  walk_state, op, op->named.node));
+			/* Set node type if we have a namespace node */
 
-		if (!acpi_ns_get_attached_object(op->named.node)) {
-			walk_state->operands[0] = (void *)op->named.node;
-			walk_state->num_operands = 1;
-
-			status =
-			    acpi_ds_create_operands(walk_state,
-						    op->common.value.arg);
-			if (ACPI_SUCCESS(status)) {
-				status = acpi_ex_create_method(op->named.data,
-							       op->named.length,
-							       walk_state);
-			}
-			walk_state->operands[0] = NULL;
-			walk_state->num_operands = 0;
-
-			if (ACPI_FAILURE(status)) {
-				return (status);
+			if (op->common.node) {
+				op->common.node->type = (u8) object_type;
 			}
 		}
 	}
 
-	/* Pop the scope stack */
+	/*
+	 * If we are executing a method, do not create any namespace objects
+	 * during the load phase, only during execution.
+	 */
+	if (!walk_state->method_node) {
+		if (op->common.aml_opcode == AML_METHOD_OP) {
+			/*
+			 * method_op pkg_length name_string method_flags term_list
+			 *
+			 * Note: We must create the method node/object pair as soon as we
+			 * see the method declaration.  This allows later pass1 parsing
+			 * of invocations of the method (need to know the number of
+			 * arguments.)
+			 */
+			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+					  "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+					  walk_state, op, op->named.node));
 
-	if (acpi_ns_opens_scope(object_type)) {
+			if (!acpi_ns_get_attached_object(op->named.node)) {
+				walk_state->operands[0] =
+				    ACPI_CAST_PTR(void, op->named.node);
+				walk_state->num_operands = 1;
+
+				status =
+				    acpi_ds_create_operands(walk_state,
+							    op->common.value.
+							    arg);
+				if (ACPI_SUCCESS(status)) {
+					status =
+					    acpi_ex_create_method(op->named.
+								  data,
+								  op->named.
+								  length,
+								  walk_state);
+				}
+				walk_state->operands[0] = NULL;
+				walk_state->num_operands = 0;
+
+				if (ACPI_FAILURE(status)) {
+					return_ACPI_STATUS(status);
+				}
+			}
+		}
+	}
+
+	/* Pop the scope stack (only if loading a table) */
+
+	if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 				  "(%s): Popping scope for Op %p\n",
 				  acpi_ut_get_type_name(object_type), op));
@@ -439,7 +485,7 @@
 		status = acpi_ds_scope_stack_pop(walk_state);
 	}
 
-	return (status);
+	return_ACPI_STATUS(status);
 }
 
 /*******************************************************************************
@@ -456,8 +502,8 @@
  ******************************************************************************/
 
 acpi_status
-acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state,
-		       union acpi_parse_object ** out_op)
+acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
+		       union acpi_parse_object **out_op)
 {
 	union acpi_parse_object *op;
 	struct acpi_namespace_node *node;
@@ -574,10 +620,10 @@
 			if (status == AE_NOT_FOUND) {
 				status = AE_OK;
 			} else {
-				ACPI_REPORT_NSERROR(buffer_ptr, status);
+				ACPI_ERROR_NAMESPACE(buffer_ptr, status);
 			}
 #else
-			ACPI_REPORT_NSERROR(buffer_ptr, status);
+			ACPI_ERROR_NAMESPACE(buffer_ptr, status);
 #endif
 			return_ACPI_STATUS(status);
 		}
@@ -607,7 +653,10 @@
 			 *  Scope (DEB) { ... }
 			 */
 
-			ACPI_REPORT_WARNING(("Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", buffer_ptr, acpi_ut_get_type_name(node->type)));
+			ACPI_WARNING((AE_INFO,
+				      "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)",
+				      buffer_ptr,
+				      acpi_ut_get_type_name(node->type)));
 
 			node->type = ACPI_TYPE_ANY;
 			walk_state->scope_info->common.value = ACPI_TYPE_ANY;
@@ -617,7 +666,10 @@
 
 			/* All other types are an error */
 
-			ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s]\n", acpi_ut_get_type_name(node->type), buffer_ptr));
+			ACPI_ERROR((AE_INFO,
+				    "Invalid type (%s) for target of Scope operator [%4.4s]",
+				    acpi_ut_get_type_name(node->type),
+				    buffer_ptr));
 
 			return (AE_AML_OPERAND_TYPE);
 		}
@@ -670,7 +722,7 @@
 	}
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_NSERROR(buffer_ptr, status);
+		ACPI_ERROR_NAMESPACE(buffer_ptr, status);
 		return_ACPI_STATUS(status);
 	}
 
@@ -840,6 +892,13 @@
 
 	case AML_TYPE_NAMED_FIELD:
 
+		/*
+		 * If we are executing a method, initialize the field
+		 */
+		if (walk_state->method_node) {
+			status = acpi_ds_init_field_objects(op, walk_state);
+		}
+
 		switch (op->common.aml_opcode) {
 		case AML_INDEX_FIELD_OP:
 
@@ -929,6 +988,24 @@
 		switch (op->common.aml_opcode) {
 #ifndef ACPI_NO_METHOD_EXECUTION
 		case AML_REGION_OP:
+
+			/*
+			 * If we are executing a method, initialize the region
+			 */
+			if (walk_state->method_node) {
+				status =
+				    acpi_ex_create_region(op->named.data,
+							  op->named.length,
+							  (acpi_adr_space_type)
+							  ((op->common.value.
+							    arg)->common.value.
+							   integer),
+							  walk_state);
+				if (ACPI_FAILURE(status)) {
+					return (status);
+				}
+			}
+
 			/*
 			 * The op_region is not fully parsed at this time. Only valid
 			 * argument is the space_id. (We must save the address of the
@@ -957,11 +1034,50 @@
 
 			status = acpi_ds_create_node(walk_state, node, op);
 			break;
+
+		case AML_METHOD_OP:
+			/*
+			 * method_op pkg_length name_string method_flags term_list
+			 *
+			 * Note: We must create the method node/object pair as soon as we
+			 * see the method declaration.  This allows later pass1 parsing
+			 * of invocations of the method (need to know the number of
+			 * arguments.)
+			 */
+			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+					  "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+					  walk_state, op, op->named.node));
+
+			if (!acpi_ns_get_attached_object(op->named.node)) {
+				walk_state->operands[0] =
+				    ACPI_CAST_PTR(void, op->named.node);
+				walk_state->num_operands = 1;
+
+				status =
+				    acpi_ds_create_operands(walk_state,
+							    op->common.value.
+							    arg);
+				if (ACPI_SUCCESS(status)) {
+					status =
+					    acpi_ex_create_method(op->named.
+								  data,
+								  op->named.
+								  length,
+								  walk_state);
+				}
+				walk_state->operands[0] = NULL;
+				walk_state->num_operands = 0;
+
+				if (ACPI_FAILURE(status)) {
+					return_ACPI_STATUS(status);
+				}
+			}
+			break;
+
 #endif				/* ACPI_NO_METHOD_EXECUTION */
 
 		default:
 			/* All NAMED_COMPLEX opcodes must be handled above */
-			/* Note: Method objects were already created in Pass 1 */
 			break;
 		}
 		break;
@@ -1004,7 +1120,7 @@
 			 */
 			op->common.node = new_node;
 		} else {
-			ACPI_REPORT_NSERROR(arg->common.value.string, status);
+			ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
 		}
 		break;
 
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
index defe956..ada21ef 100644
--- a/drivers/acpi/dispatcher/dswscope.c
+++ b/drivers/acpi/dispatcher/dswscope.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -107,14 +107,14 @@
 	if (!node) {
 		/* Invalid scope   */
 
-		ACPI_REPORT_ERROR(("ds_scope_stack_push: null scope passed\n"));
+		ACPI_ERROR((AE_INFO, "Null scope parameter"));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
 	/* Make sure object type is valid */
 
 	if (!acpi_ut_valid_object_type(type)) {
-		ACPI_REPORT_WARNING(("ds_scope_stack_push: Invalid object type: 0x%X\n", type));
+		ACPI_WARNING((AE_INFO, "Invalid object type: 0x%X", type));
 	}
 
 	/* Allocate a new scope object */
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index 7d68a5a..fa78cb7 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -92,26 +92,23 @@
 
 	state = walk_state->results;
 	if (!state) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "No result object pushed! State=%p\n",
-				  walk_state));
+		ACPI_ERROR((AE_INFO, "No result object pushed! State=%p",
+			    walk_state));
 		return (AE_NOT_EXIST);
 	}
 
 	if (index >= ACPI_OBJ_MAX_OPERAND) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Index out of range: %X State=%p Num=%X\n",
-				  index, walk_state,
-				  state->results.num_results));
+		ACPI_ERROR((AE_INFO,
+			    "Index out of range: %X State=%p Num=%X",
+			    index, walk_state, state->results.num_results));
 	}
 
 	/* Check for a valid result object */
 
 	if (!state->results.obj_desc[index]) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Null operand! State=%p #Ops=%X, Index=%X\n",
-				  walk_state, state->results.num_results,
-				  index));
+		ACPI_ERROR((AE_INFO,
+			    "Null operand! State=%p #Ops=%X, Index=%X",
+			    walk_state, state->results.num_results, index));
 		return (AE_AML_NO_RETURN_VALUE);
 	}
 
@@ -163,9 +160,8 @@
 	}
 
 	if (!state->results.num_results) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Result stack is empty! State=%p\n",
-				  walk_state));
+		ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p",
+			    walk_state));
 		return (AE_AML_NO_RETURN_VALUE);
 	}
 
@@ -192,8 +188,7 @@
 		}
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-			  "No result objects! State=%p\n", walk_state));
+	ACPI_ERROR((AE_INFO, "No result objects! State=%p", walk_state));
 	return (AE_AML_NO_RETURN_VALUE);
 }
 
@@ -222,15 +217,14 @@
 
 	state = walk_state->results;
 	if (!state) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Warning: No result object pushed! State=%p\n",
-				  walk_state));
+		ACPI_ERROR((AE_INFO,
+			    "No result object pushed! State=%p", walk_state));
 		return (AE_NOT_EXIST);
 	}
 
 	if (!state->results.num_results) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "No result objects! State=%p\n", walk_state));
+		ACPI_ERROR((AE_INFO, "No result objects! State=%p",
+			    walk_state));
 		return (AE_AML_NO_RETURN_VALUE);
 	}
 
@@ -250,10 +244,10 @@
 	/* Check for a valid result object */
 
 	if (!*object) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Null operand! State=%p #Ops=%X Index=%X\n",
-				  walk_state, state->results.num_results,
-				  (u32) index));
+		ACPI_ERROR((AE_INFO,
+			    "Null operand! State=%p #Ops=%X Index=%X",
+			    walk_state, state->results.num_results,
+			    (u32) index));
 		return (AE_AML_NO_RETURN_VALUE);
 	}
 
@@ -288,23 +282,21 @@
 
 	state = walk_state->results;
 	if (!state) {
-		ACPI_REPORT_ERROR(("No result stack frame during push\n"));
+		ACPI_ERROR((AE_INFO, "No result stack frame during push"));
 		return (AE_AML_INTERNAL);
 	}
 
 	if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Result stack overflow: Obj=%p State=%p Num=%X\n",
-				  object, walk_state,
-				  state->results.num_results));
+		ACPI_ERROR((AE_INFO,
+			    "Result stack overflow: Obj=%p State=%p Num=%X",
+			    object, walk_state, state->results.num_results));
 		return (AE_STACK_OVERFLOW);
 	}
 
 	if (!object) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Null Object! Obj=%p State=%p Num=%X\n",
-				  object, walk_state,
-				  state->results.num_results));
+		ACPI_ERROR((AE_INFO,
+			    "Null Object! Obj=%p State=%p Num=%X",
+			    object, walk_state, state->results.num_results));
 		return (AE_BAD_PARAMETER);
 	}
 
@@ -413,10 +405,9 @@
 	/* Check for stack overflow */
 
 	if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "overflow! Obj=%p State=%p #Ops=%X\n",
-				  object, walk_state,
-				  walk_state->num_operands));
+		ACPI_ERROR((AE_INFO,
+			    "Object stack overflow! Obj=%p State=%p #Ops=%X",
+			    object, walk_state, walk_state->num_operands));
 		return (AE_STACK_OVERFLOW);
 	}
 
@@ -460,10 +451,10 @@
 		/* Check for stack underflow */
 
 		if (walk_state->num_operands == 0) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Underflow! Count=%X State=%p #Ops=%X\n",
-					  pop_count, walk_state,
-					  walk_state->num_operands));
+			ACPI_ERROR((AE_INFO,
+				    "Object stack underflow! Count=%X State=%p #Ops=%X",
+				    pop_count, walk_state,
+				    walk_state->num_operands));
 			return (AE_STACK_UNDERFLOW);
 		}
 
@@ -506,10 +497,10 @@
 		/* Check for stack underflow */
 
 		if (walk_state->num_operands == 0) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Underflow! Count=%X State=%p #Ops=%X\n",
-					  pop_count, walk_state,
-					  walk_state->num_operands));
+			ACPI_ERROR((AE_INFO,
+				    "Object stack underflow! Count=%X State=%p #Ops=%X",
+				    pop_count, walk_state,
+				    walk_state->num_operands));
 			return (AE_STACK_UNDERFLOW);
 		}
 
@@ -826,16 +817,14 @@
 	}
 
 	if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "%p is not a valid walk state\n",
-				  walk_state));
+		ACPI_ERROR((AE_INFO, "%p is not a valid walk state",
+			    walk_state));
 		return;
 	}
 
 	if (walk_state->parser_state.scope) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "%p walk still has a scope list\n",
-				  walk_state));
+		ACPI_ERROR((AE_INFO, "%p walk still has a scope list",
+			    walk_state));
 	}
 
 	/* Always must free any linked control states */
@@ -894,25 +883,24 @@
 
 	state = walk_state->results;
 	if (!state) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "No result object pushed! State=%p\n",
-				  walk_state));
+		ACPI_ERROR((AE_INFO, "No result object pushed! State=%p",
+			    walk_state));
 		return (AE_NOT_EXIST);
 	}
 
 	if (index >= ACPI_OBJ_NUM_OPERANDS) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Index out of range: %X Obj=%p State=%p Num=%X\n",
-				  index, object, walk_state,
-				  state->results.num_results));
+		ACPI_ERROR((AE_INFO,
+			    "Index out of range: %X Obj=%p State=%p Num=%X",
+			    index, object, walk_state,
+			    state->results.num_results));
 		return (AE_BAD_PARAMETER);
 	}
 
 	if (!object) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Null Object! Index=%X Obj=%p State=%p Num=%X\n",
-				  index, object, walk_state,
-				  state->results.num_results));
+		ACPI_ERROR((AE_INFO,
+			    "Null Object! Index=%X Obj=%p State=%p Num=%X",
+			    index, object, walk_state,
+			    state->results.num_results));
 		return (AE_BAD_PARAMETER);
 	}
 
@@ -986,9 +974,9 @@
 	/* Check for stack underflow */
 
 	if (walk_state->num_operands == 0) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Missing operand/stack empty! State=%p #Ops=%X\n",
-				  walk_state, walk_state->num_operands));
+		ACPI_ERROR((AE_INFO,
+			    "Missing operand/stack empty! State=%p #Ops=%X",
+			    walk_state, walk_state->num_operands));
 		*object = NULL;
 		return (AE_AML_NO_OPERAND);
 	}
@@ -1000,9 +988,9 @@
 	/* Check for a valid operand */
 
 	if (!walk_state->operands[walk_state->num_operands]) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Null operand! State=%p #Ops=%X\n",
-				  walk_state, walk_state->num_operands));
+		ACPI_ERROR((AE_INFO,
+			    "Null operand! State=%p #Ops=%X",
+			    walk_state, walk_state->num_operands));
 		*object = NULL;
 		return (AE_AML_NO_OPERAND);
 	}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 3758b55..79b09d7 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -60,20 +60,20 @@
 #define ACPI_EC_BURST_ENABLE	0x82
 #define ACPI_EC_BURST_DISABLE	0x83
 #define ACPI_EC_COMMAND_QUERY	0x84
-#define EC_POLLING		0xFF
-#define EC_BURST		0x00
+#define EC_POLL			0xFF
+#define EC_INTR			0x00
 static int acpi_ec_remove(struct acpi_device *device, int type);
 static int acpi_ec_start(struct acpi_device *device);
 static int acpi_ec_stop(struct acpi_device *device, int type);
-static int acpi_ec_burst_add(struct acpi_device *device);
-static int acpi_ec_polling_add(struct acpi_device *device);
+static int acpi_ec_intr_add(struct acpi_device *device);
+static int acpi_ec_poll_add(struct acpi_device *device);
 
 static struct acpi_driver acpi_ec_driver = {
 	.name = ACPI_EC_DRIVER_NAME,
 	.class = ACPI_EC_CLASS,
 	.ids = ACPI_EC_HID,
 	.ops = {
-		.add = acpi_ec_polling_add,
+		.add = acpi_ec_intr_add,
 		.remove = acpi_ec_remove,
 		.start = acpi_ec_start,
 		.stop = acpi_ec_stop,
@@ -105,7 +105,7 @@
 		atomic_t pending_gpe;
 		struct semaphore sem;
 		wait_queue_head_t wait;
-	} burst;
+	} intr;
 
 	struct {
 		u32 mode;
@@ -117,37 +117,37 @@
 		struct acpi_generic_address data_addr;
 		unsigned long global_lock;
 		spinlock_t lock;
-	} polling;
+	} poll;
 };
 
-static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event);
-static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event);
-static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data);
-static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data);
-static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data);
-static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data);
-static void acpi_ec_gpe_polling_query(void *ec_cxt);
-static void acpi_ec_gpe_burst_query(void *ec_cxt);
-static u32 acpi_ec_gpe_polling_handler(void *data);
-static u32 acpi_ec_gpe_burst_handler(void *data);
+static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event);
+static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event);
+static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data);
+static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data);
+static void acpi_ec_gpe_poll_query(void *ec_cxt);
+static void acpi_ec_gpe_intr_query(void *ec_cxt);
+static u32 acpi_ec_gpe_poll_handler(void *data);
+static u32 acpi_ec_gpe_intr_handler(void *data);
 static acpi_status __init
-acpi_fake_ecdt_polling_callback(acpi_handle handle,
+acpi_fake_ecdt_poll_callback(acpi_handle handle,
 				u32 Level, void *context, void **retval);
 
 static acpi_status __init
-acpi_fake_ecdt_burst_callback(acpi_handle handle,
+acpi_fake_ecdt_intr_callback(acpi_handle handle,
 			      u32 Level, void *context, void **retval);
 
-static int __init acpi_ec_polling_get_real_ecdt(void);
-static int __init acpi_ec_burst_get_real_ecdt(void);
+static int __init acpi_ec_poll_get_real_ecdt(void);
+static int __init acpi_ec_intr_get_real_ecdt(void);
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
 static union acpi_ec *ec_ecdt;
 
 /* External interfaces use first EC only, so remember */
 static struct acpi_device *first_ec;
-static int acpi_ec_polling_mode = EC_POLLING;
+static int acpi_ec_poll_mode = EC_INTR;
 
 /* --------------------------------------------------------------------------
                              Transaction Management
@@ -163,13 +163,13 @@
 
 static int acpi_ec_wait(union acpi_ec *ec, u8 event)
 {
-	if (acpi_ec_polling_mode)
-		return acpi_ec_polling_wait(ec, event);
+	if (acpi_ec_poll_mode)
+		return acpi_ec_poll_wait(ec, event);
 	else
-		return acpi_ec_burst_wait(ec, event);
+		return acpi_ec_intr_wait(ec, event);
 }
 
-static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event)
+static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event)
 {
 	u32 acpi_ec_status = 0;
 	u32 i = ACPI_EC_UDELAY_COUNT;
@@ -203,36 +203,31 @@
 
 	return -ETIME;
 }
-static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
+static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event)
 {
 	int result = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_ec_wait");
 
-	ec->burst.expect_event = event;
+	ec->intr.expect_event = event;
 	smp_mb();
 
 	switch (event) {
-	case ACPI_EC_EVENT_OBF:
-		if (acpi_ec_read_status(ec) & event) {
-			ec->burst.expect_event = 0;
+	case ACPI_EC_EVENT_IBE:
+		if (~acpi_ec_read_status(ec) & event) {
+			ec->intr.expect_event = 0;
 			return_VALUE(0);
 		}
 		break;
-
-	case ACPI_EC_EVENT_IBE:
-		if (~acpi_ec_read_status(ec) & event) {
-			ec->burst.expect_event = 0;
-			return_VALUE(0);
-		}
+	default:
 		break;
 	}
 
-	result = wait_event_timeout(ec->burst.wait,
-				    !ec->burst.expect_event,
+	result = wait_event_timeout(ec->intr.wait,
+				    !ec->intr.expect_event,
 				    msecs_to_jiffies(ACPI_EC_DELAY));
 
-	ec->burst.expect_event = 0;
+	ec->intr.expect_event = 0;
 	smp_mb();
 
 	/*
@@ -255,7 +250,12 @@
 	return_VALUE(-ETIME);
 }
 
-static int acpi_ec_enter_burst_mode(union acpi_ec *ec)
+#ifdef ACPI_FUTURE_USAGE
+/*
+ * Note: samsung nv5000 doesn't work with ec burst mode.
+ * http://bugzilla.kernel.org/show_bug.cgi?id=4980
+ */
+int acpi_ec_enter_burst_mode(union acpi_ec *ec)
 {
 	u32 tmp = 0;
 	int status = 0;
@@ -270,45 +270,56 @@
 		acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE,
 					&ec->common.command_addr);
 		status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
-		if (status)
-			return_VALUE(-EINVAL);
 		acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
 		if (tmp != 0x90) {	/* Burst ACK byte */
 			return_VALUE(-EINVAL);
 		}
 	}
 
-	atomic_set(&ec->burst.leaving_burst, 0);
+	atomic_set(&ec->intr.leaving_burst, 0);
 	return_VALUE(0);
       end:
-	printk("Error in acpi_ec_wait\n");
+	printk(KERN_WARNING PREFIX "Error in acpi_ec_wait\n");
 	return_VALUE(-1);
 }
 
-static int acpi_ec_leave_burst_mode(union acpi_ec *ec)
+int acpi_ec_leave_burst_mode(union acpi_ec *ec)
 {
+	int status = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode");
 
-	atomic_set(&ec->burst.leaving_burst, 1);
+	status = acpi_ec_read_status(ec);
+	if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){
+		status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
+		if(status)
+			goto end;
+		acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
+		acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
+	} 
+	atomic_set(&ec->intr.leaving_burst, 1);
 	return_VALUE(0);
+end:
+	printk(KERN_WARNING PREFIX "leave burst_mode:error\n");
+	return_VALUE(-1);
 }
+#endif /* ACPI_FUTURE_USAGE */
 
 static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
 {
-	if (acpi_ec_polling_mode)
-		return acpi_ec_polling_read(ec, address, data);
+	if (acpi_ec_poll_mode)
+		return acpi_ec_poll_read(ec, address, data);
 	else
-		return acpi_ec_burst_read(ec, address, data);
+		return acpi_ec_intr_read(ec, address, data);
 }
 static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data)
 {
-	if (acpi_ec_polling_mode)
-		return acpi_ec_polling_write(ec, address, data);
+	if (acpi_ec_poll_mode)
+		return acpi_ec_poll_write(ec, address, data);
 	else
-		return acpi_ec_burst_write(ec, address, data);
+		return acpi_ec_intr_write(ec, address, data);
 }
-static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
+static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data)
 {
 	acpi_status status = AE_OK;
 	int result = 0;
@@ -328,7 +339,7 @@
 			return_VALUE(-ENODEV);
 	}
 
-	spin_lock_irqsave(&ec->polling.lock, flags);
+	spin_lock_irqsave(&ec->poll.lock, flags);
 
 	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
 				&ec->common.command_addr);
@@ -347,7 +358,7 @@
 			  *data, address));
 
       end:
-	spin_unlock_irqrestore(&ec->polling.lock, flags);
+	spin_unlock_irqrestore(&ec->poll.lock, flags);
 
 	if (ec->common.global_lock)
 		acpi_release_global_lock(glk);
@@ -355,7 +366,7 @@
 	return_VALUE(result);
 }
 
-static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
+static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
@@ -373,7 +384,7 @@
 			return_VALUE(-ENODEV);
 	}
 
-	spin_lock_irqsave(&ec->polling.lock, flags);
+	spin_lock_irqsave(&ec->poll.lock, flags);
 
 	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
 				&ec->common.command_addr);
@@ -395,7 +406,7 @@
 			  data, address));
 
       end:
-	spin_unlock_irqrestore(&ec->polling.lock, flags);
+	spin_unlock_irqrestore(&ec->poll.lock, flags);
 
 	if (ec->common.global_lock)
 		acpi_release_global_lock(glk);
@@ -403,7 +414,7 @@
 	return_VALUE(result);
 }
 
-static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
+static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data)
 {
 	int status = 0;
 	u32 glk;
@@ -422,25 +433,24 @@
 	}
 
 	WARN_ON(in_interrupt());
-	down(&ec->burst.sem);
+	down(&ec->intr.sem);
 
-	acpi_ec_enter_burst_mode(ec);
 	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
 	if (status) {
-		printk("read EC, IB not empty\n");
+		printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
 		goto end;
 	}
 	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
 				&ec->common.command_addr);
 	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
 	if (status) {
-		printk("read EC, IB not empty\n");
+		printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
 	}
 
 	acpi_hw_low_level_write(8, address, &ec->common.data_addr);
 	status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
 	if (status) {
-		printk("read EC, OB not full\n");
+		printk(KERN_DEBUG PREFIX "read EC, OB not full\n");
 		goto end;
 	}
 	acpi_hw_low_level_read(8, data, &ec->common.data_addr);
@@ -448,8 +458,7 @@
 			  *data, address));
 
       end:
-	acpi_ec_leave_burst_mode(ec);
-	up(&ec->burst.sem);
+	up(&ec->intr.sem);
 
 	if (ec->common.global_lock)
 		acpi_release_global_lock(glk);
@@ -457,7 +466,7 @@
 	return_VALUE(status);
 }
 
-static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
+static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data)
 {
 	int status = 0;
 	u32 glk;
@@ -474,25 +483,23 @@
 	}
 
 	WARN_ON(in_interrupt());
-	down(&ec->burst.sem);
-
-	acpi_ec_enter_burst_mode(ec);
+	down(&ec->intr.sem);
 
 	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
 	if (status) {
-		printk("write EC, IB not empty\n");
+		printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
 	}
 	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
 				&ec->common.command_addr);
 	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
 	if (status) {
-		printk("write EC, IB not empty\n");
+		printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
 	}
 
 	acpi_hw_low_level_write(8, address, &ec->common.data_addr);
 	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
 	if (status) {
-		printk("write EC, IB not empty\n");
+		printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
 	}
 
 	acpi_hw_low_level_write(8, data, &ec->common.data_addr);
@@ -500,8 +507,7 @@
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
 			  data, address));
 
-	acpi_ec_leave_burst_mode(ec);
-	up(&ec->burst.sem);
+	up(&ec->intr.sem);
 
 	if (ec->common.global_lock)
 		acpi_release_global_lock(glk);
@@ -553,12 +559,12 @@
 
 static int acpi_ec_query(union acpi_ec *ec, u32 * data)
 {
-	if (acpi_ec_polling_mode)
-		return acpi_ec_polling_query(ec, data);
+	if (acpi_ec_poll_mode)
+		return acpi_ec_poll_query(ec, data);
 	else
-		return acpi_ec_burst_query(ec, data);
+		return acpi_ec_intr_query(ec, data);
 }
-static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data)
+static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
@@ -583,7 +589,7 @@
 	 * Note that successful completion of the query causes the ACPI_EC_SCI
 	 * bit to be cleared (and thus clearing the interrupt source).
 	 */
-	spin_lock_irqsave(&ec->polling.lock, flags);
+	spin_lock_irqsave(&ec->poll.lock, flags);
 
 	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
 				&ec->common.command_addr);
@@ -596,14 +602,14 @@
 		result = -ENODATA;
 
       end:
-	spin_unlock_irqrestore(&ec->polling.lock, flags);
+	spin_unlock_irqrestore(&ec->poll.lock, flags);
 
 	if (ec->common.global_lock)
 		acpi_release_global_lock(glk);
 
 	return_VALUE(result);
 }
-static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
+static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data)
 {
 	int status = 0;
 	u32 glk;
@@ -620,11 +626,11 @@
 			return_VALUE(-ENODEV);
 	}
 
-	down(&ec->burst.sem);
+	down(&ec->intr.sem);
 
 	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
 	if (status) {
-		printk("query EC, IB not empty\n");
+		printk(KERN_DEBUG PREFIX "query EC, IB not empty\n");
 		goto end;
 	}
 	/*
@@ -636,7 +642,7 @@
 				&ec->common.command_addr);
 	status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
 	if (status) {
-		printk("query EC, OB not full\n");
+		printk(KERN_DEBUG PREFIX "query EC, OB not full\n");
 		goto end;
 	}
 
@@ -645,7 +651,7 @@
 		status = -ENODATA;
 
       end:
-	up(&ec->burst.sem);
+	up(&ec->intr.sem);
 
 	if (ec->common.global_lock)
 		acpi_release_global_lock(glk);
@@ -664,13 +670,13 @@
 
 static void acpi_ec_gpe_query(void *ec_cxt)
 {
-	if (acpi_ec_polling_mode)
-		acpi_ec_gpe_polling_query(ec_cxt);
+	if (acpi_ec_poll_mode)
+		acpi_ec_gpe_poll_query(ec_cxt);
 	else
-		acpi_ec_gpe_burst_query(ec_cxt);
+		acpi_ec_gpe_intr_query(ec_cxt);
 }
 
-static void acpi_ec_gpe_polling_query(void *ec_cxt)
+static void acpi_ec_gpe_poll_query(void *ec_cxt)
 {
 	union acpi_ec *ec = (union acpi_ec *)ec_cxt;
 	u32 value = 0;
@@ -685,9 +691,9 @@
 	if (!ec_cxt)
 		goto end;
 
-	spin_lock_irqsave(&ec->polling.lock, flags);
+	spin_lock_irqsave(&ec->poll.lock, flags);
 	acpi_hw_low_level_read(8, &value, &ec->common.command_addr);
-	spin_unlock_irqrestore(&ec->polling.lock, flags);
+	spin_unlock_irqrestore(&ec->poll.lock, flags);
 
 	/* TBD: Implement asynch events!
 	 * NOTE: All we care about are EC-SCI's.  Other EC events are
@@ -711,7 +717,7 @@
       end:
 	acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
 }
-static void acpi_ec_gpe_burst_query(void *ec_cxt)
+static void acpi_ec_gpe_intr_query(void *ec_cxt)
 {
 	union acpi_ec *ec = (union acpi_ec *)ec_cxt;
 	u32 value;
@@ -736,18 +742,18 @@
 
 	acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
       end:
-	atomic_dec(&ec->burst.pending_gpe);
+	atomic_dec(&ec->intr.pending_gpe);
 	return;
 }
 
 static u32 acpi_ec_gpe_handler(void *data)
 {
-	if (acpi_ec_polling_mode)
-		return acpi_ec_gpe_polling_handler(data);
+	if (acpi_ec_poll_mode)
+		return acpi_ec_gpe_poll_handler(data);
 	else
-		return acpi_ec_gpe_burst_handler(data);
+		return acpi_ec_gpe_intr_handler(data);
 }
-static u32 acpi_ec_gpe_polling_handler(void *data)
+static u32 acpi_ec_gpe_poll_handler(void *data)
 {
 	acpi_status status = AE_OK;
 	union acpi_ec *ec = (union acpi_ec *)data;
@@ -765,7 +771,7 @@
 	else
 		return ACPI_INTERRUPT_NOT_HANDLED;
 }
-static u32 acpi_ec_gpe_burst_handler(void *data)
+static u32 acpi_ec_gpe_intr_handler(void *data)
 {
 	acpi_status status = AE_OK;
 	u32 value;
@@ -777,22 +783,22 @@
 	acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
 	value = acpi_ec_read_status(ec);
 
-	switch (ec->burst.expect_event) {
+	switch (ec->intr.expect_event) {
 	case ACPI_EC_EVENT_OBF:
 		if (!(value & ACPI_EC_FLAG_OBF))
 			break;
 	case ACPI_EC_EVENT_IBE:
 		if ((value & ACPI_EC_FLAG_IBF))
 			break;
-		ec->burst.expect_event = 0;
-		wake_up(&ec->burst.wait);
+		ec->intr.expect_event = 0;
+		wake_up(&ec->intr.wait);
 		return ACPI_INTERRUPT_HANDLED;
 	default:
 		break;
 	}
 
 	if (value & ACPI_EC_FLAG_SCI) {
-		atomic_add(1, &ec->burst.pending_gpe);
+		atomic_add(1, &ec->intr.pending_gpe);
 		status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
 						     acpi_ec_gpe_query, ec);
 		return status == AE_OK ?
@@ -980,7 +986,7 @@
                                Driver Interface
    -------------------------------------------------------------------------- */
 
-static int acpi_ec_polling_add(struct acpi_device *device)
+static int acpi_ec_poll_add(struct acpi_device *device)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
@@ -999,7 +1005,7 @@
 
 	ec->common.handle = device->handle;
 	ec->common.uid = -1;
-	spin_lock_init(&ec->polling.lock);
+	spin_lock_init(&ec->poll.lock);
 	strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
 	strcpy(acpi_device_class(device), ACPI_EC_CLASS);
 	acpi_driver_data(device) = ec;
@@ -1038,7 +1044,7 @@
 	if (result)
 		goto end;
 
-	printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
+	printk(KERN_INFO PREFIX "%s [%s] (gpe %d) polling mode.\n",
 	       acpi_device_name(device), acpi_device_bid(device),
 	       (u32) ec->common.gpe_bit);
 
@@ -1051,7 +1057,7 @@
 
 	return_VALUE(result);
 }
-static int acpi_ec_burst_add(struct acpi_device *device)
+static int acpi_ec_intr_add(struct acpi_device *device)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
@@ -1070,10 +1076,10 @@
 
 	ec->common.handle = device->handle;
 	ec->common.uid = -1;
-	atomic_set(&ec->burst.pending_gpe, 0);
-	atomic_set(&ec->burst.leaving_burst, 1);
-	init_MUTEX(&ec->burst.sem);
-	init_waitqueue_head(&ec->burst.wait);
+	atomic_set(&ec->intr.pending_gpe, 0);
+	atomic_set(&ec->intr.leaving_burst, 1);
+	init_MUTEX(&ec->intr.sem);
+	init_waitqueue_head(&ec->intr.wait);
 	strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
 	strcpy(acpi_device_class(device), ACPI_EC_CLASS);
 	acpi_driver_data(device) = ec;
@@ -1112,8 +1118,7 @@
 	if (result)
 		goto end;
 
-	printk("burst-mode-ec-10-Aug\n");
-	printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
+	printk(KERN_INFO PREFIX "%s [%s] (gpe %d) interrupt mode.\n",
 	       acpi_device_name(device), acpi_device_bid(device),
 	       (u32) ec->common.gpe_bit);
 
@@ -1151,7 +1156,7 @@
 	union acpi_ec *ec = (union acpi_ec *)context;
 	struct acpi_generic_address *addr;
 
-	if (resource->id != ACPI_RSTYPE_IO) {
+	if (resource->type != ACPI_RESOURCE_TYPE_IO) {
 		return AE_OK;
 	}
 
@@ -1171,7 +1176,7 @@
 	addr->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
 	addr->register_bit_width = 8;
 	addr->register_bit_offset = 0;
-	addr->address = resource->data.io.min_base_address;
+	addr->address = resource->data.io.minimum;
 
 	return AE_OK;
 }
@@ -1267,16 +1272,16 @@
 			u32 Level, void *context, void **retval)
 {
 
-	if (acpi_ec_polling_mode)
-		return acpi_fake_ecdt_polling_callback(handle,
+	if (acpi_ec_poll_mode)
+		return acpi_fake_ecdt_poll_callback(handle,
 						       Level, context, retval);
 	else
-		return acpi_fake_ecdt_burst_callback(handle,
+		return acpi_fake_ecdt_intr_callback(handle,
 						     Level, context, retval);
 }
 
 static acpi_status __init
-acpi_fake_ecdt_polling_callback(acpi_handle handle,
+acpi_fake_ecdt_poll_callback(acpi_handle handle,
 				u32 Level, void *context, void **retval)
 {
 	acpi_status status;
@@ -1295,7 +1300,7 @@
 				  &ec_ecdt->common.gpe_bit);
 	if (ACPI_FAILURE(status))
 		return status;
-	spin_lock_init(&ec_ecdt->polling.lock);
+	spin_lock_init(&ec_ecdt->poll.lock);
 	ec_ecdt->common.global_lock = TRUE;
 	ec_ecdt->common.handle = handle;
 
@@ -1308,13 +1313,13 @@
 }
 
 static acpi_status __init
-acpi_fake_ecdt_burst_callback(acpi_handle handle,
+acpi_fake_ecdt_intr_callback(acpi_handle handle,
 			      u32 Level, void *context, void **retval)
 {
 	acpi_status status;
 
-	init_MUTEX(&ec_ecdt->burst.sem);
-	init_waitqueue_head(&ec_ecdt->burst.wait);
+	init_MUTEX(&ec_ecdt->intr.sem);
+	init_waitqueue_head(&ec_ecdt->intr.wait);
 	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
 				     acpi_ec_io_ports, ec_ecdt);
 	if (ACPI_FAILURE(status))
@@ -1380,13 +1385,13 @@
 
 static int __init acpi_ec_get_real_ecdt(void)
 {
-	if (acpi_ec_polling_mode)
-		return acpi_ec_polling_get_real_ecdt();
+	if (acpi_ec_poll_mode)
+		return acpi_ec_poll_get_real_ecdt();
 	else
-		return acpi_ec_burst_get_real_ecdt();
+		return acpi_ec_intr_get_real_ecdt();
 }
 
-static int __init acpi_ec_polling_get_real_ecdt(void)
+static int __init acpi_ec_poll_get_real_ecdt(void)
 {
 	acpi_status status;
 	struct acpi_table_ecdt *ecdt_ptr;
@@ -1411,7 +1416,7 @@
 	ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
 	ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
 	ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
-	spin_lock_init(&ec_ecdt->polling.lock);
+	spin_lock_init(&ec_ecdt->poll.lock);
 	/* use the GL just to be safe */
 	ec_ecdt->common.global_lock = TRUE;
 	ec_ecdt->common.uid = ecdt_ptr->uid;
@@ -1431,7 +1436,7 @@
 	return -ENODEV;
 }
 
-static int __init acpi_ec_burst_get_real_ecdt(void)
+static int __init acpi_ec_intr_get_real_ecdt(void)
 {
 	acpi_status status;
 	struct acpi_table_ecdt *ecdt_ptr;
@@ -1452,8 +1457,8 @@
 		return -ENOMEM;
 	memset(ec_ecdt, 0, sizeof(union acpi_ec));
 
-	init_MUTEX(&ec_ecdt->burst.sem);
-	init_waitqueue_head(&ec_ecdt->burst.wait);
+	init_MUTEX(&ec_ecdt->intr.sem);
+	init_waitqueue_head(&ec_ecdt->intr.wait);
 	ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
 	ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
 	ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
@@ -1571,22 +1576,22 @@
 }
 
 __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
-static int __init acpi_ec_set_polling_mode(char *str)
+static int __init acpi_ec_set_intr_mode(char *str)
 {
-	int burst;
+	int intr;
 
-	if (!get_option(&str, &burst))
+	if (!get_option(&str, &intr))
 		return 0;
 
-	if (burst) {
-		acpi_ec_polling_mode = EC_BURST;
-		acpi_ec_driver.ops.add = acpi_ec_burst_add;
+	if (intr) {
+		acpi_ec_poll_mode = EC_INTR;
+		acpi_ec_driver.ops.add = acpi_ec_intr_add;
 	} else {
-		acpi_ec_polling_mode = EC_POLLING;
-		acpi_ec_driver.ops.add = acpi_ec_polling_add;
+		acpi_ec_poll_mode = EC_POLL;
+		acpi_ec_driver.ops.add = acpi_ec_poll_add;
 	}
-	printk(KERN_INFO PREFIX "EC %s mode.\n", burst ? "burst" : "polling");
+	printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling");
 	return 0;
 }
 
-__setup("ec_burst=", acpi_ec_set_polling_mode);
+__setup("ec_intr=", acpi_ec_set_intr_mode);
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index 842d1e3..c9ac05c 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -73,7 +73,7 @@
 	/* Make sure we have ACPI tables */
 
 	if (!acpi_gbl_DSDT) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "No ACPI tables present!\n"));
+		ACPI_WARNING((AE_INFO, "No ACPI tables present!"));
 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
 	}
 
@@ -84,14 +84,15 @@
 	 */
 	status = acpi_ev_fixed_event_initialize();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Unable to initialize fixed events, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Unable to initialize fixed events"));
 		return_ACPI_STATUS(status);
 	}
 
 	status = acpi_ev_gpe_initialize();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Unable to initialize general purpose events, %s\n", acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Unable to initialize general purpose events"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -100,6 +101,48 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ev_install_fadt_gpes
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks
+ *              (0 and 1). This causes the _PRW methods to be run, so the HW
+ *              must be fully initialized at this point, including global lock
+ *              support.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ev_install_fadt_gpes(void)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE("ev_install_fadt_gpes");
+
+	/* Namespace must be locked */
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	/* FADT GPE Block 0 */
+
+	(void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
+					   acpi_gbl_gpe_fadt_blocks[0]);
+
+	/* FADT GPE Block 1 */
+
+	(void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
+					   acpi_gbl_gpe_fadt_blocks[1]);
+
+	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+	return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ev_install_xrupt_handlers
  *
  * PARAMETERS:  None
@@ -120,7 +163,8 @@
 
 	status = acpi_ev_install_sci_handler();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Unable to install System Control Interrupt Handler, %s\n", acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Unable to install System Control Interrupt handler"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -128,7 +172,8 @@
 
 	status = acpi_ev_init_global_lock_handler();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Unable to initialize Global Lock handler, %s\n", acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Unable to initialize Global Lock handler"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -262,7 +307,9 @@
 					enable_register_id, 0,
 					ACPI_MTX_DO_NOT_LOCK);
 
-		ACPI_REPORT_ERROR(("No installed handler for fixed event [%08X]\n", event));
+		ACPI_ERROR((AE_INFO,
+			    "No installed handler for fixed event [%08X]",
+			    event));
 
 		return (ACPI_INTERRUPT_NOT_HANDLED);
 	}
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index b2f232d..f64f977 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -372,14 +372,14 @@
 
 u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 {
-	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
-	u8 enabled_status_byte;
-	struct acpi_gpe_register_info *gpe_register_info;
-	u32 status_reg;
-	u32 enable_reg;
-	u32 flags;
 	acpi_status status;
 	struct acpi_gpe_block_info *gpe_block;
+	struct acpi_gpe_register_info *gpe_register_info;
+	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
+	u8 enabled_status_byte;
+	u32 status_reg;
+	u32 enable_reg;
+	acpi_cpu_flags flags;
 	acpi_native_uint i;
 	acpi_native_uint j;
 
@@ -546,7 +546,11 @@
 
 		status = acpi_ns_evaluate_by_handle(&info);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("%s while evaluating method [%4.4s] for GPE[%2X]\n", acpi_format_exception(status), acpi_ut_get_node_name(local_gpe_event_info.dispatch.method_node), gpe_number));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"While evaluating method [%4.4s] for GPE[%2X]",
+					acpi_ut_get_node_name
+					(local_gpe_event_info.dispatch.
+					 method_node), gpe_number));
 		}
 	}
 
@@ -599,8 +603,10 @@
 	    ACPI_GPE_EDGE_TRIGGERED) {
 		status = acpi_hw_clear_gpe(gpe_event_info);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
-			return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Unable to clear GPE[%2X]",
+					gpe_number));
+			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 		}
 	}
 
@@ -637,8 +643,10 @@
 		    ACPI_GPE_LEVEL_TRIGGERED) {
 			status = acpi_hw_clear_gpe(gpe_event_info);
 			if (ACPI_FAILURE(status)) {
-				ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
-				return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+				ACPI_EXCEPTION((AE_INFO, status,
+						"Unable to clear GPE[%2X]",
+						gpe_number));
+				return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 			}
 		}
 		break;
@@ -651,8 +659,10 @@
 		 */
 		status = acpi_ev_disable_gpe(gpe_event_info);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
-			return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Unable to disable GPE[%2X]",
+					gpe_number));
+			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 		}
 
 		/*
@@ -663,7 +673,9 @@
 						     acpi_ev_asynch_execute_gpe_method,
 						     gpe_event_info);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n", acpi_format_exception(status), gpe_number));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Unable to queue handler for GPE[%2X] - event disabled",
+					gpe_number));
 		}
 		break;
 
@@ -671,7 +683,9 @@
 
 		/* No handler or method to run! */
 
-		ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n", gpe_number));
+		ACPI_ERROR((AE_INFO,
+			    "No handler or method for GPE[%2X], disabling event",
+			    gpe_number));
 
 		/*
 		 * Disable the GPE.  The GPE will remain disabled until the ACPI
@@ -679,13 +693,15 @@
 		 */
 		status = acpi_ev_disable_gpe(gpe_event_info);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
-			return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Unable to disable GPE[%2X]",
+					gpe_number));
+			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 		}
 		break;
 	}
 
-	return_VALUE(ACPI_INTERRUPT_HANDLED);
+	return_UINT32(ACPI_INTERRUPT_HANDLED);
 }
 
 #ifdef ACPI_GPE_NOTIFY_CHECK
@@ -722,7 +738,9 @@
 
 		acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
 
-		ACPI_REPORT_INFO(("GPE %p was updated from wake/run to wake-only\n", gpe_event_info));
+		ACPI_INFO((AE_INFO,
+			   "GPE %p was updated from wake/run to wake-only",
+			   gpe_event_info));
 
 		/* This was a wake-only GPE */
 
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index b312eb3..0fd00b5 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -78,7 +78,7 @@
  *
  * RETURN:      TRUE if the gpe_event is valid
  *
- * DESCRIPTION: Validate a GPE event.  DO NOT CALL FROM INTERRUPT LEVEL.
+ * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
  *              Should be called only when the GPE lists are semaphore locked
  *              and not subject to change.
  *
@@ -136,7 +136,7 @@
 	struct acpi_gpe_block_info *gpe_block;
 	struct acpi_gpe_xrupt_info *gpe_xrupt_info;
 	acpi_status status = AE_OK;
-	u32 flags;
+	acpi_cpu_flags flags;
 
 	ACPI_FUNCTION_TRACE("ev_walk_gpe_list");
 
@@ -264,7 +264,7 @@
 	 * 2) Edge/Level determination is based on the 2nd character
 	 *    of the method name
 	 *
-	 * NOTE: Default GPE type is RUNTIME.  May be changed later to WAKE
+	 * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
 	 * if a _PRW object is found that points to this GPE.
 	 */
 	switch (name[1]) {
@@ -279,9 +279,9 @@
 	default:
 		/* Unknown method type, just ignore it! */
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
-				  name));
+		ACPI_ERROR((AE_INFO,
+			    "Unknown GPE method type: %s (name not of form _Lxx or _Exx)",
+			    name));
 		return_ACPI_STATUS(AE_OK);
 	}
 
@@ -291,9 +291,9 @@
 	if (gpe_number == ACPI_UINT32_MAX) {
 		/* Conversion failed; invalid method, just ignore it */
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
-				  name));
+		ACPI_ERROR((AE_INFO,
+			    "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)",
+			    name));
 		return_ACPI_STATUS(AE_OK);
 	}
 
@@ -313,14 +313,14 @@
 
 	/*
 	 * Now we can add this information to the gpe_event_info block
-	 * for use during dispatch of this GPE.  Default type is RUNTIME, although
+	 * for use during dispatch of this GPE. Default type is RUNTIME, although
 	 * this may change when the _PRW methods are executed later.
 	 */
 	gpe_event_info =
 	    &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
 
-	gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
-				      ACPI_GPE_TYPE_RUNTIME);
+	gpe_event_info->flags = (u8)
+	    (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
 
 	gpe_event_info->dispatch.method_node =
 	    (struct acpi_namespace_node *)obj_handle;
@@ -341,11 +341,11 @@
  *
  * PARAMETERS:  Callback from walk_namespace
  *
- * RETURN:      Status.  NOTE: We ignore errors so that the _PRW walk is
+ * RETURN:      Status. NOTE: We ignore errors so that the _PRW walk is
  *              not aborted on a single _PRW failure.
  *
  * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
- *              Device.  Run the _PRW method.  If present, extract the GPE
+ *              Device. Run the _PRW method. If present, extract the GPE
  *              number and mark the GPE as a WAKE GPE.
  *
  ******************************************************************************/
@@ -443,6 +443,7 @@
 
 		gpe_event_info->flags &=
 		    ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
+
 		status =
 		    acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
 		if (ACPI_FAILURE(status)) {
@@ -466,7 +467,7 @@
  *
  * RETURN:      A GPE interrupt block
  *
- * DESCRIPTION: Get or Create a GPE interrupt block.  There is one interrupt
+ * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
  *              block per unique interrupt level used for GPEs.
  *              Should be called only when the GPE lists are semaphore locked
  *              and not subject to change.
@@ -479,7 +480,7 @@
 	struct acpi_gpe_xrupt_info *next_gpe_xrupt;
 	struct acpi_gpe_xrupt_info *gpe_xrupt;
 	acpi_status status;
-	u32 flags;
+	acpi_cpu_flags flags;
 
 	ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block");
 
@@ -526,9 +527,9 @@
 							   acpi_ev_gpe_xrupt_handler,
 							   gpe_xrupt);
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Could not install GPE interrupt handler at level 0x%X\n",
-					  interrupt_number));
+			ACPI_ERROR((AE_INFO,
+				    "Could not install GPE interrupt handler at level 0x%X",
+				    interrupt_number));
 			return_PTR(NULL);
 		}
 	}
@@ -553,7 +554,7 @@
 acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
 {
 	acpi_status status;
-	u32 flags;
+	acpi_cpu_flags flags;
 
 	ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt");
 
@@ -566,8 +567,9 @@
 
 	/* Disable this interrupt */
 
-	status = acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
-						  acpi_ev_gpe_xrupt_handler);
+	status =
+	    acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
+					     acpi_ev_gpe_xrupt_handler);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
@@ -610,7 +612,7 @@
 	struct acpi_gpe_block_info *next_gpe_block;
 	struct acpi_gpe_xrupt_info *gpe_xrupt_block;
 	acpi_status status;
-	u32 flags;
+	acpi_cpu_flags flags;
 
 	ACPI_FUNCTION_TRACE("ev_install_gpe_block");
 
@@ -663,7 +665,7 @@
 acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
 {
 	acpi_status status;
-	u32 flags;
+	acpi_cpu_flags flags;
 
 	ACPI_FUNCTION_TRACE("ev_install_gpe_block");
 
@@ -743,22 +745,22 @@
 					       sizeof(struct
 						      acpi_gpe_register_info));
 	if (!gpe_register_info) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Could not allocate the gpe_register_info table\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Could not allocate the gpe_register_info table"));
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
 	/*
 	 * Allocate the GPE event_info block. There are eight distinct GPEs
-	 * per register.  Initialization to zeros is sufficient.
+	 * per register. Initialization to zeros is sufficient.
 	 */
 	gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block->
 					     register_count *
 					     ACPI_GPE_REGISTER_WIDTH) *
 					    sizeof(struct acpi_gpe_event_info));
 	if (!gpe_event_info) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Could not allocate the gpe_event_info table\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Could not allocate the gpe_event_info table"));
 		status = AE_NO_MEMORY;
 		goto error_exit;
 	}
@@ -769,9 +771,9 @@
 	gpe_block->event_info = gpe_event_info;
 
 	/*
-	 * Initialize the GPE Register and Event structures.  A goal of these
+	 * Initialize the GPE Register and Event structures. A goal of these
 	 * tables is to hide the fact that there are two separate GPE register sets
-	 * in a given gpe hardware block, the status registers occupy the first half,
+	 * in a given GPE hardware block, the status registers occupy the first half,
 	 * and the enable registers occupy the second half.
 	 */
 	this_register = gpe_register_info;
@@ -812,11 +814,8 @@
 			this_event++;
 		}
 
-		/*
-		 * Clear the status/enable registers.  Note that status registers
-		 * are cleared by writing a '1', while enable registers are cleared
-		 * by writing a '0'.
-		 */
+		/* Disable all GPEs within this register */
+
 		status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0x00,
 						 &this_register->
 						 enable_address);
@@ -824,6 +823,8 @@
 			goto error_exit;
 		}
 
+		/* Clear any pending GPE events within this register */
+
 		status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0xFF,
 						 &this_register->
 						 status_address);
@@ -860,7 +861,9 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Create and Install a block of GPE registers
+ * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
+ *              the block are disabled at exit.
+ *              Note: Assumes namespace is locked.
  *
  ******************************************************************************/
 
@@ -872,14 +875,8 @@
 			 u32 interrupt_number,
 			 struct acpi_gpe_block_info **return_gpe_block)
 {
-	struct acpi_gpe_block_info *gpe_block;
-	struct acpi_gpe_event_info *gpe_event_info;
-	acpi_native_uint i;
-	acpi_native_uint j;
-	u32 wake_gpe_count;
-	u32 gpe_enabled_count;
 	acpi_status status;
-	struct acpi_gpe_walk_info gpe_info;
+	struct acpi_gpe_block_info *gpe_block;
 
 	ACPI_FUNCTION_TRACE("ev_create_gpe_block");
 
@@ -896,22 +893,24 @@
 
 	/* Initialize the new GPE block */
 
+	gpe_block->node = gpe_device;
 	gpe_block->register_count = register_count;
 	gpe_block->block_base_number = gpe_block_base_number;
-	gpe_block->node = gpe_device;
 
 	ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
 		    sizeof(struct acpi_generic_address));
 
-	/* Create the register_info and event_info sub-structures */
-
+	/*
+	 * Create the register_info and event_info sub-structures
+	 * Note: disables and clears all GPEs in the block
+	 */
 	status = acpi_ev_create_gpe_info_blocks(gpe_block);
 	if (ACPI_FAILURE(status)) {
 		ACPI_MEM_FREE(gpe_block);
 		return_ACPI_STATUS(status);
 	}
 
-	/* Install the new block in the global list(s) */
+	/* Install the new block in the global lists */
 
 	status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
 	if (ACPI_FAILURE(status)) {
@@ -926,16 +925,70 @@
 					acpi_ev_save_method_info, gpe_block,
 					NULL);
 
+	/* Return the new block */
+
+	if (return_gpe_block) {
+		(*return_gpe_block) = gpe_block;
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+			  "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
+			  (u32) gpe_block->block_base_number,
+			  (u32) (gpe_block->block_base_number +
+				 ((gpe_block->register_count *
+				   ACPI_GPE_REGISTER_WIDTH) - 1)),
+			  gpe_device->name.ascii, gpe_block->register_count,
+			  interrupt_number));
+
+	return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_initialize_gpe_block
+ *
+ * PARAMETERS:  gpe_device          - Handle to the parent GPE block
+ *              gpe_block           - Gpe Block info
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initialize and enable a GPE block. First find and run any
+ *              _PRT methods associated with the block, then enable the
+ *              appropriate GPEs.
+ *              Note: Assumes namespace is locked.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
+			     struct acpi_gpe_block_info *gpe_block)
+{
+	acpi_status status;
+	struct acpi_gpe_event_info *gpe_event_info;
+	struct acpi_gpe_walk_info gpe_info;
+	u32 wake_gpe_count;
+	u32 gpe_enabled_count;
+	acpi_native_uint i;
+	acpi_native_uint j;
+
+	ACPI_FUNCTION_TRACE("ev_initialize_gpe_block");
+
+	/* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
+
+	if (!gpe_block) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
 	/*
-	 * Runtime option: Should Wake GPEs be enabled at runtime?  The default
-	 * is No, they should only be enabled just as the machine goes to sleep.
+	 * Runtime option: Should wake GPEs be enabled at runtime?  The default
+	 * is no, they should only be enabled just as the machine goes to sleep.
 	 */
 	if (acpi_gbl_leave_wake_gpes_disabled) {
 		/*
-		 * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
-		 * (Each GPE that has one or more _PRWs that reference it is by
-		 * definition a WAKE GPE and will not be enabled while the machine
-		 * is running.)
+		 * Differentiate runtime vs wake GPEs, via the _PRW control methods.
+		 * Each GPE that has one or more _PRWs that reference it is by
+		 * definition a wake GPE and will not be enabled while the machine
+		 * is running.
 		 */
 		gpe_info.gpe_block = gpe_block;
 		gpe_info.gpe_device = gpe_device;
@@ -948,9 +1001,12 @@
 	}
 
 	/*
-	 * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
-	 * and 2) have a corresponding _Lxx or _Exx method.  All other GPEs must
-	 * be enabled via the acpi_enable_gpe() external interface.
+	 * Enable all GPEs in this block that have these attributes:
+	 * 1) are "runtime" or "run/wake" GPEs, and
+	 * 2) have a corresponding _Lxx or _Exx method
+	 *
+	 * Any other GPEs within this block must be enabled via the acpi_enable_gpe()
+	 * external interface.
 	 */
 	wake_gpe_count = 0;
 	gpe_enabled_count = 0;
@@ -976,32 +1032,19 @@
 		}
 	}
 
-	/* Dump info about this GPE block */
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
-			  "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
-			  (u32) gpe_block->block_base_number,
-			  (u32) (gpe_block->block_base_number +
-				 ((gpe_block->register_count *
-				   ACPI_GPE_REGISTER_WIDTH) - 1)),
-			  gpe_device->name.ascii, gpe_block->register_count,
-			  interrupt_number));
-
-	/* Enable all valid GPEs found above */
-
-	status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
-
 	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
 			  "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
 			  wake_gpe_count, gpe_enabled_count));
 
-	/* Return the new block */
+	/* Enable all valid runtime GPEs found above */
 
-	if (return_gpe_block) {
-		(*return_gpe_block) = gpe_block;
+	status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
+	if (ACPI_FAILURE(status)) {
+		ACPI_ERROR((AE_INFO, "Could not enable GPEs in gpe_block %p",
+			    gpe_block));
 	}
 
-	return_ACPI_STATUS(AE_OK);
+	return_ACPI_STATUS(status);
 }
 
 /*******************************************************************************
@@ -1072,8 +1115,8 @@
 						  &acpi_gbl_gpe_fadt_blocks[0]);
 
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("Could not create GPE Block 0, %s\n",
-					   acpi_format_exception(status)));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Could not create GPE Block 0"));
 		}
 	}
 
@@ -1086,7 +1129,12 @@
 
 		if ((register_count0) &&
 		    (gpe_number_max >= acpi_gbl_FADT->gpe1_base)) {
-			ACPI_REPORT_ERROR(("GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n", gpe_number_max, acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
+			ACPI_ERROR((AE_INFO,
+				    "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1",
+				    gpe_number_max, acpi_gbl_FADT->gpe1_base,
+				    acpi_gbl_FADT->gpe1_base +
+				    ((register_count1 *
+				      ACPI_GPE_REGISTER_WIDTH) - 1)));
 
 			/* Ignore GPE1 block by setting the register count to zero */
 
@@ -1104,7 +1152,8 @@
 						     [1]);
 
 			if (ACPI_FAILURE(status)) {
-				ACPI_REPORT_ERROR(("Could not create GPE Block 1, %s\n", acpi_format_exception(status)));
+				ACPI_EXCEPTION((AE_INFO, status,
+						"Could not create GPE Block 1"));
 			}
 
 			/*
@@ -1130,7 +1179,9 @@
 	/* Check for Max GPE number out-of-range */
 
 	if (gpe_number_max > ACPI_GPE_MAX) {
-		ACPI_REPORT_ERROR(("Maximum GPE number from FADT is too large: 0x%X\n", gpe_number_max));
+		ACPI_ERROR((AE_INFO,
+			    "Maximum GPE number from FADT is too large: 0x%X",
+			    gpe_number_max));
 		status = AE_BAD_VALUE;
 		goto cleanup;
 	}
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 7e57b84..0909ba6 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -303,7 +303,8 @@
 		    acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore,
 					     acpi_gbl_global_lock_thread_count);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("Could not signal Global Lock semaphore\n"));
+			ACPI_ERROR((AE_INFO,
+				    "Could not signal Global Lock semaphore"));
 		}
 	}
 }
@@ -344,7 +345,8 @@
 						     acpi_ev_global_lock_thread,
 						     context);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("Could not queue Global Lock thread, %s\n", acpi_format_exception(status)));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Could not queue Global Lock thread"));
 
 			return (ACPI_INTERRUPT_NOT_HANDLED);
 		}
@@ -384,7 +386,8 @@
 	 * with an error.
 	 */
 	if (status == AE_NO_HARDWARE_RESPONSE) {
-		ACPI_REPORT_ERROR(("No response from Global Lock hardware, disabling lock\n"));
+		ACPI_ERROR((AE_INFO,
+			    "No response from Global Lock hardware, disabling lock"));
 
 		acpi_gbl_global_lock_present = FALSE;
 		status = AE_OK;
@@ -480,7 +483,8 @@
 	ACPI_FUNCTION_TRACE("ev_release_global_lock");
 
 	if (!acpi_gbl_global_lock_thread_count) {
-		ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n"));
+		ACPI_WARNING((AE_INFO,
+			      "Cannot release HW Global Lock, it has not been acquired"));
 		return_ACPI_STATUS(AE_NOT_ACQUIRED);
 	}
 
@@ -542,9 +546,9 @@
 		for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
 			status = acpi_disable_event((u32) i, 0);
 			if (ACPI_FAILURE(status)) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Could not disable fixed event %d\n",
-						  (u32) i));
+				ACPI_ERROR((AE_INFO,
+					    "Could not disable fixed event %d",
+					    (u32) i));
 			}
 		}
 
@@ -556,8 +560,7 @@
 
 		status = acpi_ev_remove_sci_handler();
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Could not remove SCI handler\n"));
+			ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
 		}
 	}
 
@@ -570,8 +573,7 @@
 	if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
 		status = acpi_disable();
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-					  "acpi_disable failed\n"));
+			ACPI_WARNING((AE_INFO, "acpi_disable failed"));
 		}
 	}
 	return_VOID;
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index 84fad08..6da58e7 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -295,12 +295,12 @@
 
 	handler_desc = region_obj->region.handler;
 	if (!handler_desc) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "No handler for Region [%4.4s] (%p) [%s]\n",
-				  acpi_ut_get_node_name(region_obj->region.
-							node), region_obj,
-				  acpi_ut_get_region_name(region_obj->region.
-							  space_id)));
+		ACPI_ERROR((AE_INFO,
+			    "No handler for Region [%4.4s] (%p) [%s]",
+			    acpi_ut_get_node_name(region_obj->region.node),
+			    region_obj,
+			    acpi_ut_get_region_name(region_obj->region.
+						    space_id)));
 
 		return_ACPI_STATUS(AE_NOT_EXIST);
 	}
@@ -317,12 +317,11 @@
 		if (!region_setup) {
 			/* No initialization routine, exit with error */
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "No init routine for region(%p) [%s]\n",
-					  region_obj,
-					  acpi_ut_get_region_name(region_obj->
-								  region.
-								  space_id)));
+			ACPI_ERROR((AE_INFO,
+				    "No init routine for region(%p) [%s]",
+				    region_obj,
+				    acpi_ut_get_region_name(region_obj->region.
+							    space_id)));
 			return_ACPI_STATUS(AE_NOT_EXIST);
 		}
 
@@ -347,12 +346,11 @@
 		/* Check for failure of the Region Setup */
 
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Region Init: %s [%s]\n",
-					  acpi_format_exception(status),
-					  acpi_ut_get_region_name(region_obj->
-								  region.
-								  space_id)));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"During region initialization: [%s]",
+					acpi_ut_get_region_name(region_obj->
+								region.
+								space_id)));
 			return_ACPI_STATUS(status);
 		}
 
@@ -406,10 +404,9 @@
 			 region_obj2->extra.region_context);
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Handler for [%s] returned %s\n",
-				   acpi_ut_get_region_name(region_obj->region.
-							   space_id),
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
+				acpi_ut_get_region_name(region_obj->region.
+							space_id)));
 	}
 
 	if (!
@@ -501,12 +498,10 @@
 
 			status = acpi_ev_execute_reg_method(region_obj, 0);
 			if (ACPI_FAILURE(status)) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "%s from region _REG, [%s]\n",
-						  acpi_format_exception(status),
-						  acpi_ut_get_region_name
-						  (region_obj->region.
-						   space_id)));
+				ACPI_EXCEPTION((AE_INFO, status,
+						"from region _REG, [%s]",
+						acpi_ut_get_region_name
+						(region_obj->region.space_id)));
 			}
 
 			if (acpi_ns_is_locked) {
@@ -528,12 +523,10 @@
 			/* Init routine may fail, Just ignore errors */
 
 			if (ACPI_FAILURE(status)) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "%s from region init, [%s]\n",
-						  acpi_format_exception(status),
-						  acpi_ut_get_region_name
-						  (region_obj->region.
-						   space_id)));
+				ACPI_EXCEPTION((AE_INFO, status,
+						"from region init, [%s]",
+						acpi_ut_get_region_name
+						(region_obj->region.space_id)));
 			}
 
 			region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index a1bd2da..baed8c1 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -233,7 +233,11 @@
 							 */
 							status = AE_OK;
 						} else {
-							ACPI_REPORT_ERROR(("Could not install pci_config handler for Root Bridge %4.4s, %s\n", acpi_ut_get_node_name(pci_root_node), acpi_format_exception(status)));
+							ACPI_EXCEPTION((AE_INFO,
+									status,
+									"Could not install pci_config handler for Root Bridge %4.4s",
+									acpi_ut_get_node_name
+									(pci_root_node)));
 						}
 					}
 					break;
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
index 1418359..9a62216 100644
--- a/drivers/acpi/events/evsci.c
+++ b/drivers/acpi/events/evsci.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -88,7 +88,7 @@
 	 */
 	interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
 
-	return_VALUE(interrupt_handled);
+	return_UINT32(interrupt_handled);
 }
 
 /*******************************************************************************
@@ -121,7 +121,7 @@
 	 */
 	interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
 
-	return_VALUE(interrupt_handled);
+	return_UINT32(interrupt_handled);
 }
 
 /******************************************************************************
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index 43b33d1..b38b39d 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -143,8 +143,8 @@
 	if (ACPI_SUCCESS(status))
 		status = acpi_enable_event(event, 0);
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-				  "Could not enable fixed event.\n"));
+		ACPI_WARNING((AE_INFO, "Could not enable fixed event %X",
+			      event));
 
 		/* Remove the handler */
 
@@ -204,10 +204,11 @@
 	acpi_gbl_fixed_event_handlers[event].context = NULL;
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-				  "Could not write to fixed event enable register.\n"));
+		ACPI_WARNING((AE_INFO,
+			      "Could not write to fixed event enable register %X",
+			      event));
 	} else {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X.\n",
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
 				  event));
 	}
 
@@ -434,7 +435,7 @@
 
 	if (device == ACPI_ROOT_OBJECT) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Removing notify handler for ROOT object.\n"));
+				  "Removing notify handler for namespace root object\n"));
 
 		if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
 		     !acpi_gbl_system_notify.handler) ||
@@ -562,7 +563,7 @@
 	struct acpi_gpe_event_info *gpe_event_info;
 	struct acpi_handler_info *handler;
 	acpi_status status;
-	u32 flags;
+	acpi_cpu_flags flags;
 
 	ACPI_FUNCTION_TRACE("acpi_install_gpe_handler");
 
@@ -653,7 +654,7 @@
 	struct acpi_gpe_event_info *gpe_event_info;
 	struct acpi_handler_info *handler;
 	acpi_status status;
-	u32 flags;
+	acpi_cpu_flags flags;
 
 	ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler");
 
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index 887ff9f..ec9ce84 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -70,8 +70,7 @@
 	/* Make sure we have the FADT */
 
 	if (!acpi_gbl_FADT) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-				  "No FADT information present!\n"));
+		ACPI_WARNING((AE_INFO, "No FADT information present!"));
 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
 	}
 
@@ -83,7 +82,8 @@
 
 		status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("Could not transition to ACPI mode.\n"));
+			ACPI_ERROR((AE_INFO,
+				    "Could not transition to ACPI mode"));
 			return_ACPI_STATUS(status);
 		}
 
@@ -113,8 +113,7 @@
 	ACPI_FUNCTION_TRACE("acpi_disable");
 
 	if (!acpi_gbl_FADT) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-				  "No FADT information present!\n"));
+		ACPI_WARNING((AE_INFO, "No FADT information present!"));
 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
 	}
 
@@ -127,8 +126,8 @@
 		status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
 
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Could not exit ACPI mode to legacy mode"));
+			ACPI_ERROR((AE_INFO,
+				    "Could not exit ACPI mode to legacy mode"));
 			return_ACPI_STATUS(status);
 		}
 
@@ -185,9 +184,9 @@
 	}
 
 	if (value != 1) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Could not enable %s event\n",
-				  acpi_ut_get_event_name(event)));
+		ACPI_ERROR((AE_INFO,
+			    "Could not enable %s event",
+			    acpi_ut_get_event_name(event)));
 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
 	}
 
@@ -384,9 +383,9 @@
 	}
 
 	if (value != 0) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Could not disable %s events\n",
-				  acpi_ut_get_event_name(event)));
+		ACPI_ERROR((AE_INFO,
+			    "Could not disable %s events",
+			    acpi_ut_get_event_name(event)));
 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
 	}
 
@@ -626,6 +625,13 @@
 		goto unlock_and_exit;
 	}
 
+	/* Run the _PRW methods and enable the GPEs */
+
+	status = acpi_ev_initialize_gpe_block(node, gpe_block);
+	if (ACPI_FAILURE(status)) {
+		goto unlock_and_exit;
+	}
+
 	/* Get the device_object attached to the node */
 
 	obj_desc = acpi_ns_get_attached_object(node);
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
index 6f28ea2..abf5cac 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/events/evxfregn.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 1ce365d..a29782f 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -413,9 +413,9 @@
 	    (!ACPI_STRNCMP(table_ptr->signature,
 			   acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
 			   acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Table has invalid signature [%4.4s], must be SSDT or PSDT\n",
-				  table_ptr->signature));
+		ACPI_ERROR((AE_INFO,
+			    "Table has invalid signature [%4.4s], must be SSDT or PSDT",
+			    table_ptr->signature));
 		status = AE_BAD_SIGNATURE;
 		goto cleanup;
 	}
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index 04e5194..e6d52e1 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/executer/exconvrt.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -504,18 +504,12 @@
 		}
 
 		/*
-		 * Perform the conversion.
+		 * Create a new string object and string buffer
 		 * (-1 because of extra separator included in string_length from above)
 		 */
-		string_length--;
-		if (string_length > ACPI_MAX_STRING_CONVERSION) {	/* ACPI limit */
-			return_ACPI_STATUS(AE_AML_STRING_LIMIT);
-		}
-
-		/* Create a new string object and string buffer */
-
 		return_desc =
-		    acpi_ut_create_string_object((acpi_size) string_length);
+		    acpi_ut_create_string_object((acpi_size)
+						 (string_length - 1));
 		if (!return_desc) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
@@ -647,7 +641,9 @@
 			break;
 
 		default:
-			ACPI_REPORT_ERROR(("Bad destination type during conversion: %X\n", destination_type));
+			ACPI_ERROR((AE_INFO,
+				    "Bad destination type during conversion: %X",
+				    destination_type));
 			status = AE_AML_INTERNAL;
 			break;
 		}
@@ -660,17 +656,13 @@
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unknown Target type ID 0x%X Op %s dest_type %s\n",
-				  GET_CURRENT_ARG_TYPE(walk_state->op_info->
-						       runtime_args),
-				  walk_state->op_info->name,
-				  acpi_ut_get_type_name(destination_type)));
-
-		ACPI_REPORT_ERROR(("Bad Target Type (ARGI): %X\n",
-				   GET_CURRENT_ARG_TYPE(walk_state->op_info->
-							runtime_args)))
-		    status = AE_AML_INTERNAL;
+		ACPI_ERROR((AE_INFO,
+			    "Unknown Target type ID 0x%X aml_opcode %X dest_type %s",
+			    GET_CURRENT_ARG_TYPE(walk_state->op_info->
+						 runtime_args),
+			    walk_state->opcode,
+			    acpi_ut_get_type_name(destination_type)));
+		status = AE_AML_INTERNAL;
 	}
 
 	/*
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 91c4918..6805754 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -300,8 +300,8 @@
 	 */
 	if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
 	    (region_space < ACPI_USER_REGION_BEGIN)) {
-		ACPI_REPORT_ERROR(("Invalid address_space type %X\n",
-				   region_space));
+		ACPI_ERROR((AE_INFO, "Invalid address_space type %X",
+			    region_space));
 		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
 	}
 
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index bc2fa99..a7cca8d 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,20 +55,386 @@
  */
 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
 /* Local prototypes */
-#ifdef ACPI_FUTURE_USAGE
 static void acpi_ex_out_string(char *title, char *value);
 
 static void acpi_ex_out_pointer(char *title, void *value);
 
-static void acpi_ex_out_integer(char *title, u32 value);
-
 static void acpi_ex_out_address(char *title, acpi_physical_address value);
 
-static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc);
+static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc);
 
 static void
-acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index);
-#endif				/* ACPI_FUTURE_USAGE */
+acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
+			 u32 level, u32 index);
+
+/*******************************************************************************
+ *
+ * Object Descriptor info tables
+ *
+ * Note: The first table entry must be an INIT opcode and must contain
+ * the table length (number of table entries)
+ *
+ ******************************************************************************/
+
+static struct acpi_exdump_info acpi_ex_dump_integer[2] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_integer), NULL},
+	{ACPI_EXD_UINT64, ACPI_EXD_OFFSET(integer.value), "Value"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_string[4] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_string), NULL},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(string.length), "Length"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(string.pointer), "Pointer"},
+	{ACPI_EXD_STRING, 0, NULL}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_buffer[4] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer), NULL},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(buffer.length), "Length"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.pointer), "Pointer"},
+	{ACPI_EXD_BUFFER, 0, NULL}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_package[5] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_package), NULL},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(package.flags), "Flags"},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(package.count), "Elements"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(package.elements), "Element List"},
+	{ACPI_EXD_PACKAGE, 0, NULL}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_device[4] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.system_notify),
+	 "System Notify"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.device_notify),
+	 "Device Notify"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_event[2] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_event), NULL},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(event.semaphore), "Semaphore"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_method[8] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "param_count"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.concurrency), "Concurrency"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.semaphore), "Semaphore"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.thread_count), "Thread Count"},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(method.aml_length), "Aml Length"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_mutex[5] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"},
+	{ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth),
+	 "Acquire Depth"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.semaphore), "Semaphore"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_region[7] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region), NULL},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.space_id), "Space Id"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.flags), "Flags"},
+	{ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(region.address), "Address"},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(region.length), "Length"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.handler), "Handler"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.next), "Next"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_power[5] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_power), NULL},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.system_level),
+	 "System Level"},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.resource_order),
+	 "Resource Order"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.system_notify),
+	 "System Notify"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.device_notify),
+	 "Device Notify"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_processor[7] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_processor), NULL},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(processor.length), "Length"},
+	{ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.system_notify),
+	 "System Notify"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.device_notify),
+	 "Device Notify"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.handler), "Handler"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_thermal[4] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_thermal), NULL},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.system_notify),
+	 "System Notify"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.device_notify),
+	 "Device Notify"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.handler), "Handler"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer_field), NULL},
+	{ACPI_EXD_FIELD, 0, NULL},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer_field.buffer_obj),
+	 "Buffer Object"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_region_field[3] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL},
+	{ACPI_EXD_FIELD, 0, NULL},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL},
+	{ACPI_EXD_FIELD, 0, NULL},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(bank_field.value), "Value"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.region_obj),
+	 "Region Object"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.bank_obj), "Bank Object"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_index_field[5] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL},
+	{ACPI_EXD_FIELD, 0, NULL},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(index_field.value), "Value"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.index_obj),
+	 "Index Object"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_reference[7] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.offset), "Offset"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"},
+	{ACPI_EXD_REFERENCE, 0, NULL}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_address_handler[6] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_address_handler),
+	 NULL},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(address_space.space_id), "Space Id"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.next), "Next"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.region_list),
+	 "Region List"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.node), "Node"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_notify[3] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"}
+};
+
+/* Miscellaneous tables */
+
+static struct acpi_exdump_info acpi_ex_dump_common[4] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_common), NULL},
+	{ACPI_EXD_TYPE, 0, NULL},
+	{ACPI_EXD_UINT16, ACPI_EXD_OFFSET(common.reference_count),
+	 "Reference Count"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common.flags), "Flags"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_field_common[7] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_field_common), NULL},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.field_flags),
+	 "Field Flags"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.access_byte_width),
+	 "Access Byte Width"},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.bit_length),
+	 "Bit Length"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.start_field_bit_offset),
+	 "Field Bit Offset"},
+	{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.base_byte_offset),
+	 "Base Byte Offset"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_node[6] = {
+	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL},
+	{ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"},
+	{ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"},
+	{ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET(reference_count),
+	 "Reference Count"},
+	{ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"},
+	{ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"}
+};
+
+/* Dispatch table, indexed by object type */
+
+static struct acpi_exdump_info *acpi_ex_dump_info[] = {
+	NULL,
+	acpi_ex_dump_integer,
+	acpi_ex_dump_string,
+	acpi_ex_dump_buffer,
+	acpi_ex_dump_package,
+	NULL,
+	acpi_ex_dump_device,
+	acpi_ex_dump_event,
+	acpi_ex_dump_method,
+	acpi_ex_dump_mutex,
+	acpi_ex_dump_region,
+	acpi_ex_dump_power,
+	acpi_ex_dump_processor,
+	acpi_ex_dump_thermal,
+	acpi_ex_dump_buffer_field,
+	NULL,
+	NULL,
+	acpi_ex_dump_region_field,
+	acpi_ex_dump_bank_field,
+	acpi_ex_dump_index_field,
+	acpi_ex_dump_reference,
+	NULL,
+	NULL,
+	acpi_ex_dump_notify,
+	acpi_ex_dump_address_handler,
+	NULL,
+	NULL,
+	NULL
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_dump_object
+ *
+ * PARAMETERS:  obj_desc            - Descriptor to dump
+ *              Info                - Info table corresponding to this object
+ *                                    type
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Walk the info table for this object
+ *
+ ******************************************************************************/
+
+static void
+acpi_ex_dump_object(union acpi_operand_object *obj_desc,
+		    struct acpi_exdump_info *info)
+{
+	u8 *target;
+	char *name;
+	u8 count;
+
+	if (!info) {
+		acpi_os_printf
+		    ("ex_dump_object: Display not implemented for object type %s\n",
+		     acpi_ut_get_object_type_name(obj_desc));
+		return;
+	}
+
+	/* First table entry must contain the table length (# of table entries) */
+
+	count = info->offset;
+
+	while (count) {
+		target = ACPI_ADD_PTR(u8, obj_desc, info->offset);
+		name = info->name;
+
+		switch (info->opcode) {
+		case ACPI_EXD_INIT:
+			break;
+
+		case ACPI_EXD_TYPE:
+			acpi_ex_out_string("Type",
+					   acpi_ut_get_object_type_name
+					   (obj_desc));
+			break;
+
+		case ACPI_EXD_UINT8:
+
+			acpi_os_printf("%20s : %2.2X\n", name, *target);
+			break;
+
+		case ACPI_EXD_UINT16:
+
+			acpi_os_printf("%20s : %4.4X\n", name,
+				       ACPI_GET16(target));
+			break;
+
+		case ACPI_EXD_UINT32:
+
+			acpi_os_printf("%20s : %8.8X\n", name,
+				       ACPI_GET32(target));
+			break;
+
+		case ACPI_EXD_UINT64:
+
+			acpi_os_printf("%20s : %8.8X%8.8X\n", "Value",
+				       ACPI_FORMAT_UINT64(ACPI_GET64(target)));
+			break;
+
+		case ACPI_EXD_POINTER:
+
+			acpi_ex_out_pointer(name,
+					    *ACPI_CAST_PTR(void *, target));
+			break;
+
+		case ACPI_EXD_ADDRESS:
+
+			acpi_ex_out_address(name,
+					    *ACPI_CAST_PTR
+					    (acpi_physical_address, target));
+			break;
+
+		case ACPI_EXD_STRING:
+
+			acpi_ut_print_string(obj_desc->string.pointer,
+					     ACPI_UINT8_MAX);
+			acpi_os_printf("\n");
+			break;
+
+		case ACPI_EXD_BUFFER:
+
+			ACPI_DUMP_BUFFER(obj_desc->buffer.pointer,
+					 obj_desc->buffer.length);
+			break;
+
+		case ACPI_EXD_PACKAGE:
+
+			/* Dump the package contents */
+
+			acpi_os_printf("\nPackage Contents:\n");
+			acpi_ex_dump_package_obj(obj_desc, 0, 0);
+			break;
+
+		case ACPI_EXD_FIELD:
+
+			acpi_ex_dump_object(obj_desc,
+					    acpi_ex_dump_field_common);
+			break;
+
+		case ACPI_EXD_REFERENCE:
+
+			acpi_ex_out_string("Opcode",
+					   (acpi_ps_get_opcode_info
+					    (obj_desc->reference.opcode))->
+					   name);
+			acpi_ex_dump_reference_obj(obj_desc);
+			break;
+
+		default:
+			acpi_os_printf("**** Invalid table opcode [%X] ****\n",
+				       info->opcode);
+			return;
+		}
+
+		info++;
+		count--;
+	}
+}
 
 /*******************************************************************************
  *
@@ -214,7 +580,7 @@
 
 	case ACPI_TYPE_BUFFER:
 
-		acpi_os_printf("Buffer len %X @ %p \n",
+		acpi_os_printf("Buffer len %X @ %p\n",
 			       obj_desc->buffer.length,
 			       obj_desc->buffer.pointer);
 
@@ -320,17 +686,17 @@
 
 	case ACPI_TYPE_BUFFER_FIELD:
 
-		acpi_os_printf("buffer_field: %X bits at byte %X bit %X of \n",
+		acpi_os_printf("buffer_field: %X bits at byte %X bit %X of\n",
 			       obj_desc->buffer_field.bit_length,
 			       obj_desc->buffer_field.base_byte_offset,
 			       obj_desc->buffer_field.start_field_bit_offset);
 
 		if (!obj_desc->buffer_field.buffer_obj) {
-			ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL* \n"));
+			ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL*\n"));
 		} else
 		    if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj)
 			!= ACPI_TYPE_BUFFER) {
-			acpi_os_printf("*not a Buffer* \n");
+			acpi_os_printf("*not a Buffer*\n");
 		} else {
 			acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj,
 					     depth + 1);
@@ -441,7 +807,6 @@
 	return;
 }
 
-#ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ex_out* functions
@@ -465,11 +830,6 @@
 	acpi_os_printf("%20s : %p\n", title, value);
 }
 
-static void acpi_ex_out_integer(char *title, u32 value)
-{
-	acpi_os_printf("%20s : %.2X\n", title, value);
-}
-
 static void acpi_ex_out_address(char *title, acpi_physical_address value)
 {
 
@@ -482,16 +842,16 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ex_dump_node
+ * FUNCTION:    acpi_ex_dump_namespace_node
  *
- * PARAMETERS:  *Node               - Descriptor to dump
+ * PARAMETERS:  Node                - Descriptor to dump
  *              Flags               - Force display if TRUE
  *
  * DESCRIPTION: Dumps the members of the given.Node
  *
  ******************************************************************************/
 
-void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags)
+void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags)
 {
 
 	ACPI_FUNCTION_ENTRY();
@@ -506,19 +866,17 @@
 
 	acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node));
 	acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type));
-	acpi_ex_out_integer("Flags", node->flags);
-	acpi_ex_out_integer("Owner Id", node->owner_id);
-	acpi_ex_out_integer("Reference Count", node->reference_count);
 	acpi_ex_out_pointer("Attached Object",
 			    acpi_ns_get_attached_object(node));
-	acpi_ex_out_pointer("child_list", node->child);
-	acpi_ex_out_pointer("next_peer", node->peer);
 	acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node));
+
+	acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node),
+			    acpi_ex_dump_node);
 }
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ex_dump_reference
+ * FUNCTION:    acpi_ex_dump_reference_obj
  *
  * PARAMETERS:  Object              - Descriptor to dump
  *
@@ -526,14 +884,16 @@
  *
  ******************************************************************************/
 
-static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc)
+static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
 {
 	struct acpi_buffer ret_buf;
 	acpi_status status;
 
+	ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+
 	if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) {
 		acpi_os_printf("Named Object %p ", obj_desc->reference.node);
-		ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+
 		status =
 		    acpi_ns_handle_to_pathname(obj_desc->reference.node,
 					       &ret_buf);
@@ -551,9 +911,9 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ex_dump_package
+ * FUNCTION:    acpi_ex_dump_package_obj
  *
- * PARAMETERS:  Object              - Descriptor to dump
+ * PARAMETERS:  obj_desc            - Descriptor to dump
  *              Level               - Indentation Level
  *              Index               - Package index for this object
  *
@@ -562,7 +922,8 @@
  ******************************************************************************/
 
 static void
-acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index)
+acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
+			 u32 level, u32 index)
 {
 	u32 i;
 
@@ -608,7 +969,8 @@
 		acpi_os_printf("[Buffer] Length %.2X = ",
 			       obj_desc->buffer.length);
 		if (obj_desc->buffer.length) {
-			acpi_ut_dump_buffer((u8 *) obj_desc->buffer.pointer,
+			acpi_ut_dump_buffer(ACPI_CAST_PTR
+					    (u8, obj_desc->buffer.pointer),
 					    obj_desc->buffer.length,
 					    DB_DWORD_DISPLAY, _COMPONENT);
 		} else {
@@ -618,19 +980,19 @@
 
 	case ACPI_TYPE_PACKAGE:
 
-		acpi_os_printf("[Package] Contains %d Elements: \n",
+		acpi_os_printf("[Package] Contains %d Elements:\n",
 			       obj_desc->package.count);
 
 		for (i = 0; i < obj_desc->package.count; i++) {
-			acpi_ex_dump_package(obj_desc->package.elements[i],
-					     level + 1, i);
+			acpi_ex_dump_package_obj(obj_desc->package.elements[i],
+						 level + 1, i);
 		}
 		break;
 
 	case ACPI_TYPE_LOCAL_REFERENCE:
 
 		acpi_os_printf("[Object Reference] ");
-		acpi_ex_dump_reference(obj_desc);
+		acpi_ex_dump_reference_obj(obj_desc);
 		break;
 
 	default:
@@ -645,7 +1007,7 @@
  *
  * FUNCTION:    acpi_ex_dump_object_descriptor
  *
- * PARAMETERS:  Object              - Descriptor to dump
+ * PARAMETERS:  obj_desc            - Descriptor to dump
  *              Flags               - Force display if TRUE
  *
  * DESCRIPTION: Dumps the members of the object descriptor given.
@@ -670,11 +1032,13 @@
 	}
 
 	if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) {
-		acpi_ex_dump_node((struct acpi_namespace_node *)obj_desc,
-				  flags);
+		acpi_ex_dump_namespace_node((struct acpi_namespace_node *)
+					    obj_desc, flags);
+
 		acpi_os_printf("\nAttached Object (%p):\n",
 			       ((struct acpi_namespace_node *)obj_desc)->
 			       object);
+
 		acpi_ex_dump_object_descriptor(((struct acpi_namespace_node *)
 						obj_desc)->object, flags);
 		return_VOID;
@@ -687,233 +1051,18 @@
 		return_VOID;
 	}
 
-	/* Common Fields */
-
-	acpi_ex_out_string("Type", acpi_ut_get_object_type_name(obj_desc));
-	acpi_ex_out_integer("Reference Count",
-			    obj_desc->common.reference_count);
-	acpi_ex_out_integer("Flags", obj_desc->common.flags);
-
-	/* Object-specific Fields */
-
-	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
-	case ACPI_TYPE_INTEGER:
-
-		acpi_os_printf("%20s : %8.8X%8.8X\n", "Value",
-			       ACPI_FORMAT_UINT64(obj_desc->integer.value));
-		break;
-
-	case ACPI_TYPE_STRING:
-
-		acpi_ex_out_integer("Length", obj_desc->string.length);
-
-		acpi_os_printf("%20s : %p ", "Pointer",
-			       obj_desc->string.pointer);
-		acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
-		acpi_os_printf("\n");
-		break;
-
-	case ACPI_TYPE_BUFFER:
-
-		acpi_ex_out_integer("Length", obj_desc->buffer.length);
-		acpi_ex_out_pointer("Pointer", obj_desc->buffer.pointer);
-		ACPI_DUMP_BUFFER(obj_desc->buffer.pointer,
-				 obj_desc->buffer.length);
-		break;
-
-	case ACPI_TYPE_PACKAGE:
-
-		acpi_ex_out_integer("Flags", obj_desc->package.flags);
-		acpi_ex_out_integer("Elements", obj_desc->package.count);
-		acpi_ex_out_pointer("Element List", obj_desc->package.elements);
-
-		/* Dump the package contents */
-
-		acpi_os_printf("\nPackage Contents:\n");
-		acpi_ex_dump_package(obj_desc, 0, 0);
-		break;
-
-	case ACPI_TYPE_DEVICE:
-
-		acpi_ex_out_pointer("Handler", obj_desc->device.handler);
-		acpi_ex_out_pointer("system_notify",
-				    obj_desc->device.system_notify);
-		acpi_ex_out_pointer("device_notify",
-				    obj_desc->device.device_notify);
-		break;
-
-	case ACPI_TYPE_EVENT:
-
-		acpi_ex_out_pointer("Semaphore", obj_desc->event.semaphore);
-		break;
-
-	case ACPI_TYPE_METHOD:
-
-		acpi_ex_out_integer("param_count",
-				    obj_desc->method.param_count);
-		acpi_ex_out_integer("Concurrency",
-				    obj_desc->method.concurrency);
-		acpi_ex_out_pointer("Semaphore", obj_desc->method.semaphore);
-		acpi_ex_out_integer("owner_id", obj_desc->method.owner_id);
-		acpi_ex_out_integer("aml_length", obj_desc->method.aml_length);
-		acpi_ex_out_pointer("aml_start", obj_desc->method.aml_start);
-		break;
-
-	case ACPI_TYPE_MUTEX:
-
-		acpi_ex_out_integer("sync_level", obj_desc->mutex.sync_level);
-		acpi_ex_out_pointer("owner_thread",
-				    obj_desc->mutex.owner_thread);
-		acpi_ex_out_integer("acquire_depth",
-				    obj_desc->mutex.acquisition_depth);
-		acpi_ex_out_pointer("Semaphore", obj_desc->mutex.semaphore);
-		break;
-
-	case ACPI_TYPE_REGION:
-
-		acpi_ex_out_integer("space_id", obj_desc->region.space_id);
-		acpi_ex_out_integer("Flags", obj_desc->region.flags);
-		acpi_ex_out_address("Address", obj_desc->region.address);
-		acpi_ex_out_integer("Length", obj_desc->region.length);
-		acpi_ex_out_pointer("Handler", obj_desc->region.handler);
-		acpi_ex_out_pointer("Next", obj_desc->region.next);
-		break;
-
-	case ACPI_TYPE_POWER:
-
-		acpi_ex_out_integer("system_level",
-				    obj_desc->power_resource.system_level);
-		acpi_ex_out_integer("resource_order",
-				    obj_desc->power_resource.resource_order);
-		acpi_ex_out_pointer("system_notify",
-				    obj_desc->power_resource.system_notify);
-		acpi_ex_out_pointer("device_notify",
-				    obj_desc->power_resource.device_notify);
-		break;
-
-	case ACPI_TYPE_PROCESSOR:
-
-		acpi_ex_out_integer("Processor ID",
-				    obj_desc->processor.proc_id);
-		acpi_ex_out_integer("Length", obj_desc->processor.length);
-		acpi_ex_out_address("Address",
-				    (acpi_physical_address) obj_desc->processor.
-				    address);
-		acpi_ex_out_pointer("system_notify",
-				    obj_desc->processor.system_notify);
-		acpi_ex_out_pointer("device_notify",
-				    obj_desc->processor.device_notify);
-		acpi_ex_out_pointer("Handler", obj_desc->processor.handler);
-		break;
-
-	case ACPI_TYPE_THERMAL:
-
-		acpi_ex_out_pointer("system_notify",
-				    obj_desc->thermal_zone.system_notify);
-		acpi_ex_out_pointer("device_notify",
-				    obj_desc->thermal_zone.device_notify);
-		acpi_ex_out_pointer("Handler", obj_desc->thermal_zone.handler);
-		break;
-
-	case ACPI_TYPE_BUFFER_FIELD:
-	case ACPI_TYPE_LOCAL_REGION_FIELD:
-	case ACPI_TYPE_LOCAL_BANK_FIELD:
-	case ACPI_TYPE_LOCAL_INDEX_FIELD:
-
-		acpi_ex_out_integer("field_flags",
-				    obj_desc->common_field.field_flags);
-		acpi_ex_out_integer("access_byte_width",
-				    obj_desc->common_field.access_byte_width);
-		acpi_ex_out_integer("bit_length",
-				    obj_desc->common_field.bit_length);
-		acpi_ex_out_integer("fld_bit_offset",
-				    obj_desc->common_field.
-				    start_field_bit_offset);
-		acpi_ex_out_integer("base_byte_offset",
-				    obj_desc->common_field.base_byte_offset);
-		acpi_ex_out_pointer("parent_node", obj_desc->common_field.node);
-
-		switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
-		case ACPI_TYPE_BUFFER_FIELD:
-			acpi_ex_out_pointer("buffer_obj",
-					    obj_desc->buffer_field.buffer_obj);
-			break;
-
-		case ACPI_TYPE_LOCAL_REGION_FIELD:
-			acpi_ex_out_pointer("region_obj",
-					    obj_desc->field.region_obj);
-			break;
-
-		case ACPI_TYPE_LOCAL_BANK_FIELD:
-			acpi_ex_out_integer("Value",
-					    obj_desc->bank_field.value);
-			acpi_ex_out_pointer("region_obj",
-					    obj_desc->bank_field.region_obj);
-			acpi_ex_out_pointer("bank_obj",
-					    obj_desc->bank_field.bank_obj);
-			break;
-
-		case ACPI_TYPE_LOCAL_INDEX_FIELD:
-			acpi_ex_out_integer("Value",
-					    obj_desc->index_field.value);
-			acpi_ex_out_pointer("Index",
-					    obj_desc->index_field.index_obj);
-			acpi_ex_out_pointer("Data",
-					    obj_desc->index_field.data_obj);
-			break;
-
-		default:
-			/* All object types covered above */
-			break;
-		}
-		break;
-
-	case ACPI_TYPE_LOCAL_REFERENCE:
-
-		acpi_ex_out_integer("target_type",
-				    obj_desc->reference.target_type);
-		acpi_ex_out_string("Opcode",
-				   (acpi_ps_get_opcode_info
-				    (obj_desc->reference.opcode))->name);
-		acpi_ex_out_integer("Offset", obj_desc->reference.offset);
-		acpi_ex_out_pointer("obj_desc", obj_desc->reference.object);
-		acpi_ex_out_pointer("Node", obj_desc->reference.node);
-		acpi_ex_out_pointer("Where", obj_desc->reference.where);
-
-		acpi_ex_dump_reference(obj_desc);
-		break;
-
-	case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
-
-		acpi_ex_out_integer("space_id",
-				    obj_desc->address_space.space_id);
-		acpi_ex_out_pointer("Next", obj_desc->address_space.next);
-		acpi_ex_out_pointer("region_list",
-				    obj_desc->address_space.region_list);
-		acpi_ex_out_pointer("Node", obj_desc->address_space.node);
-		acpi_ex_out_pointer("Context", obj_desc->address_space.context);
-		break;
-
-	case ACPI_TYPE_LOCAL_NOTIFY:
-
-		acpi_ex_out_pointer("Node", obj_desc->notify.node);
-		acpi_ex_out_pointer("Context", obj_desc->notify.context);
-		break;
-
-	case ACPI_TYPE_LOCAL_ALIAS:
-	case ACPI_TYPE_LOCAL_METHOD_ALIAS:
-	case ACPI_TYPE_LOCAL_EXTRA:
-	case ACPI_TYPE_LOCAL_DATA:
-	default:
-
-		acpi_os_printf
-		    ("ex_dump_object_descriptor: Display not implemented for object type %s\n",
-		     acpi_ut_get_object_type_name(obj_desc));
-		break;
+	if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) {
+		return_VOID;
 	}
 
+	/* Common Fields */
+
+	acpi_ex_dump_object(obj_desc, acpi_ex_dump_common);
+
+	/* Object-specific fields */
+
+	acpi_ex_dump_object(obj_desc, acpi_ex_dump_info[obj_desc->common.type]);
 	return_VOID;
 }
 
-#endif				/*  ACPI_FUTURE_USAGE  */
 #endif
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
index ab1ba39..e259201 100644
--- a/drivers/acpi/executer/exfield.c
+++ b/drivers/acpi/executer/exfield.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -249,13 +249,18 @@
 		 * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
 		 */
 		if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) {
-			ACPI_REPORT_ERROR(("SMBus write requires Buffer, found type %s\n", acpi_ut_get_object_type_name(source_desc)));
+			ACPI_ERROR((AE_INFO,
+				    "SMBus write requires Buffer, found type %s",
+				    acpi_ut_get_object_type_name(source_desc)));
 
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 
 		if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
-			ACPI_REPORT_ERROR(("SMBus write requires Buffer of length %X, found length %X\n", ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length));
+			ACPI_ERROR((AE_INFO,
+				    "SMBus write requires Buffer of length %X, found length %X",
+				    ACPI_SMBUS_BUFFER_SIZE,
+				    source_desc->buffer.length));
 
 			return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
 		}
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index ba6e088..bd1af35 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -94,10 +94,9 @@
 	/* We must have a valid region */
 
 	if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Needed Region, found type %X (%s)\n",
-				  ACPI_GET_OBJECT_TYPE(rgn_desc),
-				  acpi_ut_get_object_type_name(rgn_desc)));
+		ACPI_ERROR((AE_INFO, "Needed Region, found type %X (%s)",
+			    ACPI_GET_OBJECT_TYPE(rgn_desc),
+			    acpi_ut_get_object_type_name(rgn_desc)));
 
 		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 	}
@@ -162,31 +161,28 @@
 			 * than the region itself.  For example, a region of length one
 			 * byte, and a field with Dword access specified.
 			 */
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
-					  acpi_ut_get_node_name(obj_desc->
-								common_field.
-								node),
-					  obj_desc->common_field.
-					  access_byte_width,
-					  acpi_ut_get_node_name(rgn_desc->
-								region.node),
-					  rgn_desc->region.length));
+			ACPI_ERROR((AE_INFO,
+				    "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)",
+				    acpi_ut_get_node_name(obj_desc->
+							  common_field.node),
+				    obj_desc->common_field.access_byte_width,
+				    acpi_ut_get_node_name(rgn_desc->region.
+							  node),
+				    rgn_desc->region.length));
 		}
 
 		/*
 		 * Offset rounded up to next multiple of field width
 		 * exceeds region length, indicate an error
 		 */
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
-				  acpi_ut_get_node_name(obj_desc->common_field.
-							node),
-				  obj_desc->common_field.base_byte_offset,
-				  field_datum_byte_offset,
-				  obj_desc->common_field.access_byte_width,
-				  acpi_ut_get_node_name(rgn_desc->region.node),
-				  rgn_desc->region.length));
+		ACPI_ERROR((AE_INFO,
+			    "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)",
+			    acpi_ut_get_node_name(obj_desc->common_field.node),
+			    obj_desc->common_field.base_byte_offset,
+			    field_datum_byte_offset,
+			    obj_desc->common_field.access_byte_width,
+			    acpi_ut_get_node_name(rgn_desc->region.node),
+			    rgn_desc->region.length));
 
 		return_ACPI_STATUS(AE_AML_REGION_LIMIT);
 	}
@@ -270,18 +266,17 @@
 
 	if (ACPI_FAILURE(status)) {
 		if (status == AE_NOT_IMPLEMENTED) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Region %s(%X) not implemented\n",
-					  acpi_ut_get_region_name(rgn_desc->
-								  region.
-								  space_id),
-					  rgn_desc->region.space_id));
+			ACPI_ERROR((AE_INFO,
+				    "Region %s(%X) not implemented",
+				    acpi_ut_get_region_name(rgn_desc->region.
+							    space_id),
+				    rgn_desc->region.space_id));
 		} else if (status == AE_NOT_EXIST) {
-			ACPI_REPORT_ERROR(("Region %s(%X) has no handler\n",
-					   acpi_ut_get_region_name(rgn_desc->
-								   region.
-								   space_id),
-					   rgn_desc->region.space_id));
+			ACPI_ERROR((AE_INFO,
+				    "Region %s(%X) has no handler",
+				    acpi_ut_get_region_name(rgn_desc->region.
+							    space_id),
+				    rgn_desc->region.space_id));
 		}
 	}
 
@@ -514,8 +509,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("Wrong object type in field I/O %X\n",
-				   ACPI_GET_OBJECT_TYPE(obj_desc)));
+		ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %X",
+			    ACPI_GET_OBJECT_TYPE(obj_desc)));
 		status = AE_AML_INTERNAL;
 		break;
 	}
@@ -618,11 +613,11 @@
 
 		default:
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "write_with_update_rule: Unknown update_rule setting: %X\n",
-					  (obj_desc->common_field.
-					   field_flags &
-					   AML_FIELD_UPDATE_RULE_MASK)));
+			ACPI_ERROR((AE_INFO,
+				    "Unknown update_rule value: %X",
+				    (obj_desc->common_field.
+				     field_flags &
+				     AML_FIELD_UPDATE_RULE_MASK)));
 			return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
 		}
 	}
@@ -677,10 +672,9 @@
 
 	if (buffer_length <
 	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Field size %X (bits) is too large for buffer (%X)\n",
-				  obj_desc->common_field.bit_length,
-				  buffer_length));
+		ACPI_ERROR((AE_INFO,
+			    "Field size %X (bits) is too large for buffer (%X)",
+			    obj_desc->common_field.bit_length, buffer_length));
 
 		return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
 	}
@@ -792,10 +786,9 @@
 
 	if (buffer_length <
 	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Field size %X (bits) is too large for buffer (%X)\n",
-				  obj_desc->common_field.bit_length,
-				  buffer_length));
+		ACPI_ERROR((AE_INFO,
+			    "Field size %X (bits) is too large for buffer (%X)",
+			    obj_desc->common_field.bit_length, buffer_length));
 
 		return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
 	}
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index a3f4d72..48c18d2 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
 #include <acpi/acpi.h>
 #include <acpi/acinterp.h>
 #include <acpi/amlcode.h>
+#include <acpi/amlresrc.h>
 
 #define _COMPONENT          ACPI_EXECUTER
 ACPI_MODULE_NAME("exmisc")
@@ -97,7 +98,8 @@
 
 		default:
 
-			ACPI_REPORT_ERROR(("Unknown Reference opcode in get_reference %X\n", obj_desc->reference.opcode));
+			ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X",
+				    obj_desc->reference.opcode));
 			return_ACPI_STATUS(AE_AML_INTERNAL);
 		}
 		break;
@@ -112,7 +114,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("Invalid descriptor type in get_reference: %X\n", ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
+		ACPI_ERROR((AE_INFO, "Invalid descriptor type %X",
+			    ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
 		return_ACPI_STATUS(AE_TYPE);
 	}
 
@@ -157,48 +160,65 @@
 			union acpi_operand_object **actual_return_desc,
 			struct acpi_walk_state *walk_state)
 {
+	acpi_status status;
 	union acpi_operand_object *return_desc;
 	u8 *new_buf;
-	u8 *end_tag1;
-	u8 *end_tag2;
+	u8 *end_tag;
+	acpi_size length0;
 	acpi_size length1;
-	acpi_size length2;
+	acpi_size new_length;
 
 	ACPI_FUNCTION_TRACE("ex_concat_template");
 
-	/* Find the end_tags in each resource template */
+	/*
+	 * Find the end_tag descriptor in each resource template.
+	 * Note1: returned pointers point TO the end_tag, not past it.
+	 * Note2: zero-length buffers are allowed; treated like one end_tag
+	 */
 
-	end_tag1 = acpi_ut_get_resource_end_tag(operand0);
-	end_tag2 = acpi_ut_get_resource_end_tag(operand1);
-	if (!end_tag1 || !end_tag2) {
-		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+	/* Get the length of the first resource template */
+
+	status = acpi_ut_get_resource_end_tag(operand0, &end_tag);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
 	}
 
-	/* Compute the length of each part */
+	length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer);
 
-	length1 = ACPI_PTR_DIFF(end_tag1, operand0->buffer.pointer);
-	length2 = ACPI_PTR_DIFF(end_tag2, operand1->buffer.pointer) + 2;	/* Size of END_TAG */
+	/* Get the length of the second resource template */
 
-	/* Create a new buffer object for the result */
+	status = acpi_ut_get_resource_end_tag(operand1, &end_tag);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
 
-	return_desc = acpi_ut_create_buffer_object(length1 + length2);
+	length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer);
+
+	/* Combine both lengths, minimum size will be 2 for end_tag */
+
+	new_length = length0 + length1 + sizeof(struct aml_resource_end_tag);
+
+	/* Create a new buffer object for the result (with one end_tag) */
+
+	return_desc = acpi_ut_create_buffer_object(new_length);
 	if (!return_desc) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
-	/* Copy the templates to the new descriptor */
-
+	/*
+	 * Copy the templates to the new buffer, 0 first, then 1 follows. One
+	 * end_tag descriptor is copied from Operand1.
+	 */
 	new_buf = return_desc->buffer.pointer;
-	ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length1);
-	ACPI_MEMCPY(new_buf + length1, operand1->buffer.pointer, length2);
+	ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length0);
+	ACPI_MEMCPY(new_buf + length0, operand1->buffer.pointer, length1);
 
-	/* Compute the new checksum */
+	/* Insert end_tag and set the checksum to zero, means "ignore checksum" */
 
-	new_buf[return_desc->buffer.length - 1] =
-	    acpi_ut_generate_checksum(return_desc->buffer.pointer,
-				      (return_desc->buffer.length - 1));
+	new_buf[new_length - 1] = 0;
+	new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
 
-	/* Return the completed template descriptor */
+	/* Return the completed resource template */
 
 	*actual_return_desc = return_desc;
 	return_ACPI_STATUS(AE_OK);
@@ -229,7 +249,6 @@
 	union acpi_operand_object *return_desc;
 	char *new_buf;
 	acpi_status status;
-	acpi_size new_length;
 
 	ACPI_FUNCTION_TRACE("ex_do_concatenate");
 
@@ -256,8 +275,8 @@
 		break;
 
 	default:
-		ACPI_REPORT_ERROR(("Concat - invalid obj type: %X\n",
-				   ACPI_GET_OBJECT_TYPE(operand0)));
+		ACPI_ERROR((AE_INFO, "Invalid object type: %X",
+			    ACPI_GET_OBJECT_TYPE(operand0)));
 		status = AE_AML_INTERNAL;
 	}
 
@@ -296,8 +315,7 @@
 
 		/* Copy the first integer, LSB first */
 
-		ACPI_MEMCPY(new_buf,
-			    &operand0->integer.value,
+		ACPI_MEMCPY(new_buf, &operand0->integer.value,
 			    acpi_gbl_integer_byte_width);
 
 		/* Copy the second integer (LSB first) after the first */
@@ -311,14 +329,11 @@
 
 		/* Result of two Strings is a String */
 
-		new_length = (acpi_size) operand0->string.length +
-		    (acpi_size) local_operand1->string.length;
-		if (new_length > ACPI_MAX_STRING_CONVERSION) {
-			status = AE_AML_STRING_LIMIT;
-			goto cleanup;
-		}
-
-		return_desc = acpi_ut_create_string_object(new_length);
+		return_desc = acpi_ut_create_string_object((acpi_size)
+							   (operand0->string.
+							    length +
+							    local_operand1->
+							    string.length));
 		if (!return_desc) {
 			status = AE_NO_MEMORY;
 			goto cleanup;
@@ -338,11 +353,10 @@
 		/* Result of two Buffers is a Buffer */
 
 		return_desc = acpi_ut_create_buffer_object((acpi_size)
-							   operand0->buffer.
-							   length +
-							   (acpi_size)
-							   local_operand1->
-							   buffer.length);
+							   (operand0->buffer.
+							    length +
+							    local_operand1->
+							    buffer.length));
 		if (!return_desc) {
 			status = AE_NO_MEMORY;
 			goto cleanup;
@@ -352,8 +366,8 @@
 
 		/* Concatenate the buffers */
 
-		ACPI_MEMCPY(new_buf,
-			    operand0->buffer.pointer, operand0->buffer.length);
+		ACPI_MEMCPY(new_buf, operand0->buffer.pointer,
+			    operand0->buffer.length);
 		ACPI_MEMCPY(new_buf + operand0->buffer.length,
 			    local_operand1->buffer.pointer,
 			    local_operand1->buffer.length);
@@ -363,8 +377,8 @@
 
 		/* Invalid object type, should not happen here */
 
-		ACPI_REPORT_ERROR(("Concatenate - Invalid object type: %X\n",
-				   ACPI_GET_OBJECT_TYPE(operand0)));
+		ACPI_ERROR((AE_INFO, "Invalid object type: %X",
+			    ACPI_GET_OBJECT_TYPE(operand0)));
 		status = AE_AML_INTERNAL;
 		goto cleanup;
 	}
@@ -625,9 +639,8 @@
 
 		/* Lexicographic compare: compare the data bytes */
 
-		compare = ACPI_MEMCMP((const char *)operand0->buffer.pointer,
-				      (const char *)local_operand1->buffer.
-				      pointer,
+		compare = ACPI_MEMCMP(operand0->buffer.pointer,
+				      local_operand1->buffer.pointer,
 				      (length0 > length1) ? length1 : length0);
 
 		switch (opcode) {
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index ab47f6d..f843b22 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -153,7 +153,9 @@
 	/* Sanity check -- we must have a valid thread ID */
 
 	if (!walk_state->thread) {
-		ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+		ACPI_ERROR((AE_INFO,
+			    "Cannot acquire Mutex [%4.4s], null thread info",
+			    acpi_ut_get_node_name(obj_desc->mutex.node)));
 		return_ACPI_STATUS(AE_AML_INTERNAL);
 	}
 
@@ -162,7 +164,9 @@
 	 * mutex.  This mechanism provides some deadlock prevention
 	 */
 	if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
-		ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+		ACPI_ERROR((AE_INFO,
+			    "Cannot acquire Mutex [%4.4s], incorrect sync_level",
+			    acpi_ut_get_node_name(obj_desc->mutex.node)));
 		return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
 	}
 
@@ -237,14 +241,18 @@
 	/* The mutex must have been previously acquired in order to release it */
 
 	if (!obj_desc->mutex.owner_thread) {
-		ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], not acquired\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+		ACPI_ERROR((AE_INFO,
+			    "Cannot release Mutex [%4.4s], not acquired",
+			    acpi_ut_get_node_name(obj_desc->mutex.node)));
 		return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
 	}
 
 	/* Sanity check -- we must have a valid thread ID */
 
 	if (!walk_state->thread) {
-		ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+		ACPI_ERROR((AE_INFO,
+			    "Cannot release Mutex [%4.4s], null thread info",
+			    acpi_ut_get_node_name(obj_desc->mutex.node)));
 		return_ACPI_STATUS(AE_AML_INTERNAL);
 	}
 
@@ -255,7 +263,11 @@
 	if ((obj_desc->mutex.owner_thread->thread_id !=
 	     walk_state->thread->thread_id)
 	    && (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
-		ACPI_REPORT_ERROR(("Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", walk_state->thread->thread_id, acpi_ut_get_node_name(obj_desc->mutex.node), obj_desc->mutex.owner_thread->thread_id));
+		ACPI_ERROR((AE_INFO,
+			    "Thread %X cannot release Mutex [%4.4s] acquired by thread %X",
+			    walk_state->thread->thread_id,
+			    acpi_ut_get_node_name(obj_desc->mutex.node),
+			    obj_desc->mutex.owner_thread->thread_id));
 		return_ACPI_STATUS(AE_AML_NOT_OWNER);
 	}
 
@@ -264,7 +276,9 @@
 	 * equal to the current sync level
 	 */
 	if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
-		ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+		ACPI_ERROR((AE_INFO,
+			    "Cannot release Mutex [%4.4s], incorrect sync_level",
+			    acpi_ut_get_node_name(obj_desc->mutex.node)));
 		return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
 	}
 
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
index 239d847..054fe5e 100644
--- a/drivers/acpi/executer/exnames.c
+++ b/drivers/acpi/executer/exnames.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -99,7 +99,8 @@
 	 */
 	name_string = ACPI_MEM_ALLOCATE(size_needed);
 	if (!name_string) {
-		ACPI_REPORT_ERROR(("ex_allocate_name_string: Could not allocate size %d\n", size_needed));
+		ACPI_ERROR((AE_INFO,
+			    "Could not allocate size %d", size_needed));
 		return_PTR(NULL);
 	}
 
@@ -167,8 +168,7 @@
 	char_buf[0] = *aml_address;
 
 	if ('0' <= char_buf[0] && char_buf[0] <= '9') {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "leading digit: %c\n",
-				  char_buf[0]));
+		ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0]));
 		return_ACPI_STATUS(AE_CTRL_PENDING);
 	}
 
@@ -191,10 +191,10 @@
 		if (name_string) {
 			ACPI_STRCAT(name_string, char_buf);
 			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
-					  "Appended to - %s \n", name_string));
+					  "Appended to - %s\n", name_string));
 		} else {
 			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
-					  "No Name string - %s \n", char_buf));
+					  "No Name string - %s\n", char_buf));
 		}
 	} else if (index == 0) {
 		/*
@@ -211,12 +211,12 @@
 		 * the required 4
 		 */
 		status = AE_AML_BAD_NAME;
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Bad character %02x in name, at %p\n",
-				  *aml_address, aml_address));
+		ACPI_ERROR((AE_INFO,
+			    "Bad character %02x in name, at %p",
+			    *aml_address, aml_address));
 	}
 
-	*in_aml_address = (u8 *) aml_address;
+	*in_aml_address = ACPI_CAST_PTR(u8, aml_address);
 	return_ACPI_STATUS(status);
 }
 
@@ -412,8 +412,7 @@
 	if (AE_CTRL_PENDING == status && has_prefix) {
 		/* Ran out of segments after processing a prefix */
 
-		ACPI_REPORT_ERROR(("ex_do_name: Malformed Name at %p\n",
-				   name_string));
+		ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
 		status = AE_AML_BAD_NAME;
 	}
 
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index 97e3454..23d0823 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -111,7 +111,8 @@
 
 	default:		/*  Unknown opcode  */
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		break;
 	}
@@ -188,7 +189,8 @@
 
 	default:		/*  Unknown opcode  */
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		break;
 	}
@@ -227,7 +229,8 @@
 
 	default:		/* Unknown opcode */
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
@@ -346,9 +349,9 @@
 				/* Check the range of the digit */
 
 				if (temp32 > 9) {
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "BCD digit too large (not decimal): 0x%X\n",
-							  temp32));
+					ACPI_ERROR((AE_INFO,
+						    "BCD digit too large (not decimal): 0x%X",
+						    temp32));
 
 					status = AE_AML_NUMERIC_OVERFLOW;
 					goto cleanup;
@@ -393,12 +396,10 @@
 			/* Overflow if there is any data left in Digit */
 
 			if (digit > 0) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Integer too large to convert to BCD: %8.8X%8.8X\n",
-						  ACPI_FORMAT_UINT64(operand
-								     [0]->
-								     integer.
-								     value)));
+				ACPI_ERROR((AE_INFO,
+					    "Integer too large to convert to BCD: %8.8X%8.8X",
+					    ACPI_FORMAT_UINT64(operand[0]->
+							       integer.value)));
 				status = AE_AML_NUMERIC_OVERFLOW;
 				goto cleanup;
 			}
@@ -525,15 +526,16 @@
 
 		/* These are two obsolete opcodes */
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "%s is obsolete and not implemented\n",
-				  acpi_ps_get_opcode_name(walk_state->opcode)));
+		ACPI_ERROR((AE_INFO,
+			    "%s is obsolete and not implemented",
+			    acpi_ps_get_opcode_name(walk_state->opcode)));
 		status = AE_SUPPORT;
 		goto cleanup;
 
 	default:		/* Unknown opcode */
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
@@ -639,11 +641,10 @@
 		    acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc,
 					     walk_state);
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "%s: bad operand(s) %s\n",
-					  acpi_ps_get_opcode_name(walk_state->
-								  opcode),
-					  acpi_format_exception(status)));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"While resolving operands for [%s]",
+					acpi_ps_get_opcode_name(walk_state->
+								opcode)));
 
 			goto cleanup;
 		}
@@ -742,9 +743,9 @@
 			break;
 
 		default:
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n",
-					  acpi_ut_get_type_name(type)));
+			ACPI_ERROR((AE_INFO,
+				    "Operand is not Buf/Int/Str/Pkg - found type %s",
+				    acpi_ut_get_type_name(type)));
 			status = AE_AML_OPERAND_TYPE;
 			goto cleanup;
 		}
@@ -941,11 +942,10 @@
 
 				default:
 
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "Unknown Index target_type %X in obj %p\n",
-							  operand[0]->reference.
-							  target_type,
-							  operand[0]));
+					ACPI_ERROR((AE_INFO,
+						    "Unknown Index target_type %X in obj %p",
+						    operand[0]->reference.
+						    target_type, operand[0]));
 					status = AE_AML_OPERAND_TYPE;
 					goto cleanup;
 				}
@@ -971,11 +971,10 @@
 				break;
 
 			default:
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Unknown opcode in ref(%p) - %X\n",
-						  operand[0],
-						  operand[0]->reference.
-						  opcode));
+				ACPI_ERROR((AE_INFO,
+					    "Unknown opcode in ref(%p) - %X",
+					    operand[0],
+					    operand[0]->reference.opcode));
 
 				status = AE_TYPE;
 				goto cleanup;
@@ -985,7 +984,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index 8d70c6b..e263a5d 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -111,9 +111,9 @@
 		/* Are notifies allowed on this object? */
 
 		if (!acpi_ev_is_notify_object(node)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Unexpected notify object type [%s]\n",
-					  acpi_ut_get_type_name(node->type)));
+			ACPI_ERROR((AE_INFO,
+				    "Unexpected notify object type [%s]",
+				    acpi_ut_get_type_name(node->type)));
 
 			status = AE_AML_OPERAND_TYPE;
 			break;
@@ -157,7 +157,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 	}
 
@@ -221,7 +222,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
@@ -344,10 +346,6 @@
 		       (length < operand[1]->integer.value) &&
 		       (operand[0]->buffer.pointer[length])) {
 			length++;
-			if (length > ACPI_MAX_STRING_CONVERSION) {
-				status = AE_AML_STRING_LIMIT;
-				goto cleanup;
-			}
 		}
 
 		/* Allocate a new string object */
@@ -358,8 +356,10 @@
 			goto cleanup;
 		}
 
-		/* Copy the raw buffer data with no transform. NULL terminated already */
-
+		/*
+		 * Copy the raw buffer data with no transform.
+		 * (NULL terminated already)
+		 */
 		ACPI_MEMCPY(return_desc->string.pointer,
 			    operand[0]->buffer.pointer, length);
 		break;
@@ -391,10 +391,10 @@
 			/* Object to be indexed is a Package */
 
 			if (index >= operand[0]->package.count) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Index value (%X%8.8X) beyond package end (%X)\n",
-						  ACPI_FORMAT_UINT64(index),
-						  operand[0]->package.count));
+				ACPI_ERROR((AE_INFO,
+					    "Index value (%X%8.8X) beyond package end (%X)",
+					    ACPI_FORMAT_UINT64(index),
+					    operand[0]->package.count));
 				status = AE_AML_PACKAGE_LIMIT;
 				goto cleanup;
 			}
@@ -407,10 +407,10 @@
 			/* Object to be indexed is a Buffer/String */
 
 			if (index >= operand[0]->buffer.length) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Index value (%X%8.8X) beyond end of buffer (%X)\n",
-						  ACPI_FORMAT_UINT64(index),
-						  operand[0]->buffer.length));
+				ACPI_ERROR((AE_INFO,
+					    "Index value (%X%8.8X) beyond end of buffer (%X)",
+					    ACPI_FORMAT_UINT64(index),
+					    operand[0]->buffer.length));
 				status = AE_AML_BUFFER_LIMIT;
 				goto cleanup;
 			}
@@ -442,7 +442,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		break;
 	}
@@ -546,7 +547,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
index 4833657..6a3a883 100644
--- a/drivers/acpi/executer/exoparg3.c
+++ b/drivers/acpi/executer/exoparg3.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -119,7 +119,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
@@ -223,8 +224,8 @@
 			goto cleanup;
 		}
 
-		if (length > 0) {
-			/* Copy the portion requested */
+		if (buffer) {
+			/* We have a buffer, copy the portion requested */
 
 			ACPI_MEMCPY(buffer, operand[0]->string.pointer + index,
 				    length);
@@ -242,7 +243,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c
index 5dee771..e043d92 100644
--- a/drivers/acpi/executer/exoparg6.c
+++ b/drivers/acpi/executer/exoparg6.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -234,8 +234,7 @@
 
 		if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
 		    (operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Match operator out of range\n"));
+			ACPI_ERROR((AE_INFO, "Match operator out of range"));
 			status = AE_AML_OPERAND_VALUE;
 			goto cleanup;
 		}
@@ -244,10 +243,10 @@
 
 		index = operand[5]->integer.value;
 		if (index >= operand[0]->package.count) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Index (%X%8.8X) beyond package end (%X)\n",
-					  ACPI_FORMAT_UINT64(index),
-					  operand[0]->package.count));
+			ACPI_ERROR((AE_INFO,
+				    "Index (%X%8.8X) beyond package end (%X)",
+				    ACPI_FORMAT_UINT64(index),
+				    operand[0]->package.count));
 			status = AE_AML_PACKAGE_LIMIT;
 			goto cleanup;
 		}
@@ -316,7 +315,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("acpi_ex_opcode_6A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+			    walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
index 7476c36..7719ae5 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/drivers/acpi/executer/exprep.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -274,9 +274,8 @@
 	default:
 		/* Invalid field access type */
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unknown field access type %X\n", access));
-		return_VALUE(0);
+		ACPI_ERROR((AE_INFO, "Unknown field access type %X", access));
+		return_UINT32(0);
 	}
 
 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
@@ -289,7 +288,7 @@
 	}
 
 	*return_byte_alignment = byte_alignment;
-	return_VALUE(bit_length);
+	return_UINT32(bit_length);
 }
 
 /*******************************************************************************
@@ -422,15 +421,15 @@
 
 	if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
 		if (!info->region_node) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null region_node\n"));
+			ACPI_ERROR((AE_INFO, "Null region_node"));
 			return_ACPI_STATUS(AE_AML_NO_OPERAND);
 		}
 
 		type = acpi_ns_get_type(info->region_node);
 		if (type != ACPI_TYPE_REGION) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Needed Region, found type %X (%s)\n",
-					  type, acpi_ut_get_type_name(type)));
+			ACPI_ERROR((AE_INFO,
+				    "Needed Region, found type %X (%s)",
+				    type, acpi_ut_get_type_name(type)));
 
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
@@ -499,17 +498,17 @@
 
 	case ACPI_TYPE_LOCAL_INDEX_FIELD:
 
+		/* Get the Index and Data registers */
+
 		obj_desc->index_field.index_obj =
 		    acpi_ns_get_attached_object(info->register_node);
 		obj_desc->index_field.data_obj =
 		    acpi_ns_get_attached_object(info->data_register_node);
-		obj_desc->index_field.value = (u32)
-		    (info->field_bit_position /
-		     ACPI_MUL_8(obj_desc->field.access_byte_width));
 
 		if (!obj_desc->index_field.data_obj
 		    || !obj_desc->index_field.index_obj) {
-			ACPI_REPORT_ERROR(("Null Index Object during field prep\n"));
+			ACPI_ERROR((AE_INFO,
+				    "Null Index Object during field prep"));
 			acpi_ut_delete_object_desc(obj_desc);
 			return_ACPI_STATUS(AE_AML_INTERNAL);
 		}
@@ -519,6 +518,15 @@
 		acpi_ut_add_reference(obj_desc->index_field.data_obj);
 		acpi_ut_add_reference(obj_desc->index_field.index_obj);
 
+		/*
+		 * The value written to the Index register is the byte offset of the
+		 * target field
+		 * Note: may change code to: ACPI_DIV_8 (Info->field_bit_position)
+		 */
+		obj_desc->index_field.value = (u32)
+		    (info->field_bit_position /
+		     ACPI_MUL_8(obj_desc->field.access_byte_width));
+
 		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 				  "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
 				  obj_desc->index_field.start_field_bit_offset,
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
index 9a2f5be..6a4cfdf 100644
--- a/drivers/acpi/executer/exregion.c
+++ b/drivers/acpi/executer/exregion.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -77,7 +77,7 @@
 	struct acpi_mem_space_context *mem_info = region_context;
 	u32 length;
 	acpi_size window_size;
-#ifndef ACPI_MISALIGNED_TRANSFERS
+#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
 	u32 remainder;
 #endif
 
@@ -103,13 +103,12 @@
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Invalid system_memory width %d\n",
-				  bit_width));
+		ACPI_ERROR((AE_INFO, "Invalid system_memory width %d",
+			    bit_width));
 		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
 	}
 
-#ifndef ACPI_MISALIGNED_TRANSFERS
+#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
 	/*
 	 * Hardware does not support non-aligned data transfers, we must verify
 	 * the request.
@@ -159,10 +158,10 @@
 					    (void **)&mem_info->
 					    mapped_logical_address);
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Could not map memory at %8.8X%8.8X, size %X\n",
-					  ACPI_FORMAT_UINT64(address),
-					  (u32) window_size));
+			ACPI_ERROR((AE_INFO,
+				    "Could not map memory at %8.8X%8.8X, size %X",
+				    ACPI_FORMAT_UINT64(address),
+				    (u32) window_size));
 			mem_info->mapped_length = 0;
 			return_ACPI_STATUS(status);
 		}
@@ -199,20 +198,20 @@
 		*value = 0;
 		switch (bit_width) {
 		case 8:
-			*value = (acpi_integer) * ((u8 *) logical_addr_ptr);
+			*value = (acpi_integer) ACPI_GET8(logical_addr_ptr);
 			break;
 
 		case 16:
-			*value = (acpi_integer) * ((u16 *) logical_addr_ptr);
+			*value = (acpi_integer) ACPI_GET16(logical_addr_ptr);
 			break;
 
 		case 32:
-			*value = (acpi_integer) * ((u32 *) logical_addr_ptr);
+			*value = (acpi_integer) ACPI_GET32(logical_addr_ptr);
 			break;
 
 #if ACPI_MACHINE_WIDTH != 16
 		case 64:
-			*value = (acpi_integer) * ((u64 *) logical_addr_ptr);
+			*value = (acpi_integer) ACPI_GET64(logical_addr_ptr);
 			break;
 #endif
 		default:
@@ -225,20 +224,20 @@
 
 		switch (bit_width) {
 		case 8:
-			*(u8 *) logical_addr_ptr = (u8) * value;
+			ACPI_SET8(logical_addr_ptr) = (u8) * value;
 			break;
 
 		case 16:
-			*(u16 *) logical_addr_ptr = (u16) * value;
+			ACPI_SET16(logical_addr_ptr) = (u16) * value;
 			break;
 
 		case 32:
-			*(u32 *) logical_addr_ptr = (u32) * value;
+			ACPI_SET32(logical_addr_ptr) = (u32) * value;
 			break;
 
 #if ACPI_MACHINE_WIDTH != 16
 		case 64:
-			*(u64 *) logical_addr_ptr = (u64) * value;
+			ACPI_SET64(logical_addr_ptr) = (u64) * value;
 			break;
 #endif
 
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
index ff5d8f9..01b26c8 100644
--- a/drivers/acpi/executer/exresnte.c
+++ b/drivers/acpi/executer/exresnte.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -122,8 +122,7 @@
 	}
 
 	if (!source_desc) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "No object attached to node %p\n", node));
+		ACPI_ERROR((AE_INFO, "No object attached to node %p", node));
 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
 	}
 
@@ -135,10 +134,8 @@
 	case ACPI_TYPE_PACKAGE:
 
 		if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_PACKAGE) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Object not a Package, type %s\n",
-					  acpi_ut_get_object_type_name
-					  (source_desc)));
+			ACPI_ERROR((AE_INFO, "Object not a Package, type %s",
+				    acpi_ut_get_object_type_name(source_desc)));
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 
@@ -154,10 +151,8 @@
 	case ACPI_TYPE_BUFFER:
 
 		if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Object not a Buffer, type %s\n",
-					  acpi_ut_get_object_type_name
-					  (source_desc)));
+			ACPI_ERROR((AE_INFO, "Object not a Buffer, type %s",
+				    acpi_ut_get_object_type_name(source_desc)));
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 
@@ -173,10 +168,8 @@
 	case ACPI_TYPE_STRING:
 
 		if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Object not a String, type %s\n",
-					  acpi_ut_get_object_type_name
-					  (source_desc)));
+			ACPI_ERROR((AE_INFO, "Object not a String, type %s",
+				    acpi_ut_get_object_type_name(source_desc)));
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 
@@ -189,10 +182,8 @@
 	case ACPI_TYPE_INTEGER:
 
 		if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Object not a Integer, type %s\n",
-					  acpi_ut_get_object_type_name
-					  (source_desc)));
+			ACPI_ERROR((AE_INFO, "Object not a Integer, type %s",
+				    acpi_ut_get_object_type_name(source_desc)));
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 
@@ -236,9 +227,8 @@
 
 	case ACPI_TYPE_ANY:
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Untyped entry %p, no attached object!\n",
-				  node));
+		ACPI_ERROR((AE_INFO,
+			    "Untyped entry %p, no attached object!", node));
 
 		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);	/* Cannot be AE_TYPE */
 
@@ -257,12 +247,11 @@
 		default:
 			/* No named references are allowed here */
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Unsupported Reference opcode %X (%s)\n",
-					  source_desc->reference.opcode,
-					  acpi_ps_get_opcode_name(source_desc->
-								  reference.
-								  opcode)));
+			ACPI_ERROR((AE_INFO,
+				    "Unsupported Reference opcode %X (%s)",
+				    source_desc->reference.opcode,
+				    acpi_ps_get_opcode_name(source_desc->
+							    reference.opcode)));
 
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
@@ -272,9 +261,9 @@
 
 		/* Default case is for unknown types */
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Node %p - Unknown object type %X\n",
-				  node, entry_type));
+		ACPI_ERROR((AE_INFO,
+			    "Node %p - Unknown object type %X",
+			    node, entry_type));
 
 		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index 97eecbd..1deed49 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -81,7 +81,7 @@
 	ACPI_FUNCTION_TRACE_PTR("ex_resolve_to_value", stack_ptr);
 
 	if (!stack_ptr || !*stack_ptr) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Internal - null pointer\n"));
+		ACPI_ERROR((AE_INFO, "Internal - null pointer"));
 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
 	}
 
@@ -97,8 +97,7 @@
 		}
 
 		if (!*stack_ptr) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Internal - null pointer\n"));
+			ACPI_ERROR((AE_INFO, "Internal - null pointer"));
 			return_ACPI_STATUS(AE_AML_NO_OPERAND);
 		}
 	}
@@ -228,9 +227,9 @@
 					 * A NULL object descriptor means an unitialized element of
 					 * the package, can't dereference it
 					 */
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "Attempt to deref an Index to NULL pkg element Idx=%p\n",
-							  stack_desc));
+					ACPI_ERROR((AE_INFO,
+						    "Attempt to deref an Index to NULL pkg element Idx=%p",
+						    stack_desc));
 					status = AE_AML_UNINITIALIZED_ELEMENT;
 				}
 				break;
@@ -239,7 +238,10 @@
 
 				/* Invalid reference object */
 
-				ACPI_REPORT_ERROR(("During resolve, Unknown target_type %X in Index/Reference obj %p\n", stack_desc->reference.target_type, stack_desc));
+				ACPI_ERROR((AE_INFO,
+					    "Unknown target_type %X in Index/Reference obj %p",
+					    stack_desc->reference.target_type,
+					    stack_desc));
 				status = AE_AML_INTERNAL;
 				break;
 			}
@@ -264,7 +266,10 @@
 
 		default:
 
-			ACPI_REPORT_ERROR(("During resolve, Unknown Reference opcode %X (%s) in %p\n", opcode, acpi_ps_get_opcode_name(opcode), stack_desc));
+			ACPI_ERROR((AE_INFO,
+				    "Unknown Reference opcode %X (%s) in %p",
+				    opcode, acpi_ps_get_opcode_name(opcode),
+				    stack_desc));
 			status = AE_AML_INTERNAL;
 			break;
 		}
@@ -386,7 +391,9 @@
 
 			if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
 			    ACPI_DESC_TYPE_NAMED) {
-				ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", node, acpi_ut_get_descriptor_name(node)));
+				ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]",
+					    node,
+					    acpi_ut_get_descriptor_name(node)));
 				return_ACPI_STATUS(AE_AML_INTERNAL);
 			}
 
@@ -442,7 +449,9 @@
 
 			if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
 			    ACPI_DESC_TYPE_NAMED) {
-				ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", node, acpi_ut_get_descriptor_name(node)));
+				ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]",
+					    node,
+					    acpi_ut_get_descriptor_name(node)));
 				return_ACPI_STATUS(AE_AML_INTERNAL);
 			}
 
@@ -511,7 +520,9 @@
 
 		default:
 
-			ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Unknown Reference subtype %X\n", obj_desc->reference.opcode));
+			ACPI_ERROR((AE_INFO,
+				    "Unknown Reference subtype %X",
+				    obj_desc->reference.opcode));
 			return_ACPI_STATUS(AE_AML_INTERNAL);
 		}
 	}
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
index ff064e7..a1c000f 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/executer/exresop.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@
 #include <acpi/amlcode.h>
 #include <acpi/acparser.h>
 #include <acpi/acinterp.h>
+#include <acpi/acnamesp.h>
 
 #define _COMPONENT          ACPI_EXECUTER
 ACPI_MODULE_NAME("exresop")
@@ -73,7 +74,7 @@
 acpi_ex_check_object_type(acpi_object_type type_needed,
 			  acpi_object_type this_type, void *object)
 {
-	ACPI_FUNCTION_NAME("ex_check_object_type");
+	ACPI_FUNCTION_ENTRY();
 
 	if (type_needed == ACPI_TYPE_ANY) {
 		/* All types OK, so we don't perform any typechecks */
@@ -95,10 +96,10 @@
 	}
 
 	if (type_needed != this_type) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Needed [%s], found [%s] %p\n",
-				  acpi_ut_get_type_name(type_needed),
-				  acpi_ut_get_type_name(this_type), object));
+		ACPI_ERROR((AE_INFO,
+			    "Needed type [%s], found [%s] %p",
+			    acpi_ut_get_type_name(type_needed),
+			    acpi_ut_get_type_name(this_type), object));
 
 		return (AE_AML_OPERAND_TYPE);
 	}
@@ -151,13 +152,13 @@
 
 	arg_types = op_info->runtime_args;
 	if (arg_types == ARGI_INVALID_OPCODE) {
-		ACPI_REPORT_ERROR(("resolve_operands: %X is not a valid AML opcode\n", opcode));
+		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", opcode));
 
 		return_ACPI_STATUS(AE_AML_INTERNAL);
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-			  "Opcode %X [%s] required_operand_types=%8.8X \n",
+			  "Opcode %X [%s] required_operand_types=%8.8X\n",
 			  opcode, op_info->name, arg_types));
 
 	/*
@@ -169,7 +170,8 @@
 	 */
 	while (GET_CURRENT_ARG_TYPE(arg_types)) {
 		if (!stack_ptr || !*stack_ptr) {
-			ACPI_REPORT_ERROR(("resolve_operands: Null stack entry at %p\n", stack_ptr));
+			ACPI_ERROR((AE_INFO, "Null stack entry at %p",
+				    stack_ptr));
 
 			return_ACPI_STATUS(AE_AML_INTERNAL);
 		}
@@ -187,6 +189,22 @@
 
 			object_type =
 			    ((struct acpi_namespace_node *)obj_desc)->type;
+
+			/*
+			 * Resolve an alias object. The construction of these objects
+			 * guarantees that there is only one level of alias indirection;
+			 * thus, the attached object is always the aliased namespace node
+			 */
+			if (object_type == ACPI_TYPE_LOCAL_ALIAS) {
+				obj_desc =
+				    acpi_ns_get_attached_object((struct
+								 acpi_namespace_node
+								 *)obj_desc);
+				*stack_ptr = obj_desc;
+				object_type =
+				    ((struct acpi_namespace_node *)obj_desc)->
+				    type;
+			}
 			break;
 
 		case ACPI_DESC_TYPE_OPERAND:
@@ -198,9 +216,9 @@
 			/* Check for bad acpi_object_type */
 
 			if (!acpi_ut_valid_object_type(object_type)) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Bad operand object type [%X]\n",
-						  object_type));
+				ACPI_ERROR((AE_INFO,
+					    "Bad operand object type [%X]",
+					    object_type));
 
 				return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 			}
@@ -238,13 +256,10 @@
 					break;
 
 				default:
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "Operand is a Reference, Unknown Reference Opcode %X [%s]\n",
-							  obj_desc->reference.
-							  opcode,
-							  (acpi_ps_get_opcode_info
-							   (obj_desc->reference.
-							    opcode))->name));
+					ACPI_ERROR((AE_INFO,
+						    "Operand is a Reference, Unknown Reference Opcode: %X",
+						    obj_desc->reference.
+						    opcode));
 
 					return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 				}
@@ -255,11 +270,10 @@
 
 			/* Invalid descriptor */
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Invalid descriptor %p [%s]\n",
-					  obj_desc,
-					  acpi_ut_get_descriptor_name
-					  (obj_desc)));
+			ACPI_ERROR((AE_INFO,
+				    "Invalid descriptor %p [%s]",
+				    obj_desc,
+				    acpi_ut_get_descriptor_name(obj_desc)));
 
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
@@ -417,11 +431,10 @@
 			    acpi_ex_convert_to_integer(obj_desc, stack_ptr, 16);
 			if (ACPI_FAILURE(status)) {
 				if (status == AE_TYPE) {
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "Needed [Integer/String/Buffer], found [%s] %p\n",
-							  acpi_ut_get_object_type_name
-							  (obj_desc),
-							  obj_desc));
+					ACPI_ERROR((AE_INFO,
+						    "Needed [Integer/String/Buffer], found [%s] %p",
+						    acpi_ut_get_object_type_name
+						    (obj_desc), obj_desc));
 
 					return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 				}
@@ -444,11 +457,10 @@
 			status = acpi_ex_convert_to_buffer(obj_desc, stack_ptr);
 			if (ACPI_FAILURE(status)) {
 				if (status == AE_TYPE) {
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "Needed [Integer/String/Buffer], found [%s] %p\n",
-							  acpi_ut_get_object_type_name
-							  (obj_desc),
-							  obj_desc));
+					ACPI_ERROR((AE_INFO,
+						    "Needed [Integer/String/Buffer], found [%s] %p",
+						    acpi_ut_get_object_type_name
+						    (obj_desc), obj_desc));
 
 					return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 				}
@@ -472,11 +484,10 @@
 							   ACPI_IMPLICIT_CONVERT_HEX);
 			if (ACPI_FAILURE(status)) {
 				if (status == AE_TYPE) {
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "Needed [Integer/String/Buffer], found [%s] %p\n",
-							  acpi_ut_get_object_type_name
-							  (obj_desc),
-							  obj_desc));
+					ACPI_ERROR((AE_INFO,
+						    "Needed [Integer/String/Buffer], found [%s] %p",
+						    acpi_ut_get_object_type_name
+						    (obj_desc), obj_desc));
 
 					return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 				}
@@ -502,10 +513,10 @@
 				break;
 
 			default:
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Needed [Integer/String/Buffer], found [%s] %p\n",
-						  acpi_ut_get_object_type_name
-						  (obj_desc), obj_desc));
+				ACPI_ERROR((AE_INFO,
+					    "Needed [Integer/String/Buffer], found [%s] %p",
+					    acpi_ut_get_object_type_name
+					    (obj_desc), obj_desc));
 
 				return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 			}
@@ -539,10 +550,10 @@
 				break;
 
 			default:
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Needed [Integer/String/Buffer], found [%s] %p\n",
-						  acpi_ut_get_object_type_name
-						  (obj_desc), obj_desc));
+				ACPI_ERROR((AE_INFO,
+					    "Needed [Integer/String/Buffer], found [%s] %p",
+					    acpi_ut_get_object_type_name
+					    (obj_desc), obj_desc));
 
 				return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 			}
@@ -566,10 +577,10 @@
 				break;
 
 			default:
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Needed [Buffer/String/Package/Reference], found [%s] %p\n",
-						  acpi_ut_get_object_type_name
-						  (obj_desc), obj_desc));
+				ACPI_ERROR((AE_INFO,
+					    "Needed [Buffer/String/Package/Reference], found [%s] %p",
+					    acpi_ut_get_object_type_name
+					    (obj_desc), obj_desc));
 
 				return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 			}
@@ -588,10 +599,10 @@
 				break;
 
 			default:
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Needed [Buffer/String/Package], found [%s] %p\n",
-						  acpi_ut_get_object_type_name
-						  (obj_desc), obj_desc));
+				ACPI_ERROR((AE_INFO,
+					    "Needed [Buffer/String/Package], found [%s] %p",
+					    acpi_ut_get_object_type_name
+					    (obj_desc), obj_desc));
 
 				return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 			}
@@ -611,10 +622,10 @@
 				break;
 
 			default:
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Needed [Region/region_field], found [%s] %p\n",
-						  acpi_ut_get_object_type_name
-						  (obj_desc), obj_desc));
+				ACPI_ERROR((AE_INFO,
+					    "Needed [Region/region_field], found [%s] %p",
+					    acpi_ut_get_object_type_name
+					    (obj_desc), obj_desc));
 
 				return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 			}
@@ -656,10 +667,10 @@
 					break;
 				}
 
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n",
-						  acpi_ut_get_object_type_name
-						  (obj_desc), obj_desc));
+				ACPI_ERROR((AE_INFO,
+					    "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p",
+					    acpi_ut_get_object_type_name
+					    (obj_desc), obj_desc));
 
 				return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 			}
@@ -669,9 +680,9 @@
 
 			/* Unknown type */
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Internal - Unknown ARGI (required operand) type %X\n",
-					  this_arg_type));
+			ACPI_ERROR((AE_INFO,
+				    "Internal - Unknown ARGI (required operand) type %X",
+				    this_arg_type));
 
 			return_ACPI_STATUS(AE_BAD_PARAMETER);
 		}
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index a7d8eea..3f020c0 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -250,7 +250,7 @@
 	/* Validate parameters */
 
 	if (!source_desc || !dest_desc) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null parameter\n"));
+		ACPI_ERROR((AE_INFO, "Null parameter"));
 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
 	}
 
@@ -290,10 +290,10 @@
 
 		/* Destination is not a Reference object */
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Target is not a Reference or Constant object - %s [%p]\n",
-				  acpi_ut_get_object_type_name(dest_desc),
-				  dest_desc));
+		ACPI_ERROR((AE_INFO,
+			    "Target is not a Reference or Constant object - %s [%p]",
+			    acpi_ut_get_object_type_name(dest_desc),
+			    dest_desc));
 
 		ACPI_DUMP_STACK_ENTRY(source_desc);
 		ACPI_DUMP_STACK_ENTRY(dest_desc);
@@ -360,8 +360,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("ex_store: Unknown Reference opcode %X\n",
-				   ref_desc->reference.opcode));
+		ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X",
+			    ref_desc->reference.opcode));
 		ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR);
 
 		status = AE_AML_INTERNAL;
@@ -490,10 +490,9 @@
 
 			/* All other types are invalid */
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Source must be Integer/Buffer/String type, not %s\n",
-					  acpi_ut_get_object_type_name
-					  (source_desc)));
+			ACPI_ERROR((AE_INFO,
+				    "Source must be Integer/Buffer/String type, not %s",
+				    acpi_ut_get_object_type_name(source_desc)));
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 
@@ -503,8 +502,8 @@
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Target is not a Package or buffer_field\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Target is not a Package or buffer_field"));
 		status = AE_AML_OPERAND_TYPE;
 		break;
 	}
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
index 382f63c..42967ba 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/executer/exstoren.c
@@ -7,7 +7,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -123,11 +123,10 @@
 		      && (source_desc->reference.opcode == AML_LOAD_OP))) {
 			/* Conversion successful but still not a valid type */
 
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Cannot assign type %s to %s (must be type Int/Str/Buf)\n",
-					  acpi_ut_get_object_type_name
-					  (source_desc),
-					  acpi_ut_get_type_name(target_type)));
+			ACPI_ERROR((AE_INFO,
+				    "Cannot assign type %s to %s (must be type Int/Str/Buf)",
+				    acpi_ut_get_object_type_name(source_desc),
+				    acpi_ut_get_type_name(target_type)));
 			status = AE_AML_OPERAND_TYPE;
 		}
 		break;
@@ -135,9 +134,11 @@
 	case ACPI_TYPE_LOCAL_ALIAS:
 	case ACPI_TYPE_LOCAL_METHOD_ALIAS:
 
-		/* Aliases are resolved by acpi_ex_prep_operands */
-
-		ACPI_REPORT_ERROR(("Store into Alias - should never happen\n"));
+		/*
+		 * All aliases should have been resolved earlier, during the
+		 * operand resolution phase.
+		 */
+		ACPI_ERROR((AE_INFO, "Store into an unresolved Alias object"));
 		status = AE_AML_INTERNAL;
 		break;
 
@@ -280,9 +281,8 @@
 		/*
 		 * All other types come here.
 		 */
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-				  "Store into type %s not implemented\n",
-				  acpi_ut_get_object_type_name(dest_desc)));
+		ACPI_WARNING((AE_INFO, "Store into type %s not implemented",
+			      acpi_ut_get_object_type_name(dest_desc)));
 
 		status = AE_NOT_IMPLEMENTED;
 		break;
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
index c4ff654..6ab7070 100644
--- a/drivers/acpi/executer/exstorob.c
+++ b/drivers/acpi/executer/exstorob.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,7 @@
 
 	/* We know that source_desc is a buffer by now */
 
-	buffer = (u8 *) source_desc->buffer.pointer;
+	buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer);
 	length = source_desc->buffer.length;
 
 	/*
@@ -160,7 +160,7 @@
 
 	/* We know that source_desc is a string by now */
 
-	buffer = (u8 *) source_desc->string.pointer;
+	buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer);
 	length = source_desc->string.length;
 
 	/*
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index 8a88b84..ea9144f 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -129,8 +129,8 @@
 		 * (ACPI specifies 100 usec as max, but this gives some slack in
 		 * order to support existing BIOSs)
 		 */
-		ACPI_REPORT_ERROR(("Stall: Time parameter is too large (%d)\n",
-				   how_long));
+		ACPI_ERROR((AE_INFO, "Time parameter is too large (%d)",
+			    how_long));
 		status = AE_AML_OPERAND_VALUE;
 	} else {
 		acpi_os_stall(how_long);
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index 1ee79d8..f73a61a 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -91,7 +91,7 @@
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not acquire interpreter mutex\n"));
+		ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex"));
 	}
 
 	return_ACPI_STATUS(status);
@@ -127,7 +127,7 @@
 
 	status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not release interpreter mutex\n"));
+		ACPI_ERROR((AE_INFO, "Could not release interpreter mutex"));
 	}
 
 	return_VOID;
@@ -200,13 +200,12 @@
 		if (ACPI_SUCCESS(status)) {
 			locked = TRUE;
 		} else {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Could not acquire Global Lock, %s\n",
-					  acpi_format_exception(status)));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Could not acquire Global Lock"));
 		}
 	}
 
-	return_VALUE(locked);
+	return_UINT8(locked);
 }
 
 /*******************************************************************************
@@ -237,7 +236,8 @@
 		if (ACPI_FAILURE(status)) {
 			/* Report the error, but there isn't much else we can do */
 
-			ACPI_REPORT_ERROR(("Could not release ACPI Global Lock, %s\n", acpi_format_exception(status)));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Could not release ACPI Global Lock"));
 		}
 	}
 
@@ -268,7 +268,7 @@
 	/* acpi_integer is unsigned, so we don't worry about a '-' prefix */
 
 	if (value == 0) {
-		return_VALUE(1);
+		return_UINT32(1);
 	}
 
 	current_value = value;
@@ -282,7 +282,7 @@
 		num_digits++;
 	}
 
-	return_VALUE(num_digits);
+	return_UINT32(num_digits);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index aa99371..8daef57 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -99,15 +99,15 @@
 	unsigned long *busnr = (unsigned long *)data;
 	struct acpi_resource_address64 address;
 
-	if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
-	    resource->id != ACPI_RSTYPE_ADDRESS32 &&
-	    resource->id != ACPI_RSTYPE_ADDRESS64)
+	if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
+	    resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 &&
+	    resource->type != ACPI_RESOURCE_TYPE_ADDRESS64)
 		return AE_OK;
 
 	acpi_resource_to_address64(resource, &address);
 	if ((address.address_length > 0) &&
 	    (address.resource_type == ACPI_BUS_NUMBER_RANGE))
-		*busnr = address.min_address_range;
+		*busnr = address.minimum;
 
 	return AE_OK;
 }
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c
index 1bb3463..ea2f13271 100644
--- a/drivers/acpi/hardware/hwacpi.c
+++ b/drivers/acpi/hardware/hwacpi.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -68,8 +68,7 @@
 	/* We must have the ACPI tables by the time we get here */
 
 	if (!acpi_gbl_FADT) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No FADT is present\n"));
-
+		ACPI_ERROR((AE_INFO, "No FADT is present"));
 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
 	}
 
@@ -108,7 +107,8 @@
 	 * system does not support mode transition.
 	 */
 	if (!acpi_gbl_FADT->smi_cmd) {
-		ACPI_REPORT_ERROR(("No SMI_CMD in FADT, mode transition failed.\n"));
+		ACPI_ERROR((AE_INFO,
+			    "No SMI_CMD in FADT, mode transition failed"));
 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
 	}
 
@@ -120,7 +120,8 @@
 	 * transitions are not supported.
 	 */
 	if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) {
-		ACPI_REPORT_ERROR(("No ACPI mode transition supported in this system (enable/disable both zero)\n"));
+		ACPI_ERROR((AE_INFO,
+			    "No ACPI mode transition supported in this system (enable/disable both zero)"));
 		return_ACPI_STATUS(AE_OK);
 	}
 
@@ -154,8 +155,8 @@
 	}
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not write mode change, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not write ACPI mode change"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -175,7 +176,7 @@
 		retry--;
 	}
 
-	ACPI_REPORT_ERROR(("Hardware never changed modes\n"));
+	ACPI_ERROR((AE_INFO, "Hardware did not change modes"));
 	return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
 }
 
@@ -204,18 +205,18 @@
 	 * system does not support mode transition.
 	 */
 	if (!acpi_gbl_FADT->smi_cmd) {
-		return_VALUE(ACPI_SYS_MODE_ACPI);
+		return_UINT32(ACPI_SYS_MODE_ACPI);
 	}
 
 	status =
 	    acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK);
 	if (ACPI_FAILURE(status)) {
-		return_VALUE(ACPI_SYS_MODE_LEGACY);
+		return_UINT32(ACPI_SYS_MODE_LEGACY);
 	}
 
 	if (value) {
-		return_VALUE(ACPI_SYS_MODE_ACPI);
+		return_UINT32(ACPI_SYS_MODE_ACPI);
 	} else {
-		return_VALUE(ACPI_SYS_MODE_LEGACY);
+		return_UINT32(ACPI_SYS_MODE_LEGACY);
 	}
 }
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
index 5c8e5df..d84942d 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index 536a7ae..e1fe754 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -7,7 +7,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -144,7 +144,8 @@
 
 	info.parameters = NULL;
 	info.return_object = NULL;
-	sleep_state_name = (char *)acpi_gbl_sleep_state_names[sleep_state];
+	sleep_state_name =
+	    ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
 
 	status = acpi_ns_evaluate_by_name(sleep_state_name, &info);
 	if (ACPI_FAILURE(status)) {
@@ -159,15 +160,16 @@
 	/* Must have a return object */
 
 	if (!info.return_object) {
-		ACPI_REPORT_ERROR(("No Sleep State object returned from [%s]\n",
-				   sleep_state_name));
+		ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
+			    sleep_state_name));
 		status = AE_NOT_EXIST;
 	}
 
 	/* It must be of type Package */
 
 	else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) {
-		ACPI_REPORT_ERROR(("Sleep State return object is not a Package\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Sleep State return object is not a Package"));
 		status = AE_AML_OPERAND_TYPE;
 	}
 
@@ -179,7 +181,8 @@
 	 * one per sleep type (A/B).
 	 */
 	else if (info.return_object->package.count < 2) {
-		ACPI_REPORT_ERROR(("Sleep State return package does not have at least two elements\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Sleep State return package does not have at least two elements"));
 		status = AE_AML_NO_OPERAND;
 	}
 
@@ -189,7 +192,12 @@
 		  != ACPI_TYPE_INTEGER) ||
 		 (ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[1])
 		  != ACPI_TYPE_INTEGER)) {
-		ACPI_REPORT_ERROR(("Sleep State return package elements are not both Integers (%s, %s)\n", acpi_ut_get_object_type_name(info.return_object->package.elements[0]), acpi_ut_get_object_type_name(info.return_object->package.elements[1])));
+		ACPI_ERROR((AE_INFO,
+			    "Sleep State return package elements are not both Integers (%s, %s)",
+			    acpi_ut_get_object_type_name(info.return_object->
+							 package.elements[0]),
+			    acpi_ut_get_object_type_name(info.return_object->
+							 package.elements[1])));
 		status = AE_AML_OPERAND_TYPE;
 	} else {
 		/* Valid _Sx_ package size, type, and value */
@@ -201,12 +209,11 @@
 	}
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "%s While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
-				  acpi_format_exception(status),
-				  sleep_state_name, info.return_object,
-				  acpi_ut_get_object_type_name(info.
-							       return_object)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"While evaluating sleep_state [%s], bad Sleep object %p type %s",
+				sleep_state_name, info.return_object,
+				acpi_ut_get_object_type_name(info.
+							     return_object)));
 	}
 
 	acpi_ut_remove_reference(info.return_object);
@@ -229,12 +236,11 @@
 
 struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
 {
-	ACPI_FUNCTION_NAME("hw_get_bit_register_info");
+	ACPI_FUNCTION_ENTRY();
 
 	if (register_id > ACPI_BITREG_MAX) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Invalid bit_register ID: %X\n",
-				  register_id));
+		ACPI_ERROR((AE_INFO, "Invalid bit_register ID: %X",
+			    register_id));
 		return (NULL);
 	}
 
@@ -334,8 +340,8 @@
 
 	bit_reg_info = acpi_hw_get_bit_register_info(register_id);
 	if (!bit_reg_info) {
-		ACPI_REPORT_ERROR(("Bad ACPI HW register_id: %X\n",
-				   register_id));
+		ACPI_ERROR((AE_INFO, "Bad ACPI HW register_id: %X",
+			    register_id));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -569,8 +575,7 @@
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown Register ID: %X\n",
-				  register_id));
+		ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id));
 		status = AE_BAD_PARAMETER;
 		break;
 	}
@@ -765,9 +770,9 @@
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unsupported address space: %X\n",
-				  reg->address_space_id));
+		ACPI_ERROR((AE_INFO,
+			    "Unsupported address space: %X",
+			    reg->address_space_id));
 		return (AE_BAD_PARAMETER);
 	}
 
@@ -836,9 +841,9 @@
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unsupported address space: %X\n",
-				  reg->address_space_id));
+		ACPI_ERROR((AE_INFO,
+			    "Unsupported address space: %X",
+			    reg->address_space_id));
 		return (AE_BAD_PARAMETER);
 	}
 
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 3451906..8926927 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -199,8 +199,8 @@
 
 	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"While executing method _SST"));
 	}
 
 	return_ACPI_STATUS(AE_OK);
@@ -232,9 +232,8 @@
 
 	if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
 	    (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
-		ACPI_REPORT_ERROR(("Sleep values out of range: A=%X B=%X\n",
-				   acpi_gbl_sleep_type_a,
-				   acpi_gbl_sleep_type_b));
+		ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X",
+			    acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
 		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
 	}
 
@@ -533,21 +532,18 @@
 	arg.integer.value = ACPI_SST_WAKING;
 	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
 	}
 
 	arg.integer.value = sleep_state;
 	status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		ACPI_REPORT_ERROR(("Method _BFS failed, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
 	}
 
 	status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		ACPI_REPORT_ERROR(("Method _WAK failed, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK"));
 	}
 	/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
 
@@ -582,8 +578,7 @@
 	arg.integer.value = ACPI_SST_WORKING;
 	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
 	}
 
 	return_ACPI_STATUS(status);
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
index aff6dc1..fc10b7c 100644
--- a/drivers/acpi/hardware/hwtimer.c
+++ b/drivers/acpi/hardware/hwtimer.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
index e928e8c..4682441 100644
--- a/drivers/acpi/motherboard.c
+++ b/drivers/acpi/motherboard.c
@@ -54,36 +54,36 @@
 
 	ACPI_FUNCTION_TRACE("acpi_reserve_io_ranges");
 
-	if (res->id == ACPI_RSTYPE_IO) {
+	if (res->type == ACPI_RESOURCE_TYPE_IO) {
 		struct acpi_resource_io *io_res = &res->data.io;
 
-		if (io_res->min_base_address != io_res->max_base_address)
+		if (io_res->minimum != io_res->maximum)
 			return_VALUE(AE_OK);
 		if (IS_RESERVED_ADDR
-		    (io_res->min_base_address, io_res->range_length)) {
+		    (io_res->minimum, io_res->address_length)) {
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 					  "Motherboard resources 0x%08x - 0x%08x\n",
-					  io_res->min_base_address,
-					  io_res->min_base_address +
-					  io_res->range_length));
+					  io_res->minimum,
+					  io_res->minimum +
+					  io_res->address_length));
 			requested_res =
-			    request_region(io_res->min_base_address,
-					   io_res->range_length, "motherboard");
+			    request_region(io_res->minimum,
+					   io_res->address_length, "motherboard");
 		}
-	} else if (res->id == ACPI_RSTYPE_FIXED_IO) {
+	} else if (res->type == ACPI_RESOURCE_TYPE_FIXED_IO) {
 		struct acpi_resource_fixed_io *fixed_io_res =
 		    &res->data.fixed_io;
 
 		if (IS_RESERVED_ADDR
-		    (fixed_io_res->base_address, fixed_io_res->range_length)) {
+		    (fixed_io_res->address, fixed_io_res->address_length)) {
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 					  "Motherboard resources 0x%08x - 0x%08x\n",
-					  fixed_io_res->base_address,
-					  fixed_io_res->base_address +
-					  fixed_io_res->range_length));
+					  fixed_io_res->address,
+					  fixed_io_res->address +
+					  fixed_io_res->address_length));
 			requested_res =
-			    request_region(fixed_io_res->base_address,
-					   fixed_io_res->range_length,
+			    request_region(fixed_io_res->address,
+					   fixed_io_res->address_length,
 					   "motherboard");
 		}
 	} else {
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index edfbe34..1149bc1 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -110,10 +110,9 @@
 					ACPI_NS_NO_UPSEARCH, NULL, &new_node);
 
 		if (ACPI_FAILURE(status) || (!new_node)) {	/* Must be on same line for code converter */
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Could not create predefined name %s, %s\n",
-					  init_val->name,
-					  acpi_format_exception(status)));
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Could not create predefined name %s",
+					init_val->name));
 		}
 
 		/*
@@ -124,9 +123,9 @@
 		if (init_val->val) {
 			status = acpi_os_predefined_override(init_val, &val);
 			if (ACPI_FAILURE(status)) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Could not override predefined %s\n",
-						  init_val->name));
+				ACPI_ERROR((AE_INFO,
+					    "Could not override predefined %s",
+					    init_val->name));
 			}
 
 			if (!val) {
@@ -233,7 +232,9 @@
 
 			default:
 
-				ACPI_REPORT_ERROR(("Unsupported initial type value %X\n", init_val->type));
+				ACPI_ERROR((AE_INFO,
+					    "Unsupported initial type value %X",
+					    init_val->type));
 				acpi_ut_remove_reference(obj_desc);
 				obj_desc = NULL;
 				continue;
@@ -339,7 +340,9 @@
 		prefix_node = scope_info->scope.node;
 		if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) !=
 		    ACPI_DESC_TYPE_NAMED) {
-			ACPI_REPORT_ERROR(("ns_lookup: %p is not a namespace node [%s]\n", prefix_node, acpi_ut_get_descriptor_name(prefix_node)));
+			ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]",
+				    prefix_node,
+				    acpi_ut_get_descriptor_name(prefix_node)));
 			return_ACPI_STATUS(AE_AML_INTERNAL);
 		}
 
@@ -429,7 +432,8 @@
 				if (!this_node) {
 					/* Current scope has no parent scope */
 
-					ACPI_REPORT_ERROR(("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
+					ACPI_ERROR((AE_INFO,
+						    "ACPI path has too many parent prefixes (^) - reached beyond root node"));
 					return_ACPI_STATUS(AE_NOT_FOUND);
 				}
 			}
@@ -498,7 +502,7 @@
 			path++;
 
 			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
-					  "Multi Pathname (%d Segments, Flags=%X) \n",
+					  "Multi Pathname (%d Segments, Flags=%X)\n",
 					  num_segments, flags));
 			break;
 
@@ -600,7 +604,12 @@
 		    (this_node->type != type_to_check_for)) {
 			/* Complain about a type mismatch */
 
-			ACPI_REPORT_WARNING(("ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)\n", (char *)&simple_name, acpi_ut_get_type_name(this_node->type), acpi_ut_get_type_name(type_to_check_for)));
+			ACPI_WARNING((AE_INFO,
+				      "ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)",
+				      ACPI_CAST_PTR(char, &simple_name),
+				      acpi_ut_get_type_name(this_node->type),
+				      acpi_ut_get_type_name
+				      (type_to_check_for)));
 		}
 
 		/*
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index cc7a85f..9b871f3 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -272,9 +272,8 @@
 		/* Grandchildren should have all been deleted already */
 
 		if (child_node->child) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Found a grandchild! P=%p C=%p\n",
-					  parent_node, child_node));
+			ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p",
+				    parent_node, child_node));
 		}
 
 		/* Now we can free this child object */
@@ -302,7 +301,9 @@
 		/* There should be only one reference remaining on this node */
 
 		if (child_node->reference_count != 1) {
-			ACPI_REPORT_WARNING(("Existing references (%d) on node being deleted (%p)\n", child_node->reference_count, child_node));
+			ACPI_WARNING((AE_INFO,
+				      "Existing references (%d) on node being deleted (%p)",
+				      child_node->reference_count, child_node));
 		}
 
 		/* Now we can delete the node */
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
index 9faf1d5..a280731 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/drivers/acpi/namespace/nsdump.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -198,12 +198,13 @@
 		/* Check the node type and name */
 
 		if (type > ACPI_TYPE_LOCAL_MAX) {
-			ACPI_REPORT_WARNING(("Invalid ACPI Type %08X\n", type));
+			ACPI_WARNING((AE_INFO, "Invalid ACPI Object Type %08X",
+				      type));
 		}
 
 		if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
-			ACPI_REPORT_WARNING(("Invalid ACPI Name %08X\n",
-					     this_node->name.integer));
+			ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
+				      this_node->name.integer));
 		}
 
 		acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
@@ -212,7 +213,9 @@
 	/*
 	 * Now we can print out the pertinent information
 	 */
-	acpi_os_printf(" %-12s %p ", acpi_ut_get_type_name(type), this_node);
+	acpi_os_printf(" %-12s %p %2.2X ",
+		       acpi_ut_get_type_name(type), this_node,
+		       this_node->owner_id);
 
 	dbg_level = acpi_dbg_level;
 	acpi_dbg_level = 0;
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
index 55de883..aff899a 100644
--- a/drivers/acpi/namespace/nsdumpdv.c
+++ b/drivers/acpi/namespace/nsdumpdv.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 0191c7d..19d7b94 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -373,8 +373,7 @@
 
 	info->obj_desc = acpi_ns_get_attached_object(info->node);
 	if (!info->obj_desc) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "No attached method object\n"));
+		ACPI_ERROR((AE_INFO, "No attached method object"));
 
 		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 		return_ACPI_STATUS(AE_NULL_OBJECT);
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 0a08d2f..9f929e4 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -93,8 +93,7 @@
 				     ACPI_UINT32_MAX, acpi_ns_init_one_object,
 				     &info, NULL);
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
-				  acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
 	}
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
@@ -159,12 +158,11 @@
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
-				  acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
 	}
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
-			      "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n",
+			      "\n%hd Devices found - executed %hd _STA, %hd _INI methods\n",
 			      info.device_count, info.num_STA, info.num_INI));
 
 	return_ACPI_STATUS(status);
@@ -289,12 +287,10 @@
 	}
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR, "\n"));
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Could not execute arguments for [%4.4s] (%s), %s\n",
-				  acpi_ut_get_node_name(node),
-				  acpi_ut_get_type_name(type),
-				  acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not execute arguments for [%4.4s] (%s)",
+				acpi_ut_get_node_name(node),
+				acpi_ut_get_type_name(type)));
 	}
 
 	/*
@@ -336,23 +332,22 @@
 	struct acpi_parameter_info pinfo;
 	u32 flags;
 	acpi_status status;
+	struct acpi_namespace_node *ini_node;
+	struct acpi_namespace_node *device_node;
 
 	ACPI_FUNCTION_TRACE("ns_init_one_device");
 
-	pinfo.parameters = NULL;
-	pinfo.parameter_type = ACPI_PARAM_ARGS;
-
-	pinfo.node = acpi_ns_map_handle_to_node(obj_handle);
-	if (!pinfo.node) {
+	device_node = acpi_ns_map_handle_to_node(obj_handle);
+	if (!device_node) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
 	/*
 	 * We will run _STA/_INI on Devices, Processors and thermal_zones only
 	 */
-	if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
-	    (pinfo.node->type != ACPI_TYPE_PROCESSOR) &&
-	    (pinfo.node->type != ACPI_TYPE_THERMAL)) {
+	if ((device_node->type != ACPI_TYPE_DEVICE) &&
+	    (device_node->type != ACPI_TYPE_PROCESSOR) &&
+	    (device_node->type != ACPI_TYPE_THERMAL)) {
 		return_ACPI_STATUS(AE_OK);
 	}
 
@@ -364,57 +359,69 @@
 	info->device_count++;
 
 	/*
-	 * Run _STA to determine if we can run _INI on the device.
+	 * Check if the _INI method exists for this device -
+	 * if _INI does not exist, there is no need to run _STA
+	 * No _INI means device requires no initialization
 	 */
-	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
-						      pinfo.node,
-						      METHOD_NAME__STA));
-	status = acpi_ut_execute_STA(pinfo.node, &flags);
-
+	status = acpi_ns_search_node(*ACPI_CAST_PTR(u32, METHOD_NAME__INI),
+				     device_node, ACPI_TYPE_METHOD, &ini_node);
 	if (ACPI_FAILURE(status)) {
-		if (pinfo.node->type == ACPI_TYPE_DEVICE) {
-			/* Ignore error and move on to next device */
+		/* No _INI method found - move on to next device */
 
-			return_ACPI_STATUS(AE_OK);
-		}
-
-		/* _STA is not required for Processor or thermal_zone objects */
-	} else {
-		info->num_STA++;
-
-		if (!(flags & 0x01)) {
-			/* Don't look at children of a not present device */
-
-			return_ACPI_STATUS(AE_CTRL_DEPTH);
-		}
+		return_ACPI_STATUS(AE_OK);
 	}
 
 	/*
-	 * The device is present. Run _INI.
+	 * Run _STA to determine if we can run _INI on the device -
+	 * the device must be present before _INI can be run.
+	 * However, _STA is not required - assume device present if no _STA
+	 */
+	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
+						      device_node,
+						      METHOD_NAME__STA));
+
+	pinfo.node = device_node;
+	pinfo.parameters = NULL;
+	pinfo.parameter_type = ACPI_PARAM_ARGS;
+
+	status = acpi_ut_execute_STA(pinfo.node, &flags);
+	if (ACPI_FAILURE(status)) {
+		/* Ignore error and move on to next device */
+
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	if (flags != ACPI_UINT32_MAX) {
+		info->num_STA++;
+	}
+
+	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
+		/* Don't look at children of a not present device */
+
+		return_ACPI_STATUS(AE_CTRL_DEPTH);
+	}
+
+	/*
+	 * The device is present and _INI exists. Run the _INI method.
+	 * (We already have the _INI node from above)
 	 */
 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
 						      pinfo.node,
 						      METHOD_NAME__INI));
-	status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo);
-	if (ACPI_FAILURE(status)) {
-		/* No _INI (AE_NOT_FOUND) means device requires no initialization */
 
-		if (status != AE_NOT_FOUND) {
-			/* Ignore error and move on to next device */
+	pinfo.node = ini_node;
+	status = acpi_ns_evaluate_by_handle(&pinfo);
+	if (ACPI_FAILURE(status)) {
+		/* Ignore error and move on to next device */
 
 #ifdef ACPI_DEBUG_OUTPUT
-			char *scope_name =
-			    acpi_ns_get_external_pathname(pinfo.node);
+		char *scope_name = acpi_ns_get_external_pathname(ini_node);
 
-			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "%s._INI failed: %s\n",
-					  scope_name,
-					  acpi_format_exception(status)));
+		ACPI_WARNING((AE_INFO, "%s._INI failed: %s",
+			      scope_name, acpi_format_exception(status)));
 
-			ACPI_MEM_FREE(scope_name);
+		ACPI_MEM_FREE(scope_name);
 #endif
-		}
-
-		status = AE_OK;
 	} else {
 		/* Delete any return object (especially if implicit_return is enabled) */
 
@@ -434,5 +441,5 @@
 		    acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI);
 	}
 
-	return_ACPI_STATUS(status);
+	return_ACPI_STATUS(AE_OK);
 }
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index c28849d..4e0b052 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -92,7 +92,7 @@
 	/* Check validity of the AML start and length */
 
 	if (!table_desc->aml_start) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null AML pointer\n"));
+		ACPI_ERROR((AE_INFO, "Null AML pointer"));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -102,8 +102,8 @@
 	/* Ignore table if there is no AML contained within */
 
 	if (!table_desc->aml_length) {
-		ACPI_REPORT_WARNING(("Zero-length AML block in table [%4.4s]\n",
-				     table_desc->pointer->signature));
+		ACPI_WARNING((AE_INFO, "Zero-length AML block in table [%4.4s]",
+			      table_desc->pointer->signature));
 		return_ACPI_STATUS(AE_OK);
 	}
 
@@ -263,7 +263,7 @@
 	/* There must be at least a DSDT installed */
 
 	if (acpi_gbl_DSDT == NULL) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "DSDT is not in memory\n"));
+		ACPI_ERROR((AE_INFO, "DSDT is not in memory"));
 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
 	}
 
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index d5e8dea..639f653 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -75,7 +75,7 @@
 	acpi_size index;
 	struct acpi_namespace_node *parent_node;
 
-	ACPI_FUNCTION_NAME("ns_build_external_path");
+	ACPI_FUNCTION_ENTRY();
 
 	/* Special case for root */
 
@@ -110,9 +110,9 @@
 	name_buffer[index] = AML_ROOT_PREFIX;
 
 	if (index != 0) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Could not construct pathname; index=%X, size=%X, Path=%s\n",
-				  (u32) index, (u32) size, &name_buffer[size]));
+		ACPI_ERROR((AE_INFO,
+			    "Could not construct pathname; index=%X, size=%X, Path=%s",
+			    (u32) index, (u32) size, &name_buffer[size]));
 	}
 
 	return;
@@ -148,7 +148,7 @@
 
 	name_buffer = ACPI_MEM_CALLOCATE(size);
 	if (!name_buffer) {
-		ACPI_REPORT_ERROR(("ns_get_table_pathname: allocation failure\n"));
+		ACPI_ERROR((AE_INFO, "Allocation failure"));
 		return_PTR(NULL);
 	}
 
@@ -241,7 +241,7 @@
 
 	acpi_ns_build_external_path(node, required_size, buffer->pointer);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X] \n",
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n",
 			  (char *)buffer->pointer, (u32) required_size));
 	return_ACPI_STATUS(AE_OK);
 }
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
index fc9be94..10ae629 100644
--- a/drivers/acpi/namespace/nsobject.c
+++ b/drivers/acpi/namespace/nsobject.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -84,22 +84,23 @@
 	if (!node) {
 		/* Invalid handle */
 
-		ACPI_REPORT_ERROR(("ns_attach_object: Null named_obj handle\n"));
+		ACPI_ERROR((AE_INFO, "Null named_obj handle"));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
 	if (!object && (ACPI_TYPE_ANY != type)) {
 		/* Null object */
 
-		ACPI_REPORT_ERROR(("ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Null object, but type not ACPI_TYPE_ANY"));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
 	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
 		/* Not a name handle */
 
-		ACPI_REPORT_ERROR(("ns_attach_object: Invalid handle %p [%s]\n",
-				   node, acpi_ut_get_descriptor_name(node)));
+		ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
+			    node, acpi_ut_get_descriptor_name(node)));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -254,7 +255,7 @@
 	ACPI_FUNCTION_TRACE_PTR("ns_get_attached_object", node);
 
 	if (!node) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Null Node ptr\n"));
+		ACPI_WARNING((AE_INFO, "Null Node ptr"));
 		return_PTR(NULL);
 	}
 
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
index 433442a..232be43 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/namespace/nsparse.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
index 50a3ca5..d64b789 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/namespace/nssearch.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -99,8 +99,8 @@
 		if (scope_name) {
 			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 					  "Searching %s (%p) For [%4.4s] (%s)\n",
-					  scope_name, node,
-					  (char *)&target_name,
+					  scope_name, node, ACPI_CAST_PTR(char,
+									  &target_name),
 					  acpi_ut_get_type_name(type)));
 
 			ACPI_MEM_FREE(scope_name);
@@ -131,7 +131,7 @@
 			 */
 			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 					  "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
-					  (char *)&target_name,
+					  ACPI_CAST_PTR(char, &target_name),
 					  acpi_ut_get_type_name(next_node->
 								type),
 					  next_node,
@@ -160,7 +160,8 @@
 
 	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 			  "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
-			  (char *)&target_name, acpi_ut_get_type_name(type),
+			  ACPI_CAST_PTR(char, &target_name),
+			  acpi_ut_get_type_name(type),
 			  acpi_ut_get_node_name(node), node, node->child));
 
 	return_ACPI_STATUS(AE_NOT_FOUND);
@@ -210,14 +211,14 @@
 	 */
 	if (!parent_node) {
 		ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[%4.4s] has no parent\n",
-				  (char *)&target_name));
+				  ACPI_CAST_PTR(char, &target_name)));
 		return_ACPI_STATUS(AE_NOT_FOUND);
 	}
 
 	if (acpi_ns_local(type)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 				  "[%4.4s] type [%s] must be local to this scope (no parent search)\n",
-				  (char *)&target_name,
+				  ACPI_CAST_PTR(char, &target_name),
 				  acpi_ut_get_type_name(type)));
 		return_ACPI_STATUS(AE_NOT_FOUND);
 	}
@@ -227,7 +228,7 @@
 	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 			  "Searching parent [%4.4s] for [%4.4s]\n",
 			  acpi_ut_get_node_name(parent_node),
-			  (char *)&target_name));
+			  ACPI_CAST_PTR(char, &target_name)));
 
 	/*
 	 * Search parents until target is found or we have backed up to the root
@@ -297,18 +298,17 @@
 	/* Parameter validation */
 
 	if (!node || !target_name || !return_node) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Null param: Node %p Name %X return_node %p\n",
-				  node, target_name, return_node));
-
-		ACPI_REPORT_ERROR(("ns_search_and_enter: Null parameter\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Null param: Node %p Name %X return_node %p",
+			    node, target_name, return_node));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
 	/* Name must consist of printable characters */
 
 	if (!acpi_ut_valid_acpi_name(target_name)) {
-		ACPI_REPORT_ERROR(("ns_search_and_enter: Bad character in ACPI Name: %X\n", target_name));
+		ACPI_ERROR((AE_INFO, "Bad character in ACPI Name: %X",
+			    target_name));
 		return_ACPI_STATUS(AE_BAD_CHARACTER);
 	}
 
@@ -360,7 +360,7 @@
 	if (interpreter_mode == ACPI_IMODE_EXECUTE) {
 		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 				  "%4.4s Not found in %p [Not adding]\n",
-				  (char *)&target_name, node));
+				  ACPI_CAST_PTR(char, &target_name), node));
 
 		return_ACPI_STATUS(AE_NOT_FOUND);
 	}
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
index ebec036..3e7cad5 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/drivers/acpi/namespace/nsutils.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,6 @@
  *
  * PARAMETERS:  module_name         - Caller's module name (for error output)
  *              line_number         - Caller's line number (for error output)
- *              component_id        - Caller's component ID (for error output)
  *              internal_name       - Name or path of the namespace node
  *              lookup_status       - Exception code from NS lookup
  *
@@ -76,19 +75,17 @@
 void
 acpi_ns_report_error(char *module_name,
 		     u32 line_number,
-		     u32 component_id,
 		     char *internal_name, acpi_status lookup_status)
 {
 	acpi_status status;
 	char *name = NULL;
 
-	acpi_os_printf("%8s-%04d: *** Error: Looking up ",
-		       module_name, line_number);
+	acpi_ut_report_error(module_name, line_number);
 
 	if (lookup_status == AE_BAD_CHARACTER) {
 		/* There is a non-ascii character in the name */
 
-		acpi_os_printf("[0x%4.4X] (NON-ASCII)\n",
+		acpi_os_printf("[0x%4.4X] (NON-ASCII)",
 			       *(ACPI_CAST_PTR(u32, internal_name)));
 	} else {
 		/* Convert path to external format */
@@ -109,7 +106,7 @@
 		}
 	}
 
-	acpi_os_printf(" in namespace, %s\n",
+	acpi_os_printf(" Namespace lookup failure, %s\n",
 		       acpi_format_exception(lookup_status));
 }
 
@@ -119,10 +116,9 @@
  *
  * PARAMETERS:  module_name         - Caller's module name (for error output)
  *              line_number         - Caller's line number (for error output)
- *              component_id        - Caller's component ID (for error output)
  *              Message             - Error message to use on failure
  *              prefix_node         - Prefix relative to the path
- *              Path                - Path to the node
+ *              Path                - Path to the node (optional)
  *              method_status       - Execution status
  *
  * RETURN:      None
@@ -134,7 +130,6 @@
 void
 acpi_ns_report_method_error(char *module_name,
 			    u32 line_number,
-			    u32 component_id,
 			    char *message,
 			    struct acpi_namespace_node *prefix_node,
 			    char *path, acpi_status method_status)
@@ -142,17 +137,16 @@
 	acpi_status status;
 	struct acpi_namespace_node *node = prefix_node;
 
+	acpi_ut_report_error(module_name, line_number);
+
 	if (path) {
 		status = acpi_ns_get_node_by_path(path, prefix_node,
 						  ACPI_NS_NO_UPSEARCH, &node);
 		if (ACPI_FAILURE(status)) {
-			acpi_os_printf
-			    ("report_method_error: Could not get node\n");
-			return;
+			acpi_os_printf("[Could not get node by pathname]");
 		}
 	}
 
-	acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
 	acpi_ns_print_node_pathname(node, message);
 	acpi_os_printf(", %s\n", acpi_format_exception(method_status));
 }
@@ -248,11 +242,11 @@
 	ACPI_FUNCTION_TRACE("ns_get_type");
 
 	if (!node) {
-		ACPI_REPORT_WARNING(("ns_get_type: Null Node input pointer\n"));
-		return_VALUE(ACPI_TYPE_ANY);
+		ACPI_WARNING((AE_INFO, "Null Node parameter"));
+		return_UINT32(ACPI_TYPE_ANY);
 	}
 
-	return_VALUE((acpi_object_type) node->type);
+	return_UINT32((acpi_object_type) node->type);
 }
 
 /*******************************************************************************
@@ -275,11 +269,11 @@
 	if (!acpi_ut_valid_object_type(type)) {
 		/* Type code out of range  */
 
-		ACPI_REPORT_WARNING(("ns_local: Invalid Object Type\n"));
-		return_VALUE(ACPI_NS_NORMAL);
+		ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
+		return_UINT32(ACPI_NS_NORMAL);
 	}
 
-	return_VALUE((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
+	return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
 }
 
 /*******************************************************************************
@@ -627,7 +621,7 @@
 	 * with internal_name (invalid format).
 	 */
 	if (required_length > internal_name_length) {
-		ACPI_REPORT_ERROR(("ns_externalize_name: Invalid internal name\n"));
+		ACPI_ERROR((AE_INFO, "Invalid internal name"));
 		return_ACPI_STATUS(AE_BAD_PATHNAME);
 	}
 
@@ -803,12 +797,11 @@
 	if (!acpi_ut_valid_object_type(type)) {
 		/* type code out of range  */
 
-		ACPI_REPORT_WARNING(("ns_opens_scope: Invalid Object Type %X\n",
-				     type));
-		return_VALUE(ACPI_NS_NORMAL);
+		ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
+		return_UINT32(ACPI_NS_NORMAL);
 	}
 
-	return_VALUE(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
+	return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
index 5f164c0..fcab1e7 100644
--- a/drivers/acpi/namespace/nswalk.c
+++ b/drivers/acpi/namespace/nswalk.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index c07b046..a95f636 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -112,8 +112,7 @@
 	if (return_buffer->length == 0) {
 		/* Error because caller specifically asked for a return value */
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No return value\n"));
-
+		ACPI_ERROR((AE_INFO, "No return value"));
 		return_ACPI_STATUS(AE_NULL_OBJECT);
 	}
 
@@ -125,11 +124,11 @@
 
 	/* Return object type does not match requested type */
 
-	ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-			  "Incorrect return type [%s] requested [%s]\n",
-			  acpi_ut_get_type_name(((union acpi_object *)
-						 return_buffer->pointer)->type),
-			  acpi_ut_get_type_name(return_type)));
+	ACPI_ERROR((AE_INFO,
+		    "Incorrect return type [%s] requested [%s]",
+		    acpi_ut_get_type_name(((union acpi_object *)return_buffer->
+					   pointer)->type),
+		    acpi_ut_get_type_name(return_type)));
 
 	if (must_free) {
 		/* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
@@ -236,11 +235,11 @@
 		 * qualified names above, this is an error
 		 */
 		if (!pathname) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Both Handle and Pathname are NULL\n"));
+			ACPI_ERROR((AE_INFO,
+				    "Both Handle and Pathname are NULL"));
 		} else {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Handle is NULL and Pathname is relative\n"));
+			ACPI_ERROR((AE_INFO,
+				    "Handle is NULL and Pathname is relative"));
 		}
 
 		status = AE_BAD_PARAMETER;
@@ -399,7 +398,7 @@
 
 	/* Parameter validation */
 
-	if ((type > ACPI_TYPE_EXTERNAL_MAX) || (!max_depth) || (!user_function)) {
+	if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -473,8 +472,8 @@
 		return (AE_CTRL_DEPTH);
 	}
 
-	if (!(flags & 0x01)) {
-		/* Don't return at the device or children of the device if not there */
+	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
+		/* Don't examine children of the device if not present */
 
 		return (AE_CTRL_DEPTH);
 	}
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index 6b5f8d4..8cd8675 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -300,8 +300,7 @@
 
 		status = acpi_ut_execute_CID(node, &cid_list);
 		if (ACPI_SUCCESS(status)) {
-			size += ((acpi_size) cid_list->count - 1) *
-			    sizeof(struct acpi_compatible_id);
+			size += cid_list->size;
 			info->valid |= ACPI_VALID_CID;
 		}
 
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index 0856d42..a033259 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 20c9a37..ac5bbae 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -838,7 +838,7 @@
 			static const int quantum_ms = 1000 / HZ;
 
 			ret = down_trylock(sem);
-			for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) {
+			for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
 				schedule_timeout_interruptible(1);
 				ret = down_trylock(sem);
 			}
@@ -1060,13 +1060,11 @@
  * Acquire a spinlock.
  *
  * handle is a pointer to the spinlock_t.
- * flags is *not* the result of save_flags - it is an ACPI-specific flag variable
- *   that indicates whether we are at interrupt level.
  */
 
-unsigned long acpi_os_acquire_lock(acpi_handle handle)
+acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle)
 {
-	unsigned long flags;
+	acpi_cpu_flags flags;
 	spin_lock_irqsave((spinlock_t *) handle, flags);
 	return flags;
 }
@@ -1075,7 +1073,7 @@
  * Release a spinlock. See above.
  */
 
-void acpi_os_release_lock(acpi_handle handle, unsigned long flags)
+void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags)
 {
 	spin_unlock_irqrestore((spinlock_t *) handle, flags);
 }
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index 5858188..de573be 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
 #include <acpi/acparser.h>
 #include <acpi/amlcode.h>
 #include <acpi/acnamesp.h>
+#include <acpi/acdispat.h>
 
 #define _COMPONENT          ACPI_PARSER
 ACPI_MODULE_NAME("psargs")
@@ -62,61 +63,51 @@
  *
  * PARAMETERS:  parser_state        - Current parser state object
  *
- * RETURN:      Decoded package length.  On completion, the AML pointer points
+ * RETURN:      Decoded package length. On completion, the AML pointer points
  *              past the length byte or bytes.
  *
- * DESCRIPTION: Decode and return a package length field
+ * DESCRIPTION: Decode and return a package length field.
+ *              Note: Largest package length is 28 bits, from ACPI specification
  *
  ******************************************************************************/
 
 static u32
 acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
 {
-	u32 encoded_length;
-	u32 length = 0;
+	u8 *aml = parser_state->aml;
+	u32 package_length = 0;
+	acpi_native_uint byte_count;
+	u8 byte_zero_mask = 0x3F;	/* Default [0:5] */
 
 	ACPI_FUNCTION_TRACE("ps_get_next_package_length");
 
-	encoded_length = (u32) ACPI_GET8(parser_state->aml);
-	parser_state->aml++;
+	/*
+	 * Byte 0 bits [6:7] contain the number of additional bytes
+	 * used to encode the package length, either 0,1,2, or 3
+	 */
+	byte_count = (aml[0] >> 6);
+	parser_state->aml += (byte_count + 1);
 
-	switch (encoded_length >> 6) {	/* bits 6-7 contain encoding scheme */
-	case 0:		/* 1-byte encoding (bits 0-5) */
+	/* Get bytes 3, 2, 1 as needed */
 
-		length = (encoded_length & 0x3F);
-		break;
+	while (byte_count) {
+		/*
+		 * Final bit positions for the package length bytes:
+		 *      Byte3->[20:27]
+		 *      Byte2->[12:19]
+		 *      Byte1->[04:11]
+		 *      Byte0->[00:03]
+		 */
+		package_length |= (aml[byte_count] << ((byte_count << 3) - 4));
 
-	case 1:		/* 2-byte encoding (next byte + bits 0-3) */
-
-		length = ((ACPI_GET8(parser_state->aml) << 04) |
-			  (encoded_length & 0x0F));
-		parser_state->aml++;
-		break;
-
-	case 2:		/* 3-byte encoding (next 2 bytes + bits 0-3) */
-
-		length = ((ACPI_GET8(parser_state->aml + 1) << 12) |
-			  (ACPI_GET8(parser_state->aml) << 04) |
-			  (encoded_length & 0x0F));
-		parser_state->aml += 2;
-		break;
-
-	case 3:		/* 4-byte encoding (next 3 bytes + bits 0-3) */
-
-		length = ((ACPI_GET8(parser_state->aml + 2) << 20) |
-			  (ACPI_GET8(parser_state->aml + 1) << 12) |
-			  (ACPI_GET8(parser_state->aml) << 04) |
-			  (encoded_length & 0x0F));
-		parser_state->aml += 3;
-		break;
-
-	default:
-
-		/* Can't get here, only 2 bits / 4 cases */
-		break;
+		byte_zero_mask = 0x0F;	/* Use bits [0:3] of byte 0 */
+		byte_count--;
 	}
 
-	return_VALUE(length);
+	/* Byte 0 is a special case, either bits [0:3] or [0:5] are used */
+
+	package_length |= (aml[0] & byte_zero_mask);
+	return_UINT32(package_length);
 }
 
 /*******************************************************************************
@@ -135,16 +126,15 @@
 u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
 {
 	u8 *start = parser_state->aml;
-	acpi_native_uint length;
+	u32 package_length;
 
 	ACPI_FUNCTION_TRACE("ps_get_next_package_end");
 
-	/* Function below changes parser_state->Aml */
+	/* Function below updates parser_state->Aml */
 
-	length =
-	    (acpi_native_uint) acpi_ps_get_next_package_length(parser_state);
+	package_length = acpi_ps_get_next_package_length(parser_state);
 
-	return_PTR(start + length);	/* end of package */
+	return_PTR(start + package_length);	/* end of package */
 }
 
 /*******************************************************************************
@@ -169,17 +159,15 @@
 
 	ACPI_FUNCTION_TRACE("ps_get_next_namestring");
 
-	/* Handle multiple prefix characters */
+	/* Point past any namestring prefix characters (backslash or carat) */
 
-	while (acpi_ps_is_prefix_char(ACPI_GET8(end))) {
-		/* Include prefix '\\' or '^' */
-
+	while (acpi_ps_is_prefix_char(*end)) {
 		end++;
 	}
 
-	/* Decode the path */
+	/* Decode the path prefix character */
 
-	switch (ACPI_GET8(end)) {
+	switch (*end) {
 	case 0:
 
 		/* null_name */
@@ -199,9 +187,9 @@
 
 	case AML_MULTI_NAME_PREFIX_OP:
 
-		/* Multiple name segments, 4 chars each */
+		/* Multiple name segments, 4 chars each, count in next byte */
 
-		end += 2 + ((acpi_size) ACPI_GET8(end + 1) * ACPI_NAME_SIZE);
+		end += 2 + (*(end + 1) * ACPI_NAME_SIZE);
 		break;
 
 	default:
@@ -212,7 +200,7 @@
 		break;
 	}
 
-	parser_state->aml = (u8 *) end;
+	parser_state->aml = end;
 	return_PTR((char *)start);
 }
 
@@ -224,7 +212,7 @@
  *              Arg                 - Where the namepath will be stored
  *              arg_count           - If the namepath points to a control method
  *                                    the method's argument is returned here.
- *              method_call         - Whether the namepath can possibly be the
+ *              possible_method_call - Whether the namepath can possibly be the
  *                                    start of a method call
  *
  * RETURN:      Status
@@ -240,11 +228,11 @@
 acpi_status
 acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
 			  struct acpi_parse_state *parser_state,
-			  union acpi_parse_object *arg, u8 method_call)
+			  union acpi_parse_object *arg, u8 possible_method_call)
 {
 	char *path;
 	union acpi_parse_object *name_op;
-	acpi_status status = AE_OK;
+	acpi_status status;
 	union acpi_operand_object *method_desc;
 	struct acpi_namespace_node *node;
 	union acpi_generic_state scope_info;
@@ -252,115 +240,129 @@
 	ACPI_FUNCTION_TRACE("ps_get_next_namepath");
 
 	path = acpi_ps_get_next_namestring(parser_state);
+	acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
 
-	/* Null path case is allowed */
+	/* Null path case is allowed, just exit */
 
-	if (path) {
-		/*
-		 * Lookup the name in the internal namespace
-		 */
-		scope_info.scope.node = NULL;
-		node = parser_state->start_node;
-		if (node) {
-			scope_info.scope.node = node;
-		}
+	if (!path) {
+		arg->common.value.name = path;
+		return_ACPI_STATUS(AE_OK);
+	}
 
-		/*
-		 * Lookup object.  We don't want to add anything new to the namespace
-		 * here, however.  So we use MODE_EXECUTE.  Allow searching of the
-		 * parent tree, but don't open a new scope -- we just want to lookup the
-		 * object  (MUST BE mode EXECUTE to perform upsearch)
-		 */
-		status = acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY,
-					ACPI_IMODE_EXECUTE,
-					ACPI_NS_SEARCH_PARENT |
-					ACPI_NS_DONT_OPEN_SCOPE, NULL, &node);
-		if (ACPI_SUCCESS(status) && method_call) {
-			if (node->type == ACPI_TYPE_METHOD) {
-				/* This name is actually a control method invocation */
+	/* Setup search scope info */
 
-				method_desc = acpi_ns_get_attached_object(node);
-				ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-						  "Control Method - %p Desc %p Path=%p\n",
-						  node, method_desc, path));
-
-				name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
-				if (!name_op) {
-					return_ACPI_STATUS(AE_NO_MEMORY);
-				}
-
-				/* Change arg into a METHOD CALL and attach name to it */
-
-				acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
-				name_op->common.value.name = path;
-
-				/* Point METHODCALL/NAME to the METHOD Node */
-
-				name_op->common.node = node;
-				acpi_ps_append_arg(arg, name_op);
-
-				if (!method_desc) {
-					ACPI_REPORT_ERROR(("ps_get_next_namepath: Control Method %p has no attached object\n", node));
-					return_ACPI_STATUS(AE_AML_INTERNAL);
-				}
-
-				ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-						  "Control Method - %p Args %X\n",
-						  node,
-						  method_desc->method.
-						  param_count));
-
-				/* Get the number of arguments to expect */
-
-				walk_state->arg_count =
-				    method_desc->method.param_count;
-				return_ACPI_STATUS(AE_OK);
-			}
-
-			/*
-			 * Else this is normal named object reference.
-			 * Just init the NAMEPATH object with the pathname.
-			 * (See code below)
-			 */
-		}
-
-		if (ACPI_FAILURE(status)) {
-			/*
-			 * 1) Any error other than NOT_FOUND is always severe
-			 * 2) NOT_FOUND is only important if we are executing a method.
-			 * 3) If executing a cond_ref_of opcode, NOT_FOUND is ok.
-			 */
-			if ((((walk_state->
-			       parse_flags & ACPI_PARSE_MODE_MASK) ==
-			      ACPI_PARSE_EXECUTE) && (status == AE_NOT_FOUND)
-			     && (walk_state->op->common.aml_opcode !=
-				 AML_COND_REF_OF_OP))
-			    || (status != AE_NOT_FOUND)) {
-				ACPI_REPORT_NSERROR(path, status);
-
-				acpi_os_printf
-				    ("search_node %p start_node %p return_node %p\n",
-				     scope_info.scope.node,
-				     parser_state->start_node, node);
-
-			} else {
-				/*
-				 * We got a NOT_FOUND during table load or we encountered
-				 * a cond_ref_of(x) where the target does not exist.
-				 * Either case is ok
-				 */
-				status = AE_OK;
-			}
-		}
+	scope_info.scope.node = NULL;
+	node = parser_state->start_node;
+	if (node) {
+		scope_info.scope.node = node;
 	}
 
 	/*
-	 * Regardless of success/failure above,
-	 * Just initialize the Op with the pathname.
+	 * Lookup the name in the internal namespace. We don't want to add
+	 * anything new to the namespace here, however, so we use MODE_EXECUTE.
+	 * Allow searching of the parent tree, but don't open a new scope -
+	 * we just want to lookup the object (must be mode EXECUTE to perform
+	 * the upsearch)
 	 */
-	acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
-	arg->common.value.name = path;
+	status =
+	    acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+			   ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
+			   NULL, &node);
 
+	/*
+	 * If this name is a control method invocation, we must
+	 * setup the method call
+	 */
+	if (ACPI_SUCCESS(status) &&
+	    possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
+		/* This name is actually a control method invocation */
+
+		method_desc = acpi_ns_get_attached_object(node);
+		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+				  "Control Method - %p Desc %p Path=%p\n", node,
+				  method_desc, path));
+
+		name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
+		if (!name_op) {
+			return_ACPI_STATUS(AE_NO_MEMORY);
+		}
+
+		/* Change Arg into a METHOD CALL and attach name to it */
+
+		acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
+		name_op->common.value.name = path;
+
+		/* Point METHODCALL/NAME to the METHOD Node */
+
+		name_op->common.node = node;
+		acpi_ps_append_arg(arg, name_op);
+
+		if (!method_desc) {
+			ACPI_ERROR((AE_INFO,
+				    "Control Method %p has no attached object",
+				    node));
+			return_ACPI_STATUS(AE_AML_INTERNAL);
+		}
+
+		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+				  "Control Method - %p Args %X\n",
+				  node, method_desc->method.param_count));
+
+		/* Get the number of arguments to expect */
+
+		walk_state->arg_count = method_desc->method.param_count;
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	/*
+	 * Special handling if the name was not found during the lookup -
+	 * some not_found cases are allowed
+	 */
+	if (status == AE_NOT_FOUND) {
+		/* 1) not_found is ok during load pass 1/2 (allow forward references) */
+
+		if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) !=
+		    ACPI_PARSE_EXECUTE) {
+			status = AE_OK;
+		}
+
+		/* 2) not_found during a cond_ref_of(x) is ok by definition */
+
+		else if (walk_state->op->common.aml_opcode ==
+			 AML_COND_REF_OF_OP) {
+			status = AE_OK;
+		}
+
+		/*
+		 * 3) not_found while building a Package is ok at this point, we
+		 * may flag as an error later if slack mode is not enabled.
+		 * (Some ASL code depends on allowing this behavior)
+		 */
+		else if ((arg->common.parent) &&
+			 ((arg->common.parent->common.aml_opcode ==
+			   AML_PACKAGE_OP)
+			  || (arg->common.parent->common.aml_opcode ==
+			      AML_VAR_PACKAGE_OP))) {
+			status = AE_OK;
+		}
+	}
+
+	/* Final exception check (may have been changed from code above) */
+
+	if (ACPI_FAILURE(status)) {
+		ACPI_ERROR_NAMESPACE(path, status);
+
+		if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
+		    ACPI_PARSE_EXECUTE) {
+			/* Report a control method execution error */
+
+			status = acpi_ds_method_error(status, walk_state);
+		}
+	}
+
+	/* Save the namepath */
+
+	arg->common.value.name = path;
 	return_ACPI_STATUS(status);
 }
 
@@ -382,59 +384,63 @@
 acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
 			    u32 arg_type, union acpi_parse_object *arg)
 {
+	u32 length;
+	u16 opcode;
+	u8 *aml = parser_state->aml;
 
 	ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type);
 
 	switch (arg_type) {
 	case ARGP_BYTEDATA:
 
-		acpi_ps_init_op(arg, AML_BYTE_OP);
-		arg->common.value.integer = (u32) ACPI_GET8(parser_state->aml);
-		parser_state->aml++;
+		/* Get 1 byte from the AML stream */
+
+		opcode = AML_BYTE_OP;
+		arg->common.value.integer = (acpi_integer) * aml;
+		length = 1;
 		break;
 
 	case ARGP_WORDDATA:
 
-		acpi_ps_init_op(arg, AML_WORD_OP);
-
 		/* Get 2 bytes from the AML stream */
 
-		ACPI_MOVE_16_TO_32(&arg->common.value.integer,
-				   parser_state->aml);
-		parser_state->aml += 2;
+		opcode = AML_WORD_OP;
+		ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml);
+		length = 2;
 		break;
 
 	case ARGP_DWORDDATA:
 
-		acpi_ps_init_op(arg, AML_DWORD_OP);
-
 		/* Get 4 bytes from the AML stream */
 
-		ACPI_MOVE_32_TO_32(&arg->common.value.integer,
-				   parser_state->aml);
-		parser_state->aml += 4;
+		opcode = AML_DWORD_OP;
+		ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml);
+		length = 4;
 		break;
 
 	case ARGP_QWORDDATA:
 
-		acpi_ps_init_op(arg, AML_QWORD_OP);
-
 		/* Get 8 bytes from the AML stream */
 
-		ACPI_MOVE_64_TO_64(&arg->common.value.integer,
-				   parser_state->aml);
-		parser_state->aml += 8;
+		opcode = AML_QWORD_OP;
+		ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml);
+		length = 8;
 		break;
 
 	case ARGP_CHARLIST:
 
-		acpi_ps_init_op(arg, AML_STRING_OP);
-		arg->common.value.string = (char *)parser_state->aml;
+		/* Get a pointer to the string, point past the string */
 
-		while (ACPI_GET8(parser_state->aml) != '\0') {
-			parser_state->aml++;
+		opcode = AML_STRING_OP;
+		arg->common.value.string = ACPI_CAST_PTR(char, aml);
+
+		/* Find the null terminator */
+
+		length = 0;
+		while (aml[length]) {
+			length++;
 		}
-		parser_state->aml++;
+		length++;
 		break;
 
 	case ARGP_NAME:
@@ -443,14 +449,16 @@
 		acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
 		arg->common.value.name =
 		    acpi_ps_get_next_namestring(parser_state);
-		break;
+		return_VOID;
 
 	default:
 
-		ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type));
-		break;
+		ACPI_ERROR((AE_INFO, "Invalid arg_type %X", arg_type));
+		return_VOID;
 	}
 
+	acpi_ps_init_op(arg, opcode);
+	parser_state->aml += length;
 	return_VOID;
 }
 
@@ -540,7 +548,7 @@
 		 * access_type is first operand, access_attribute is second
 		 */
 		field->common.value.integer =
-		    (ACPI_GET8(parser_state->aml) << 8);
+		    (((u32) ACPI_GET8(parser_state->aml) << 8));
 		parser_state->aml++;
 		field->common.value.integer |= ACPI_GET8(parser_state->aml);
 		parser_state->aml++;
@@ -703,7 +711,7 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("Invalid arg_type: %X\n", arg_type));
+		ACPI_ERROR((AE_INFO, "Invalid arg_type: %X", arg_type));
 		status = AE_AML_OPERAND_TYPE;
 		break;
 	}
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
index 088d339..00b072e 100644
--- a/drivers/acpi/parser/psloop.c
+++ b/drivers/acpi/parser/psloop.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -123,16 +123,12 @@
 				    && ((status & AE_CODE_MASK) !=
 					AE_CODE_CONTROL)) {
 					if (status == AE_AML_NO_RETURN_VALUE) {
-						ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-								  "Invoked method did not return a value, %s\n",
-								  acpi_format_exception
-								  (status)));
+						ACPI_EXCEPTION((AE_INFO, status,
+								"Invoked method did not return a value"));
 
 					}
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "get_predicate Failed, %s\n",
-							  acpi_format_exception
-							  (status)));
+					ACPI_EXCEPTION((AE_INFO, status,
+							"get_predicate Failed"));
 					return_ACPI_STATUS(status);
 				}
 
@@ -190,11 +186,11 @@
 
 				/* The opcode is unrecognized.  Just skip unknown opcodes */
 
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
-						  walk_state->opcode,
-						  parser_state->aml,
-						  walk_state->aml_offset));
+				ACPI_ERROR((AE_INFO,
+					    "Found unknown opcode %X at AML address %p offset %X, ignoring",
+					    walk_state->opcode,
+					    parser_state->aml,
+					    walk_state->aml_offset));
 
 				ACPI_DUMP_BUFFER(parser_state->aml, 128);
 
@@ -281,10 +277,8 @@
 				    walk_state->descending_callback(walk_state,
 								    &op);
 				if (ACPI_FAILURE(status)) {
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "During name lookup/catalog, %s\n",
-							  acpi_format_exception
-							  (status)));
+					ACPI_EXCEPTION((AE_INFO, status,
+							"During name lookup/catalog"));
 					goto close_this_op;
 				}
 
@@ -704,6 +698,15 @@
 				acpi_ps_pop_scope(parser_state, &op,
 						  &walk_state->arg_types,
 						  &walk_state->arg_count);
+
+				if (op->common.aml_opcode != AML_WHILE_OP) {
+					status2 =
+					    acpi_ds_result_stack_pop
+					    (walk_state);
+					if (ACPI_FAILURE(status2)) {
+						return_ACPI_STATUS(status2);
+					}
+				}
 			}
 
 			/* Close this iteration of the While loop */
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 229ae86..11d6351 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -747,7 +747,7 @@
 
 	/* Unknown AML opcode */
 
-	ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 			  "Unknown AML opcode [%4.4X]\n", opcode));
 
 	return (&acpi_gbl_aml_op_info[_UNK]);
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index 76d4d64..a9f3229 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -333,7 +333,6 @@
 
 	switch (callback_status) {
 	case AE_CTRL_TERMINATE:
-
 		/*
 		 * A control method was terminated via a RETURN statement.
 		 * The walk of this method is complete.
@@ -346,13 +345,19 @@
 
 		parser_state->aml = walk_state->aml_last_while;
 		walk_state->control_state->common.value = FALSE;
-		status = AE_CTRL_BREAK;
+		status = acpi_ds_result_stack_pop(walk_state);
+		if (ACPI_SUCCESS(status)) {
+			status = AE_CTRL_BREAK;
+		}
 		break;
 
 	case AE_CTRL_CONTINUE:
 
 		parser_state->aml = walk_state->aml_last_while;
-		status = AE_CTRL_CONTINUE;
+		status = acpi_ds_result_stack_pop(walk_state);
+		if (ACPI_SUCCESS(status)) {
+			status = AE_CTRL_CONTINUE;
+		}
 		break;
 
 	case AE_CTRL_PENDING:
@@ -369,16 +374,18 @@
 #endif
 
 	case AE_CTRL_TRUE:
-
 		/*
 		 * Predicate of an IF was true, and we are at the matching ELSE.
 		 * Just close out this package
 		 */
 		parser_state->aml = acpi_ps_get_next_package_end(parser_state);
+		status = acpi_ds_result_stack_pop(walk_state);
+		if (ACPI_SUCCESS(status)) {
+			status = AE_CTRL_PENDING;
+		}
 		break;
 
 	case AE_CTRL_FALSE:
-
 		/*
 		 * Either an IF/WHILE Predicate was false or we encountered a BREAK
 		 * opcode.  In both cases, we do not execute the rest of the
@@ -503,22 +510,23 @@
 		} else if (status == AE_CTRL_TERMINATE) {
 			status = AE_OK;
 		} else if ((status != AE_OK) && (walk_state->method_desc)) {
-			ACPI_REPORT_METHOD_ERROR("Method execution failed",
-						 walk_state->method_node, NULL,
-						 status);
+			/* Either the method parse or actual execution failed */
 
-			/* Ensure proper cleanup */
-
-			walk_state->parse_flags |= ACPI_PARSE_EXECUTE;
+			ACPI_ERROR_METHOD("Method parse/execution failed",
+					  walk_state->method_node, NULL,
+					  status);
 
 			/* Check for possible multi-thread reentrancy problem */
 
 			if ((status == AE_ALREADY_EXISTS) &&
 			    (!walk_state->method_desc->method.semaphore)) {
 				/*
-				 * This method is marked not_serialized, but it tried to create
+				 * Method tried to create an object twice. The probable cause is
+				 * that the method cannot handle reentrancy.
+				 *
+				 * The method is marked not_serialized, but it tried to create
 				 * a named object, causing the second thread entrance to fail.
-				 * We will workaround this by marking the method permanently
+				 * Workaround this problem by marking the method permanently
 				 * as Serialized.
 				 */
 				walk_state->method_desc->method.method_flags |=
@@ -536,15 +544,23 @@
 		acpi_ds_scope_stack_clear(walk_state);
 
 		/*
-		 * If we just returned from the execution of a control method,
-		 * there's lots of cleanup to do
+		 * If we just returned from the execution of a control method or if we
+		 * encountered an error during the method parse phase, there's lots of
+		 * cleanup to do
 		 */
-		if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
-		    ACPI_PARSE_EXECUTE) {
+		if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
+		     ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) {
 			if (walk_state->method_desc) {
 				/* Decrement the thread count on the method parse tree */
 
-				walk_state->method_desc->method.thread_count--;
+				if (walk_state->method_desc->method.
+				    thread_count) {
+					walk_state->method_desc->method.
+					    thread_count--;
+				} else {
+					ACPI_ERROR((AE_INFO,
+						    "Invalid zero thread count in method"));
+				}
 			}
 
 			acpi_ds_terminate_control_method(walk_state);
@@ -553,7 +569,6 @@
 		/* Delete this walk state and all linked control states */
 
 		acpi_ps_cleanup_scope(&walk_state->parser_state);
-
 		previous_walk_state = walk_state;
 
 		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c
index 1c953b6..bc6047c 100644
--- a/drivers/acpi/parser/psscope.c
+++ b/drivers/acpi/parser/psscope.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c
index f0e7558..dd6f167 100644
--- a/drivers/acpi/parser/pstree.c
+++ b/drivers/acpi/parser/pstree.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -132,7 +132,8 @@
 	if (op_info->class == AML_CLASS_UNKNOWN) {
 		/* Invalid opcode */
 
-		ACPI_REPORT_ERROR(("ps_append_arg: Invalid AML Opcode: 0x%2.2X\n", op->common.aml_opcode));
+		ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X",
+			    op->common.aml_opcode));
 		return;
 	}
 
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
index 2075efb..3e07cb9 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/parser/psutils.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
index 08f2321..06f05bf 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/parser/pswalk.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index 4dcbd44..2dd48cb 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/parser/psxface.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,10 @@
 ACPI_MODULE_NAME("psxface")
 
 /* Local Prototypes */
+static void acpi_ps_start_trace(struct acpi_parameter_info *info);
+
+static void acpi_ps_stop_trace(struct acpi_parameter_info *info);
+
 static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info);
 
 static void
@@ -57,6 +61,136 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_debug_trace
+ *
+ * PARAMETERS:  method_name     - Valid ACPI name string
+ *              debug_level     - Optional level mask. 0 to use default
+ *              debug_layer     - Optional layer mask. 0 to use default
+ *              Flags           - bit 1: one shot(1) or persistent(0)
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: External interface to enable debug tracing during control
+ *              method execution
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags)
+{
+	acpi_status status;
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	/* TBDs: Validate name, allow full path or just nameseg */
+
+	acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name);
+	acpi_gbl_trace_flags = flags;
+
+	if (debug_level) {
+		acpi_gbl_trace_dbg_level = debug_level;
+	}
+	if (debug_layer) {
+		acpi_gbl_trace_dbg_layer = debug_layer;
+	}
+
+	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ps_start_trace
+ *
+ * PARAMETERS:  Info        - Method info struct
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Start control method execution trace
+ *
+ ******************************************************************************/
+
+static void acpi_ps_start_trace(struct acpi_parameter_info *info)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_ENTRY();
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		return;
+	}
+
+	if ((!acpi_gbl_trace_method_name) ||
+	    (acpi_gbl_trace_method_name != info->node->name.integer)) {
+		goto exit;
+	}
+
+	acpi_gbl_original_dbg_level = acpi_dbg_level;
+	acpi_gbl_original_dbg_layer = acpi_dbg_layer;
+
+	acpi_dbg_level = 0x00FFFFFF;
+	acpi_dbg_layer = ACPI_UINT32_MAX;
+
+	if (acpi_gbl_trace_dbg_level) {
+		acpi_dbg_level = acpi_gbl_trace_dbg_level;
+	}
+	if (acpi_gbl_trace_dbg_layer) {
+		acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
+	}
+
+      exit:
+	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ps_stop_trace
+ *
+ * PARAMETERS:  Info        - Method info struct
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Stop control method execution trace
+ *
+ ******************************************************************************/
+
+static void acpi_ps_stop_trace(struct acpi_parameter_info *info)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_ENTRY();
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		return;
+	}
+
+	if ((!acpi_gbl_trace_method_name) ||
+	    (acpi_gbl_trace_method_name != info->node->name.integer)) {
+		goto exit;
+	}
+
+	/* Disable further tracing if type is one-shot */
+
+	if (acpi_gbl_trace_flags & 1) {
+		acpi_gbl_trace_method_name = 0;
+		acpi_gbl_trace_dbg_level = 0;
+		acpi_gbl_trace_dbg_layer = 0;
+	}
+
+	acpi_dbg_level = acpi_gbl_original_dbg_level;
+	acpi_dbg_layer = acpi_gbl_original_dbg_layer;
+
+      exit:
+	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ps_execute_method
  *
  * PARAMETERS:  Info            - Method info block, contains:
@@ -104,6 +238,10 @@
 	 */
 	acpi_ps_update_parameter_list(info, REF_INCREMENT);
 
+	/* Begin tracing if requested */
+
+	acpi_ps_start_trace(info);
+
 	/*
 	 * 1) Perform the first pass parse of the method to enter any
 	 *    named objects that it creates into the namespace
@@ -129,6 +267,10 @@
 	status = acpi_ps_execute_pass(info);
 
       cleanup:
+	/* End optional tracing */
+
+	acpi_ps_stop_trace(info);
+
 	/* Take away the extra reference that we gave the parameters above */
 
 	acpi_ps_update_parameter_list(info, REF_DECREMENT);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index e567c03..65aee79 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -258,7 +258,7 @@
 
 static int
 acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
-		      int *edge_level, int *active_high_low, char **link)
+		      int *triggering, int *polarity, char **link)
 {
 	int irq;
 
@@ -266,8 +266,8 @@
 
 	if (entry->link.handle) {
 		irq = acpi_pci_link_allocate_irq(entry->link.handle,
-						 entry->link.index, edge_level,
-						 active_high_low, link);
+						 entry->link.index, triggering,
+						 polarity, link);
 		if (irq < 0) {
 			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
 					  "Invalid IRQ link routing entry\n"));
@@ -275,8 +275,8 @@
 		}
 	} else {
 		irq = entry->link.index;
-		*edge_level = ACPI_LEVEL_SENSITIVE;
-		*active_high_low = ACPI_ACTIVE_LOW;
+		*triggering = ACPI_LEVEL_SENSITIVE;
+		*polarity = ACPI_ACTIVE_LOW;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
@@ -285,7 +285,7 @@
 
 static int
 acpi_pci_free_irq(struct acpi_prt_entry *entry,
-		  int *edge_level, int *active_high_low, char **link)
+		  int *triggering, int *polarity, char **link)
 {
 	int irq;
 
@@ -307,8 +307,8 @@
 acpi_pci_irq_lookup(struct pci_bus *bus,
 		    int device,
 		    int pin,
-		    int *edge_level,
-		    int *active_high_low, char **link, irq_lookup_func func)
+		    int *triggering,
+		    int *polarity, char **link, irq_lookup_func func)
 {
 	struct acpi_prt_entry *entry = NULL;
 	int segment = pci_domain_nr(bus);
@@ -327,7 +327,7 @@
 		return_VALUE(-1);
 	}
 
-	ret = func(entry, edge_level, active_high_low, link);
+	ret = func(entry, triggering, polarity, link);
 	return_VALUE(ret);
 }
 
@@ -339,8 +339,8 @@
 static int
 acpi_pci_irq_derive(struct pci_dev *dev,
 		    int pin,
-		    int *edge_level,
-		    int *active_high_low, char **link, irq_lookup_func func)
+		    int *triggering,
+		    int *polarity, char **link, irq_lookup_func func)
 {
 	struct pci_dev *bridge = dev;
 	int irq = -1;
@@ -374,7 +374,7 @@
 		}
 
 		irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
-					  pin, edge_level, active_high_low,
+					  pin, triggering, polarity,
 					  link, func);
 	}
 
@@ -401,8 +401,8 @@
 {
 	int irq = 0;
 	u8 pin = 0;
-	int edge_level = ACPI_LEVEL_SENSITIVE;
-	int active_high_low = ACPI_ACTIVE_LOW;
+	int triggering = ACPI_LEVEL_SENSITIVE;
+	int polarity = ACPI_ACTIVE_LOW;
 	char *link = NULL;
 	int rc;
 
@@ -431,7 +431,7 @@
 	 * values override any BIOS-assigned IRQs set during boot.
 	 */
 	irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
-				  &edge_level, &active_high_low, &link,
+				  &triggering, &polarity, &link,
 				  acpi_pci_allocate_irq);
 
 	/*
@@ -439,8 +439,8 @@
 	 * device's parent bridge.
 	 */
 	if (irq < 0)
-		irq = acpi_pci_irq_derive(dev, pin, &edge_level,
-					  &active_high_low, &link,
+		irq = acpi_pci_irq_derive(dev, pin, &triggering,
+					  &polarity, &link,
 					  acpi_pci_allocate_irq);
 
 	/*
@@ -462,7 +462,7 @@
 		}
 	}
 
-	rc = acpi_register_gsi(irq, edge_level, active_high_low);
+	rc = acpi_register_gsi(irq, triggering, polarity);
 	if (rc < 0) {
 		printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: failed "
 		       "to register GSI\n", pci_name(dev), ('A' + pin));
@@ -477,8 +477,8 @@
 		printk("Link [%s] -> ", link);
 
 	printk("GSI %u (%s, %s) -> IRQ %d\n", irq,
-	       (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
-	       (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+	       (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
+	       (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
 	return_VALUE(0);
 }
@@ -494,8 +494,8 @@
 {
 	int gsi = 0;
 	u8 pin = 0;
-	int edge_level = ACPI_LEVEL_SENSITIVE;
-	int active_high_low = ACPI_ACTIVE_LOW;
+	int triggering = ACPI_LEVEL_SENSITIVE;
+	int polarity = ACPI_ACTIVE_LOW;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_disable");
 
@@ -511,7 +511,7 @@
 	 * First we check the PCI IRQ routing table (PRT) for an IRQ.
 	 */
 	gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
-				  &edge_level, &active_high_low, NULL,
+				  &triggering, &polarity, NULL,
 				  acpi_pci_free_irq);
 	/*
 	 * If no PRT entry was found, we'll try to derive an IRQ from the
@@ -519,7 +519,7 @@
 	 */
 	if (gsi < 0)
 		gsi = acpi_pci_irq_derive(dev, pin,
-					  &edge_level, &active_high_low, NULL,
+					  &triggering, &polarity, NULL,
 					  acpi_pci_free_irq);
 	if (gsi < 0)
 		return_VOID;
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 78927c0..07bc6df 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -70,8 +70,8 @@
  */
 struct acpi_pci_link_irq {
 	u8 active;		/* Current IRQ */
-	u8 edge_level;		/* All IRQs */
-	u8 active_high_low;	/* All IRQs */
+	u8 triggering;		/* All IRQs */
+	u8 polarity;	/* All IRQs */
 	u8 resource_type;
 	u8 possible_count;
 	u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
@@ -108,19 +108,19 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible");
 
-	switch (resource->id) {
-	case ACPI_RSTYPE_START_DPF:
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 		return_ACPI_STATUS(AE_OK);
-	case ACPI_RSTYPE_IRQ:
+	case ACPI_RESOURCE_TYPE_IRQ:
 		{
 			struct acpi_resource_irq *p = &resource->data.irq;
-			if (!p || !p->number_of_interrupts) {
+			if (!p || !p->interrupt_count) {
 				ACPI_DEBUG_PRINT((ACPI_DB_WARN,
 						  "Blank IRQ resource\n"));
 				return_ACPI_STATUS(AE_OK);
 			}
 			for (i = 0;
-			     (i < p->number_of_interrupts
+			     (i < p->interrupt_count
 			      && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
 				if (!p->interrupts[i]) {
 					ACPI_DEBUG_PRINT((ACPI_DB_WARN,
@@ -131,22 +131,22 @@
 				link->irq.possible[i] = p->interrupts[i];
 				link->irq.possible_count++;
 			}
-			link->irq.edge_level = p->edge_level;
-			link->irq.active_high_low = p->active_high_low;
-			link->irq.resource_type = ACPI_RSTYPE_IRQ;
+			link->irq.triggering = p->triggering;
+			link->irq.polarity = p->polarity;
+			link->irq.resource_type = ACPI_RESOURCE_TYPE_IRQ;
 			break;
 		}
-	case ACPI_RSTYPE_EXT_IRQ:
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		{
-			struct acpi_resource_ext_irq *p =
+			struct acpi_resource_extended_irq *p =
 			    &resource->data.extended_irq;
-			if (!p || !p->number_of_interrupts) {
+			if (!p || !p->interrupt_count) {
 				ACPI_DEBUG_PRINT((ACPI_DB_WARN,
 						  "Blank EXT IRQ resource\n"));
 				return_ACPI_STATUS(AE_OK);
 			}
 			for (i = 0;
-			     (i < p->number_of_interrupts
+			     (i < p->interrupt_count
 			      && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
 				if (!p->interrupts[i]) {
 					ACPI_DEBUG_PRINT((ACPI_DB_WARN,
@@ -157,9 +157,9 @@
 				link->irq.possible[i] = p->interrupts[i];
 				link->irq.possible_count++;
 			}
-			link->irq.edge_level = p->edge_level;
-			link->irq.active_high_low = p->active_high_low;
-			link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
+			link->irq.triggering = p->triggering;
+			link->irq.polarity = p->polarity;
+			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
 			break;
 		}
 	default:
@@ -201,11 +201,11 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_link_check_current");
 
-	switch (resource->id) {
-	case ACPI_RSTYPE_IRQ:
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_IRQ:
 		{
 			struct acpi_resource_irq *p = &resource->data.irq;
-			if (!p || !p->number_of_interrupts) {
+			if (!p || !p->interrupt_count) {
 				/*
 				 * IRQ descriptors may have no IRQ# bits set,
 				 * particularly those those w/ _STA disabled
@@ -217,11 +217,11 @@
 			*irq = p->interrupts[0];
 			break;
 		}
-	case ACPI_RSTYPE_EXT_IRQ:
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		{
-			struct acpi_resource_ext_irq *p =
+			struct acpi_resource_extended_irq *p =
 			    &resource->data.extended_irq;
-			if (!p || !p->number_of_interrupts) {
+			if (!p || !p->interrupt_count) {
 				/*
 				 * extended IRQ descriptors must
 				 * return at least 1 IRQ
@@ -233,8 +233,10 @@
 			*irq = p->interrupts[0];
 			break;
 		}
+		break;
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource isn't an IRQ\n"));
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource %d isn't an IRQ\n", resource->type));
+	case ACPI_RESOURCE_TYPE_END_TAG:
 		return_ACPI_STATUS(AE_OK);
 	}
 	return_ACPI_STATUS(AE_CTRL_TERMINATE);
@@ -325,36 +327,36 @@
 	buffer.pointer = resource;
 
 	switch (link->irq.resource_type) {
-	case ACPI_RSTYPE_IRQ:
-		resource->res.id = ACPI_RSTYPE_IRQ;
+	case ACPI_RESOURCE_TYPE_IRQ:
+		resource->res.type = ACPI_RESOURCE_TYPE_IRQ;
 		resource->res.length = sizeof(struct acpi_resource);
-		resource->res.data.irq.edge_level = link->irq.edge_level;
-		resource->res.data.irq.active_high_low =
-		    link->irq.active_high_low;
-		if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
-			resource->res.data.irq.shared_exclusive =
+		resource->res.data.irq.triggering = link->irq.triggering;
+		resource->res.data.irq.polarity =
+		    link->irq.polarity;
+		if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
+			resource->res.data.irq.sharable =
 			    ACPI_EXCLUSIVE;
 		else
-			resource->res.data.irq.shared_exclusive = ACPI_SHARED;
-		resource->res.data.irq.number_of_interrupts = 1;
+			resource->res.data.irq.sharable = ACPI_SHARED;
+		resource->res.data.irq.interrupt_count = 1;
 		resource->res.data.irq.interrupts[0] = irq;
 		break;
 
-	case ACPI_RSTYPE_EXT_IRQ:
-		resource->res.id = ACPI_RSTYPE_EXT_IRQ;
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+		resource->res.type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
 		resource->res.length = sizeof(struct acpi_resource);
 		resource->res.data.extended_irq.producer_consumer =
 		    ACPI_CONSUMER;
-		resource->res.data.extended_irq.edge_level =
-		    link->irq.edge_level;
-		resource->res.data.extended_irq.active_high_low =
-		    link->irq.active_high_low;
-		if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
-			resource->res.data.irq.shared_exclusive =
+		resource->res.data.extended_irq.triggering =
+		    link->irq.triggering;
+		resource->res.data.extended_irq.polarity =
+		    link->irq.polarity;
+		if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
+			resource->res.data.irq.sharable =
 			    ACPI_EXCLUSIVE;
 		else
-			resource->res.data.irq.shared_exclusive = ACPI_SHARED;
-		resource->res.data.extended_irq.number_of_interrupts = 1;
+			resource->res.data.irq.sharable = ACPI_SHARED;
+		resource->res.data.extended_irq.interrupt_count = 1;
 		resource->res.data.extended_irq.interrupts[0] = irq;
 		/* ignore resource_source, it's optional */
 		break;
@@ -364,7 +366,7 @@
 		goto end;
 
 	}
-	resource->end.id = ACPI_RSTYPE_END_TAG;
+	resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
 
 	/* Attempt to set the resource */
 	status = acpi_set_current_resources(link->handle, &buffer);
@@ -613,7 +615,7 @@
 int
 acpi_pci_link_allocate_irq(acpi_handle handle,
 			   int index,
-			   int *edge_level, int *active_high_low, char **name)
+			   int *triggering, int *polarity, char **name)
 {
 	int result = 0;
 	struct acpi_device *device = NULL;
@@ -653,10 +655,10 @@
 	link->refcnt++;
 	up(&acpi_link_lock);
 
-	if (edge_level)
-		*edge_level = link->irq.edge_level;
-	if (active_high_low)
-		*active_high_low = link->irq.active_high_low;
+	if (triggering)
+		*triggering = link->irq.triggering;
+	if (polarity)
+		*polarity = link->irq.polarity;
 	if (name)
 		*name = acpi_device_bid(link->device);
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 0fd9988..4c313ea 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -122,15 +122,15 @@
 	int *busnr = (int *)data;
 	struct acpi_resource_address64 address;
 
-	if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
-	    resource->id != ACPI_RSTYPE_ADDRESS32 &&
-	    resource->id != ACPI_RSTYPE_ADDRESS64)
+	if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
+	    resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 &&
+	    resource->type != ACPI_RESOURCE_TYPE_ADDRESS64)
 		return AE_OK;
 
 	acpi_resource_to_address64(resource, &address);
 	if ((address.address_length > 0) &&
 	    (address.resource_type == ACPI_BUS_NUMBER_RANGE))
-		*busnr = address.min_address_range;
+		*busnr = address.minimum;
 
 	return AE_OK;
 }
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 1278aca..99a3a28 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -253,31 +253,21 @@
  * _PDC is required for a BIOS-OS handshake for most of the newer
  * ACPI processor features.
  */
-
-int acpi_processor_set_pdc(struct acpi_processor *pr,
-			   struct acpi_object_list *pdc_in)
+static int acpi_processor_set_pdc(struct acpi_processor *pr)
 {
+	struct acpi_object_list *pdc_in = pr->pdc;
 	acpi_status status = AE_OK;
-	u32 arg0_buf[3];
-	union acpi_object arg0 = { ACPI_TYPE_BUFFER };
-	struct acpi_object_list no_object = { 1, &arg0 };
-	struct acpi_object_list *pdc;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
 
-	arg0.buffer.length = 12;
-	arg0.buffer.pointer = (u8 *) arg0_buf;
-	arg0_buf[0] = ACPI_PDC_REVISION_ID;
-	arg0_buf[1] = 0;
-	arg0_buf[2] = 0;
+	if (!pdc_in)
+		return_VALUE(status);
 
-	pdc = (pdc_in) ? pdc_in : &no_object;
+	status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);
 
-	status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
-
-	if ((ACPI_FAILURE(status)) && (pdc_in))
+	if (ACPI_FAILURE(status))
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Error evaluating _PDC, using legacy perf. control...\n"));
+		    "Could not evaluate _PDC, using legacy perf. control...\n"));
 
 	return_VALUE(status);
 }
@@ -357,7 +347,6 @@
 				  ACPI_PROCESSOR_FILE_THROTTLING));
 	else {
 		entry->proc_fops = &acpi_processor_throttling_fops;
-		entry->proc_fops->write = acpi_processor_write_throttling;
 		entry->data = acpi_driver_data(device);
 		entry->owner = THIS_MODULE;
 	}
@@ -372,7 +361,6 @@
 				  ACPI_PROCESSOR_FILE_LIMIT));
 	else {
 		entry->proc_fops = &acpi_processor_limit_fops;
-		entry->proc_fops->write = acpi_processor_write_limit;
 		entry->data = acpi_driver_data(device);
 		entry->owner = THIS_MODULE;
 	}
@@ -589,6 +577,10 @@
 				  "Error installing device notify handler\n"));
 	}
 
+	/* _PDC call should be done before doing anything else (if reqd.). */
+	arch_acpi_processor_init_pdc(pr);
+	acpi_processor_set_pdc(pr);
+
 	acpi_processor_power_init(pr, device);
 
 	if (pr->flags.throttling) {
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index cc04933..eb730a8 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -94,23 +94,60 @@
 	return 0;
 }
 
-static struct dmi_system_id __initdata processor_power_dmi_table[] = {
-	{set_max_cstate, "IBM ThinkPad R40e", {
-					       DMI_MATCH(DMI_BIOS_VENDOR,
-							 "IBM"),
-					       DMI_MATCH(DMI_BIOS_VERSION,
-							 "1SET60WW")},
-	 (void *)1},
-	{set_max_cstate, "Medion 41700", {
-					  DMI_MATCH(DMI_BIOS_VENDOR,
-						    "Phoenix Technologies LTD"),
-					  DMI_MATCH(DMI_BIOS_VERSION,
-						    "R01-A1J")}, (void *)1},
-	{set_max_cstate, "Clevo 5600D", {
-					 DMI_MATCH(DMI_BIOS_VENDOR,
-						   "Phoenix Technologies LTD"),
-					 DMI_MATCH(DMI_BIOS_VERSION,
-						   "SHE845M0.86C.0013.D.0302131307")},
+/* Actually this shouldn't be __cpuinitdata, would be better to fix the
+   callers to only run once -AK */
+static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = {
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET43WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET45WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET47WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET50WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET52WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET55WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET56WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET59WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET61WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET62WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET64WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET65WW") }, (void*)1},
+	{ set_max_cstate, "IBM ThinkPad R40e", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"1SET68WW") }, (void*)1},
+	{ set_max_cstate, "Medion 41700", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J")}, (void *)1},
+	{ set_max_cstate, "Clevo 5600D", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+	  DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")},
 	 (void *)2},
 	{},
 };
@@ -550,18 +587,10 @@
 	if (!pr->pblk)
 		return_VALUE(-ENODEV);
 
-	memset(pr->power.states, 0, sizeof(pr->power.states));
-
 	/* if info is obtained from pblk/fadt, type equals state */
-	pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
 	pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2;
 	pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3;
 
-	/* the C0 state only exists as a filler in our array,
-	 * and all processors need to support C1 */
-	pr->power.states[ACPI_STATE_C0].valid = 1;
-	pr->power.states[ACPI_STATE_C1].valid = 1;
-
 #ifndef CONFIG_HOTPLUG_CPU
 	/*
 	 * Check for P_LVL2_UP flag before entering C2 and above on
@@ -591,12 +620,11 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1");
 
+	/* Zero initialize all the C-states info. */
 	memset(pr->power.states, 0, sizeof(pr->power.states));
 
-	/* if info is obtained from pblk/fadt, type equals state */
+	/* set the first C-State to C1 */
 	pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
-	pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2;
-	pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3;
 
 	/* the C0 state only exists as a filler in our array,
 	 * and all processors need to support C1 */
@@ -610,6 +638,7 @@
 {
 	acpi_status status = 0;
 	acpi_integer count;
+	int current_count;
 	int i;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *cst;
@@ -619,10 +648,12 @@
 	if (nocst)
 		return_VALUE(-ENODEV);
 
-	pr->power.count = 0;
-	for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
-		memset(&(pr->power.states[i]), 0,
-		       sizeof(struct acpi_processor_cx));
+	current_count = 1;
+
+	/* Zero initialize C2 onwards and prepare for fresh CST lookup */
+	for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++)
+		memset(&(pr->power.states[i]), 0, 
+				sizeof(struct acpi_processor_cx));
 
 	status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
 	if (ACPI_FAILURE(status)) {
@@ -650,16 +681,6 @@
 		goto end;
 	}
 
-	/* We support up to ACPI_PROCESSOR_MAX_POWER. */
-	if (count > ACPI_PROCESSOR_MAX_POWER) {
-		printk(KERN_WARNING
-		       "Limiting number of power states to max (%d)\n",
-		       ACPI_PROCESSOR_MAX_POWER);
-		printk(KERN_WARNING
-		       "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
-		count = ACPI_PROCESSOR_MAX_POWER;
-	}
-
 	/* Tell driver that at least _CST is supported. */
 	pr->flags.has_cst = 1;
 
@@ -703,7 +724,7 @@
 		    (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
 			continue;
 
-		if ((cx.type < ACPI_STATE_C1) || (cx.type > ACPI_STATE_C3))
+		if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3))
 			continue;
 
 		obj = (union acpi_object *)&(element->package.elements[2]);
@@ -718,15 +739,28 @@
 
 		cx.power = obj->integer.value;
 
-		(pr->power.count)++;
-		memcpy(&(pr->power.states[pr->power.count]), &cx, sizeof(cx));
+		current_count++;
+		memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
+
+		/*
+		 * We support total ACPI_PROCESSOR_MAX_POWER - 1
+		 * (From 1 through ACPI_PROCESSOR_MAX_POWER - 1)
+		 */
+		if (current_count >= (ACPI_PROCESSOR_MAX_POWER - 1)) {
+			printk(KERN_WARNING
+			       "Limiting number of power states to max (%d)\n",
+			       ACPI_PROCESSOR_MAX_POWER);
+			printk(KERN_WARNING
+			       "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
+			break;
+		}
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n",
-			  pr->power.count));
+			  current_count));
 
 	/* Validate number of power states discovered */
-	if (pr->power.count < 2)
+	if (current_count < 2)
 		status = -EFAULT;
 
       end:
@@ -867,7 +901,7 @@
 		case ACPI_STATE_C3:
 			acpi_processor_power_verify_c3(pr, cx);
 #ifdef ARCH_APICTIMER_STOPS_ON_C3
-			if (c->x86_vendor == X86_VENDOR_INTEL) {
+			if (cx->valid && c->x86_vendor == X86_VENDOR_INTEL) {
 				on_each_cpu(switch_APIC_timer_to_ipi,
 						&mask, 1, 1);
 			}
@@ -892,12 +926,13 @@
 	/* NOTE: the idle thread may not be running while calling
 	 * this function */
 
+	/* Adding C1 state */
+	acpi_processor_get_power_info_default_c1(pr);
 	result = acpi_processor_get_power_info_cst(pr);
 	if (result == -ENODEV)
-		result = acpi_processor_get_power_info_fadt(pr);
+		acpi_processor_get_power_info_fadt(pr);
 
-	if ((result) || (acpi_processor_power_verify(pr) < 2))
-		result = acpi_processor_get_power_info_default_c1(pr);
+	pr->power.count = acpi_processor_power_verify(pr);
 
 	/*
 	 * Set Default Policy
@@ -1066,8 +1101,6 @@
 		}
 	}
 
-	acpi_processor_power_init_pdc(&(pr->power), pr->id);
-	acpi_processor_set_pdc(pr, pr->power.pdc);
 	acpi_processor_get_power_info(pr);
 
 	/*
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 22c7bb6..abbdb37 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -315,8 +315,6 @@
 	if (!pr || !pr->performance || !pr->handle)
 		return_VALUE(-EINVAL);
 
-	acpi_processor_set_pdc(pr, pr->performance->pdc);
-
 	status = acpi_get_handle(pr->handle, "_PCT", &handle);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -520,8 +518,8 @@
 				  "Unable to create '%s' fs entry\n",
 				  ACPI_PROCESSOR_FILE_PERFORMANCE));
 	else {
+		acpi_processor_perf_fops.write = acpi_processor_write_performance;
 		entry->proc_fops = &acpi_processor_perf_fops;
-		entry->proc_fops->write = acpi_processor_write_performance;
 		entry->data = acpi_driver_data(device);
 		entry->owner = THIS_MODULE;
 	}
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index dc9817c..f99ad05 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -348,9 +348,9 @@
 			   PDE(inode)->data);
 }
 
-ssize_t acpi_processor_write_limit(struct file * file,
-				   const char __user * buffer,
-				   size_t count, loff_t * data)
+static ssize_t acpi_processor_write_limit(struct file * file,
+					  const char __user * buffer,
+					  size_t count, loff_t * data)
 {
 	int result = 0;
 	struct seq_file *m = (struct seq_file *)file->private_data;
@@ -394,6 +394,7 @@
 struct file_operations acpi_processor_limit_fops = {
 	.open = acpi_processor_limit_open_fs,
 	.read = seq_read,
+	.write = acpi_processor_write_limit,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 74a52d4..b966549 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -306,9 +306,9 @@
 			   PDE(inode)->data);
 }
 
-ssize_t acpi_processor_write_throttling(struct file * file,
-					const char __user * buffer,
-					size_t count, loff_t * data)
+static ssize_t acpi_processor_write_throttling(struct file * file,
+					       const char __user * buffer,
+					       size_t count, loff_t * data)
 {
 	int result = 0;
 	struct seq_file *m = (struct seq_file *)file->private_data;
@@ -337,6 +337,7 @@
 struct file_operations acpi_processor_throttling_fops = {
 	.open = acpi_processor_throttling_open_fs,
 	.read = seq_read,
+	.write = acpi_processor_write_throttling,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
diff --git a/drivers/acpi/resources/Makefile b/drivers/acpi/resources/Makefile
index 2130b74..8de4f69 100644
--- a/drivers/acpi/resources/Makefile
+++ b/drivers/acpi/resources/Makefile
@@ -2,7 +2,7 @@
 # Makefile for all Linux ACPI interpreter subdirectories
 #
 
-obj-y := rsaddr.o  rscreate.o  rsio.o   rslist.o    rsmisc.o   rsxface.o \
+obj-y := rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \
 	 rscalc.o  rsirq.o  rsmemory.o  rsutils.o
 
 obj-$(ACPI_FUTURE_USAGE) += rsdump.o
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c
index 23b54ba..8fa3213 100644
--- a/drivers/acpi/resources/rsaddr.c
+++ b/drivers/acpi/resources/rsaddr.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,1072 +47,334 @@
 #define _COMPONENT          ACPI_RESOURCES
 ACPI_MODULE_NAME("rsaddr")
 
-/* Local prototypes */
-static void
-acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags);
-
-static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource);
-
-static void
-acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags);
-
-static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource);
-
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_decode_general_flags
- *
- * PARAMETERS:  Resource            - Address resource data struct
- *              Flags               - Actual flag byte
- *
- * RETURN:      Decoded flag bits in resource struct
- *
- * DESCRIPTION: Decode a general flag byte to an address resource struct
+ * acpi_rs_convert_address16 - All WORD (16-bit) address resources
  *
  ******************************************************************************/
+struct acpi_rsconvert_info acpi_rs_convert_address16[5] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS16,
+	 ACPI_RS_SIZE(struct acpi_resource_address16),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address16)},
 
-static void
-acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags)
-{
-	ACPI_FUNCTION_ENTRY();
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS16,
+	 sizeof(struct aml_resource_address16),
+	 0},
 
-	/* Producer / Consumer - flag bit[0] */
+	/* Resource Type, General Flags, and Type-Specific Flags */
 
-	resource->address.producer_consumer = (u32) (flags & 0x01);
-
-	/* Decode (_DEC) - flag bit[1] */
-
-	resource->address.decode = (u32) ((flags >> 1) & 0x01);
-
-	/* Min Address Fixed (_MIF) - flag bit[2] */
-
-	resource->address.min_address_fixed = (u32) ((flags >> 2) & 0x01);
-
-	/* Max Address Fixed (_MAF) - flag bit[3] */
-
-	resource->address.max_address_fixed = (u32) ((flags >> 3) & 0x01);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_encode_general_flags
- *
- * PARAMETERS:  Resource            - Address resource data struct
- *
- * RETURN:      Encoded general flag byte
- *
- * DESCRIPTION: Construct a general flag byte from an address resource struct
- *
- ******************************************************************************/
-
-static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource)
-{
-	u8 flags;
-
-	ACPI_FUNCTION_ENTRY();
-
-	/* Producer / Consumer - flag bit[0] */
-
-	flags = (u8) (resource->address.producer_consumer & 0x01);
-
-	/* Decode (_DEC) - flag bit[1] */
-
-	flags |= (u8) ((resource->address.decode & 0x01) << 1);
-
-	/* Min Address Fixed (_MIF) - flag bit[2] */
-
-	flags |= (u8) ((resource->address.min_address_fixed & 0x01) << 2);
-
-	/* Max Address Fixed (_MAF) - flag bit[3] */
-
-	flags |= (u8) ((resource->address.max_address_fixed & 0x01) << 3);
-
-	return (flags);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_decode_specific_flags
- *
- * PARAMETERS:  Resource            - Address resource data struct
- *              Flags               - Actual flag byte
- *
- * RETURN:      Decoded flag bits in attribute struct
- *
- * DESCRIPTION: Decode a type-specific flag byte to an attribute struct.
- *              Type-specific flags are only defined for the Memory and IO
- *              resource types.
- *
- ******************************************************************************/
-
-static void
-acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags)
-{
-	ACPI_FUNCTION_ENTRY();
-
-	if (resource->address.resource_type == ACPI_MEMORY_RANGE) {
-		/* Write Status (_RW) - flag bit[0] */
-
-		resource->address.attribute.memory.read_write_attribute =
-		    (u16) (flags & 0x01);
-
-		/* Memory Attributes (_MEM) - flag bits[2:1] */
-
-		resource->address.attribute.memory.cache_attribute =
-		    (u16) ((flags >> 1) & 0x03);
-	} else if (resource->address.resource_type == ACPI_IO_RANGE) {
-		/* Ranges (_RNG) - flag bits[1:0] */
-
-		resource->address.attribute.io.range_attribute =
-		    (u16) (flags & 0x03);
-
-		/* Translations (_TTP and _TRS) - flag bits[5:4] */
-
-		resource->address.attribute.io.translation_attribute =
-		    (u16) ((flags >> 4) & 0x03);
-	}
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_encode_specific_flags
- *
- * PARAMETERS:  Resource            - Address resource data struct
- *
- * RETURN:      Encoded type-specific flag byte
- *
- * DESCRIPTION: Construct a type-specific flag byte from an attribute struct.
- *              Type-specific flags are only defined for the Memory and IO
- *              resource types.
- *
- ******************************************************************************/
-
-static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource)
-{
-	u8 flags = 0;
-
-	ACPI_FUNCTION_ENTRY();
-
-	if (resource->address.resource_type == ACPI_MEMORY_RANGE) {
-		/* Write Status (_RW) - flag bit[0] */
-
-		flags = (u8)
-		    (resource->address.attribute.memory.
-		     read_write_attribute & 0x01);
-
-		/* Memory Attributes (_MEM) - flag bits[2:1] */
-
-		flags |= (u8)
-		    ((resource->address.attribute.memory.
-		      cache_attribute & 0x03) << 1);
-	} else if (resource->address.resource_type == ACPI_IO_RANGE) {
-		/* Ranges (_RNG) - flag bits[1:0] */
-
-		flags = (u8)
-		    (resource->address.attribute.io.range_attribute & 0x03);
-
-		/* Translations (_TTP and _TRS) - flag bits[5:4] */
-
-		flags |= (u8)
-		    ((resource->address.attribute.io.
-		      translation_attribute & 0x03) << 4);
-	}
-
-	return (flags);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_address16_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_address16_resource(u8 * byte_stream_buffer,
-			   acpi_size * bytes_consumed,
-			   u8 ** output_buffer, acpi_size * structure_size)
-{
-	u32 index;
-	u16 temp16;
-	u8 temp8;
-	u8 *temp_ptr;
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16);
-
-	ACPI_FUNCTION_TRACE("rs_address16_resource");
-
-	/* Get the Descriptor Length field */
-
-	buffer += 1;
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-	/* Validate minimum descriptor length */
-
-	if (temp16 < 13) {
-		return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
-	}
-
-	*bytes_consumed = temp16 + 3;
-	output_struct->id = ACPI_RSTYPE_ADDRESS16;
-
-	/* Get the Resource Type (Byte3) */
-
-	buffer += 2;
-	temp8 = *buffer;
-
-	/* Values 0-2 and 0xC0-0xFF are valid */
-
-	if ((temp8 > 2) && (temp8 < 0xC0)) {
-		return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
-	}
-
-	output_struct->data.address16.resource_type = temp8;
-
-	/* Get the General Flags (Byte4) */
-
-	buffer += 1;
-	acpi_rs_decode_general_flags(&output_struct->data, *buffer);
-
-	/* Get the Type Specific Flags (Byte5) */
-
-	buffer += 1;
-	acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
-
-	/* Get Granularity (Bytes 6-7) */
-
-	buffer += 1;
-	ACPI_MOVE_16_TO_32(&output_struct->data.address16.granularity, buffer);
-
-	/* Get min_address_range (Bytes 8-9) */
-
-	buffer += 2;
-	ACPI_MOVE_16_TO_32(&output_struct->data.address16.min_address_range,
-			   buffer);
-
-	/* Get max_address_range (Bytes 10-11) */
-
-	buffer += 2;
-	ACPI_MOVE_16_TO_32(&output_struct->data.address16.max_address_range,
-			   buffer);
-
-	/* Get address_translation_offset (Bytes 12-13) */
-
-	buffer += 2;
-	ACPI_MOVE_16_TO_32(&output_struct->data.address16.
-			   address_translation_offset, buffer);
-
-	/* Get address_length (Bytes 14-15) */
-
-	buffer += 2;
-	ACPI_MOVE_16_TO_32(&output_struct->data.address16.address_length,
-			   buffer);
-
-	/* Resource Source Index (if present) */
-
-	buffer += 2;
+	{ACPI_RSC_ADDRESS, 0, 0, 0},
 
 	/*
-	 * This will leave us pointing to the Resource Source Index
-	 * If it is present, then save it off and calculate the
-	 * pointer to where the null terminated string goes:
-	 * Each Interrupt takes 32-bits + the 5 bytes of the
-	 * stream that are default.
-	 *
-	 * Note: Some resource descriptors will have an additional null, so
-	 * we add 1 to the length.
+	 * These fields are contiguous in both the source and destination:
+	 * Address Granularity
+	 * Address Range Minimum
+	 * Address Range Maximum
+	 * Address Translation Offset
+	 * Address Length
 	 */
-	if (*bytes_consumed > (16 + 1)) {
-		/* Dereference the Index */
+	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.granularity),
+	 AML_OFFSET(address16.granularity),
+	 5},
 
-		output_struct->data.address16.resource_source.index =
-		    (u32) * buffer;
+	/* Optional resource_source (Index and String) */
 
-		/* Point to the String */
+	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address16.resource_source),
+	 0,
+	 sizeof(struct aml_resource_address16)}
+};
 
-		buffer += 1;
+/*******************************************************************************
+ *
+ * acpi_rs_convert_address32 - All DWORD (32-bit) address resources
+ *
+ ******************************************************************************/
 
-		/* Point the String pointer to the end of this structure */
+struct acpi_rsconvert_info acpi_rs_convert_address32[5] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS32,
+	 ACPI_RS_SIZE(struct acpi_resource_address32),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address32)},
 
-		output_struct->data.address16.resource_source.string_ptr =
-		    (char *)((u8 *) output_struct + struct_size);
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS32,
+	 sizeof(struct aml_resource_address32),
+	 0},
 
-		temp_ptr = (u8 *)
-		    output_struct->data.address16.resource_source.string_ptr;
+	/* Resource Type, General Flags, and Type-Specific Flags */
 
-		/* Copy the resource_source string into the buffer */
+	{ACPI_RSC_ADDRESS, 0, 0, 0},
 
-		index = 0;
-		while (*buffer) {
-			*temp_ptr = *buffer;
+	/*
+	 * These fields are contiguous in both the source and destination:
+	 * Address Granularity
+	 * Address Range Minimum
+	 * Address Range Maximum
+	 * Address Translation Offset
+	 * Address Length
+	 */
+	{ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.granularity),
+	 AML_OFFSET(address32.granularity),
+	 5},
 
-			temp_ptr++;
-			buffer++;
-			index++;
-		}
+	/* Optional resource_source (Index and String) */
 
-		/* Add the terminating null and set the string length */
+	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address32.resource_source),
+	 0,
+	 sizeof(struct aml_resource_address32)}
+};
 
-		*temp_ptr = 0;
-		output_struct->data.address16.resource_source.string_length =
-		    index + 1;
+/*******************************************************************************
+ *
+ * acpi_rs_convert_address64 - All QWORD (64-bit) address resources
+ *
+ ******************************************************************************/
 
-		/*
-		 * In order for the struct_size to fall on a 32-bit boundary,
-		 * calculate the length of the string and expand the
-		 * struct_size to the next 32-bit boundary.
-		 */
-		temp8 = (u8) (index + 1);
-		struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
+struct acpi_rsconvert_info acpi_rs_convert_address64[5] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS64,
+	 ACPI_RS_SIZE(struct acpi_resource_address64),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address64)},
+
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS64,
+	 sizeof(struct aml_resource_address64),
+	 0},
+
+	/* Resource Type, General Flags, and Type-Specific Flags */
+
+	{ACPI_RSC_ADDRESS, 0, 0, 0},
+
+	/*
+	 * These fields are contiguous in both the source and destination:
+	 * Address Granularity
+	 * Address Range Minimum
+	 * Address Range Maximum
+	 * Address Translation Offset
+	 * Address Length
+	 */
+	{ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.granularity),
+	 AML_OFFSET(address64.granularity),
+	 5},
+
+	/* Optional resource_source (Index and String) */
+
+	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address64.resource_source),
+	 0,
+	 sizeof(struct aml_resource_address64)}
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_ext_address64 - All Extended (64-bit) address resources
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64,
+	 ACPI_RS_SIZE(struct acpi_resource_extended_address64),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_address64)},
+
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64,
+	 sizeof(struct aml_resource_extended_address64),
+	 0},
+
+	/* Resource Type, General Flags, and Type-Specific Flags */
+
+	{ACPI_RSC_ADDRESS, 0, 0, 0},
+
+	/* Revision ID */
+
+	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_iD),
+	 AML_OFFSET(ext_address64.revision_iD),
+	 1},
+	/*
+	 * These fields are contiguous in both the source and destination:
+	 * Address Granularity
+	 * Address Range Minimum
+	 * Address Range Maximum
+	 * Address Translation Offset
+	 * Address Length
+	 * Type-Specific Attribute
+	 */
+	{ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.ext_address64.granularity),
+	 AML_OFFSET(ext_address64.granularity),
+	 6}
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_general_flags - Flags common to all address descriptors
+ *
+ ******************************************************************************/
+
+static struct acpi_rsconvert_info acpi_rs_convert_general_flags[6] = {
+	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.flags),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_general_flags)},
+
+	/* Resource Type (Memory, Io, bus_number, etc.) */
+
+	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.address.resource_type),
+	 AML_OFFSET(address.resource_type),
+	 1},
+
+	/* General Flags - Consume, Decode, min_fixed, max_fixed */
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.producer_consumer),
+	 AML_OFFSET(address.flags),
+	 0},
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.decode),
+	 AML_OFFSET(address.flags),
+	 1},
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.min_address_fixed),
+	 AML_OFFSET(address.flags),
+	 2},
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.max_address_fixed),
+	 AML_OFFSET(address.flags),
+	 3}
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_mem_flags - Flags common to Memory address descriptors
+ *
+ ******************************************************************************/
+
+static struct acpi_rsconvert_info acpi_rs_convert_mem_flags[5] = {
+	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_mem_flags)},
+
+	/* Memory-specific flags */
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.write_protect),
+	 AML_OFFSET(address.specific_flags),
+	 0},
+
+	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.caching),
+	 AML_OFFSET(address.specific_flags),
+	 1},
+
+	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.range_type),
+	 AML_OFFSET(address.specific_flags),
+	 3},
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.translation),
+	 AML_OFFSET(address.specific_flags),
+	 5}
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_io_flags - Flags common to I/O address descriptors
+ *
+ ******************************************************************************/
+
+static struct acpi_rsconvert_info acpi_rs_convert_io_flags[4] = {
+	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io_flags)},
+
+	/* I/O-specific flags */
+
+	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.io.range_type),
+	 AML_OFFSET(address.specific_flags),
+	 0},
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.io.translation),
+	 AML_OFFSET(address.specific_flags),
+	 4},
+
+	{ACPI_RSC_1BITFLAG,
+	 ACPI_RS_OFFSET(data.address.info.io.translation_type),
+	 AML_OFFSET(address.specific_flags),
+	 5}
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_get_address_common
+ *
+ * PARAMETERS:  Resource            - Pointer to the internal resource struct
+ *              Aml                 - Pointer to the AML resource descriptor
+ *
+ * RETURN:      TRUE if the resource_type field is OK, FALSE otherwise
+ *
+ * DESCRIPTION: Convert common flag fields from a raw AML resource descriptor
+ *              to an internal resource descriptor
+ *
+ ******************************************************************************/
+
+u8
+acpi_rs_get_address_common(struct acpi_resource *resource,
+			   union aml_resource *aml)
+{
+	ACPI_FUNCTION_ENTRY();
+
+	/* Validate the Resource Type */
+
+	if ((aml->address.resource_type > 2)
+	    && (aml->address.resource_type < 0xC0)) {
+		return (FALSE);
+	}
+
+	/* Get the Resource Type and General Flags */
+
+	(void)acpi_rs_convert_aml_to_resource(resource, aml,
+					      acpi_rs_convert_general_flags);
+
+	/* Get the Type-Specific Flags (Memory and I/O descriptors only) */
+
+	if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
+		(void)acpi_rs_convert_aml_to_resource(resource, aml,
+						      acpi_rs_convert_mem_flags);
+	} else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
+		(void)acpi_rs_convert_aml_to_resource(resource, aml,
+						      acpi_rs_convert_io_flags);
 	} else {
-		output_struct->data.address16.resource_source.index = 0;
-		output_struct->data.address16.resource_source.string_length = 0;
-		output_struct->data.address16.resource_source.string_ptr = NULL;
+		/* Generic resource type, just grab the type_specific byte */
+
+		resource->data.address.info.type_specific =
+		    aml->address.specific_flags;
 	}
 
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
+	return (TRUE);
 }
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_address16_stream
+ * FUNCTION:    acpi_rs_set_address_common
  *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
+ * PARAMETERS:  Aml                 - Pointer to the AML resource descriptor
+ *              Resource            - Pointer to the internal resource struct
  *
- * RETURN:      Status
+ * RETURN:      None
  *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
+ * DESCRIPTION: Convert common flag fields from a resource descriptor to an
+ *              AML descriptor
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_address16_stream(struct acpi_resource *linked_list,
-			 u8 ** output_buffer, acpi_size * bytes_consumed)
+void
+acpi_rs_set_address_common(union aml_resource *aml,
+			   struct acpi_resource *resource)
 {
-	u8 *buffer = *output_buffer;
-	u8 *length_field;
-	acpi_size actual_bytes;
+	ACPI_FUNCTION_ENTRY();
 
-	ACPI_FUNCTION_TRACE("rs_address16_stream");
+	/* Set the Resource Type and General Flags */
 
-	/* Set the Descriptor Type field */
+	(void)acpi_rs_convert_resource_to_aml(resource, aml,
+					      acpi_rs_convert_general_flags);
 
-	*buffer = ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE;
-	buffer += 1;
+	/* Set the Type-Specific Flags (Memory and I/O descriptors only) */
 
-	/* Save a pointer to the Length field - to be filled in later */
-
-	length_field = buffer;
-	buffer += 2;
-
-	/* Set the Resource Type (Memory, Io, bus_number) */
-
-	*buffer = (u8) (linked_list->data.address16.resource_type & 0x03);
-	buffer += 1;
-
-	/* Set the general flags */
-
-	*buffer = acpi_rs_encode_general_flags(&linked_list->data);
-	buffer += 1;
-
-	/* Set the type specific flags */
-
-	*buffer = acpi_rs_encode_specific_flags(&linked_list->data);
-	buffer += 1;
-
-	/* Set the address space granularity */
-
-	ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.granularity);
-	buffer += 2;
-
-	/* Set the address range minimum */
-
-	ACPI_MOVE_32_TO_16(buffer,
-			   &linked_list->data.address16.min_address_range);
-	buffer += 2;
-
-	/* Set the address range maximum */
-
-	ACPI_MOVE_32_TO_16(buffer,
-			   &linked_list->data.address16.max_address_range);
-	buffer += 2;
-
-	/* Set the address translation offset */
-
-	ACPI_MOVE_32_TO_16(buffer,
-			   &linked_list->data.address16.
-			   address_translation_offset);
-	buffer += 2;
-
-	/* Set the address length */
-
-	ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.address_length);
-	buffer += 2;
-
-	/* Resource Source Index and Resource Source are optional */
-
-	if (linked_list->data.address16.resource_source.string_length) {
-		*buffer =
-		    (u8) linked_list->data.address16.resource_source.index;
-		buffer += 1;
-
-		/* Copy the resource_source string */
-
-		ACPI_STRCPY((char *)buffer,
-			    linked_list->data.address16.resource_source.
-			    string_ptr);
-
-		/*
-		 * Buffer needs to be set to the length of the string + one for the
-		 * terminating null
-		 */
-		buffer +=
-		    (acpi_size) (ACPI_STRLEN
-				 (linked_list->data.address16.resource_source.
-				  string_ptr) + 1);
-	}
-
-	/* Return the number of bytes consumed in this operation */
-
-	actual_bytes = ACPI_PTR_DIFF(buffer, *output_buffer);
-	*bytes_consumed = actual_bytes;
-
-	/*
-	 * Set the length field to the number of bytes consumed
-	 * minus the header size (3 bytes)
-	 */
-	actual_bytes -= 3;
-	ACPI_MOVE_SIZE_TO_16(length_field, &actual_bytes);
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_address32_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_address32_resource(u8 * byte_stream_buffer,
-			   acpi_size * bytes_consumed,
-			   u8 ** output_buffer, acpi_size * structure_size)
-{
-	u16 temp16;
-	u8 temp8;
-	u8 *temp_ptr;
-	u32 index;
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32);
-
-	ACPI_FUNCTION_TRACE("rs_address32_resource");
-
-	/* Get the Descriptor Length field */
-
-	buffer += 1;
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-	/* Validate minimum descriptor length */
-
-	if (temp16 < 23) {
-		return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
-	}
-
-	*bytes_consumed = temp16 + 3;
-	output_struct->id = ACPI_RSTYPE_ADDRESS32;
-
-	/* Get the Resource Type (Byte3) */
-
-	buffer += 2;
-	temp8 = *buffer;
-
-	/* Values 0-2 and 0xC0-0xFF are valid */
-
-	if ((temp8 > 2) && (temp8 < 0xC0)) {
-		return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
-	}
-
-	output_struct->data.address32.resource_type = temp8;
-
-	/* Get the General Flags (Byte4) */
-
-	buffer += 1;
-	acpi_rs_decode_general_flags(&output_struct->data, *buffer);
-
-	/* Get the Type Specific Flags (Byte5) */
-
-	buffer += 1;
-	acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
-
-	/* Get Granularity (Bytes 6-9) */
-
-	buffer += 1;
-	ACPI_MOVE_32_TO_32(&output_struct->data.address32.granularity, buffer);
-
-	/* Get min_address_range (Bytes 10-13) */
-
-	buffer += 4;
-	ACPI_MOVE_32_TO_32(&output_struct->data.address32.min_address_range,
-			   buffer);
-
-	/* Get max_address_range (Bytes 14-17) */
-
-	buffer += 4;
-	ACPI_MOVE_32_TO_32(&output_struct->data.address32.max_address_range,
-			   buffer);
-
-	/* Get address_translation_offset (Bytes 18-21) */
-
-	buffer += 4;
-	ACPI_MOVE_32_TO_32(&output_struct->data.address32.
-			   address_translation_offset, buffer);
-
-	/* Get address_length (Bytes 22-25) */
-
-	buffer += 4;
-	ACPI_MOVE_32_TO_32(&output_struct->data.address32.address_length,
-			   buffer);
-
-	/* Resource Source Index (if present) */
-
-	buffer += 4;
-
-	/*
-	 * This will leave us pointing to the Resource Source Index
-	 * If it is present, then save it off and calculate the
-	 * pointer to where the null terminated string goes:
-	 *
-	 * Note: Some resource descriptors will have an additional null, so
-	 * we add 1 to the length.
-	 */
-	if (*bytes_consumed > (26 + 1)) {
-		/* Dereference the Index */
-
-		output_struct->data.address32.resource_source.index =
-		    (u32) * buffer;
-
-		/* Point to the String */
-
-		buffer += 1;
-
-		/* Point the String pointer to the end of this structure */
-
-		output_struct->data.address32.resource_source.string_ptr =
-		    (char *)((u8 *) output_struct + struct_size);
-
-		temp_ptr = (u8 *)
-		    output_struct->data.address32.resource_source.string_ptr;
-
-		/* Copy the resource_source string into the buffer */
-
-		index = 0;
-		while (*buffer) {
-			*temp_ptr = *buffer;
-
-			temp_ptr++;
-			buffer++;
-			index++;
-		}
-
-		/* Add the terminating null and set the string length */
-
-		*temp_ptr = 0;
-		output_struct->data.address32.resource_source.string_length =
-		    index + 1;
-
-		/*
-		 * In order for the struct_size to fall on a 32-bit boundary,
-		 * calculate the length of the string and expand the
-		 * struct_size to the next 32-bit boundary.
-		 */
-		temp8 = (u8) (index + 1);
-		struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
+	if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
+		(void)acpi_rs_convert_resource_to_aml(resource, aml,
+						      acpi_rs_convert_mem_flags);
+	} else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
+		(void)acpi_rs_convert_resource_to_aml(resource, aml,
+						      acpi_rs_convert_io_flags);
 	} else {
-		output_struct->data.address32.resource_source.index = 0;
-		output_struct->data.address32.resource_source.string_length = 0;
-		output_struct->data.address32.resource_source.string_ptr = NULL;
+		/* Generic resource type, just copy the type_specific byte */
+
+		aml->address.specific_flags =
+		    resource->data.address.info.type_specific;
 	}
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_address32_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_address32_stream(struct acpi_resource *linked_list,
-			 u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer;
-	u16 *length_field;
-
-	ACPI_FUNCTION_TRACE("rs_address32_stream");
-
-	buffer = *output_buffer;
-
-	/* Set the Descriptor Type field */
-
-	*buffer = ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE;
-	buffer += 1;
-
-	/* Save a pointer to the Length field - to be filled in later */
-
-	length_field = ACPI_CAST_PTR(u16, buffer);
-	buffer += 2;
-
-	/* Set the Resource Type (Memory, Io, bus_number) */
-
-	*buffer = (u8) (linked_list->data.address32.resource_type & 0x03);
-	buffer += 1;
-
-	/* Set the general flags */
-
-	*buffer = acpi_rs_encode_general_flags(&linked_list->data);
-	buffer += 1;
-
-	/* Set the type specific flags */
-
-	*buffer = acpi_rs_encode_specific_flags(&linked_list->data);
-	buffer += 1;
-
-	/* Set the address space granularity */
-
-	ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.granularity);
-	buffer += 4;
-
-	/* Set the address range minimum */
-
-	ACPI_MOVE_32_TO_32(buffer,
-			   &linked_list->data.address32.min_address_range);
-	buffer += 4;
-
-	/* Set the address range maximum */
-
-	ACPI_MOVE_32_TO_32(buffer,
-			   &linked_list->data.address32.max_address_range);
-	buffer += 4;
-
-	/* Set the address translation offset */
-
-	ACPI_MOVE_32_TO_32(buffer,
-			   &linked_list->data.address32.
-			   address_translation_offset);
-	buffer += 4;
-
-	/* Set the address length */
-
-	ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.address_length);
-	buffer += 4;
-
-	/* Resource Source Index and Resource Source are optional */
-
-	if (linked_list->data.address32.resource_source.string_length) {
-		*buffer =
-		    (u8) linked_list->data.address32.resource_source.index;
-		buffer += 1;
-
-		/* Copy the resource_source string */
-
-		ACPI_STRCPY((char *)buffer,
-			    linked_list->data.address32.resource_source.
-			    string_ptr);
-
-		/*
-		 * Buffer needs to be set to the length of the string + one for the
-		 *  terminating null
-		 */
-		buffer +=
-		    (acpi_size) (ACPI_STRLEN
-				 (linked_list->data.address32.resource_source.
-				  string_ptr) + 1);
-	}
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-
-	/*
-	 * Set the length field to the number of bytes consumed
-	 * minus the header size (3 bytes)
-	 */
-	*length_field = (u16) (*bytes_consumed - 3);
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_address64_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_address64_resource(u8 * byte_stream_buffer,
-			   acpi_size * bytes_consumed,
-			   u8 ** output_buffer, acpi_size * structure_size)
-{
-	u16 temp16;
-	u8 temp8;
-	u8 resource_type;
-	u8 *temp_ptr;
-	u32 index;
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64);
-
-	ACPI_FUNCTION_TRACE("rs_address64_resource");
-
-	/* Get the Descriptor Type */
-
-	resource_type = *buffer;
-
-	/* Get the Descriptor Length field */
-
-	buffer += 1;
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-	/* Validate minimum descriptor length */
-
-	if (temp16 < 43) {
-		return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
-	}
-
-	*bytes_consumed = temp16 + 3;
-	output_struct->id = ACPI_RSTYPE_ADDRESS64;
-
-	/* Get the Resource Type (Byte3) */
-
-	buffer += 2;
-	temp8 = *buffer;
-
-	/* Values 0-2 and 0xC0-0xFF are valid */
-
-	if ((temp8 > 2) && (temp8 < 0xC0)) {
-		return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
-	}
-
-	output_struct->data.address64.resource_type = temp8;
-
-	/* Get the General Flags (Byte4) */
-
-	buffer += 1;
-	acpi_rs_decode_general_flags(&output_struct->data, *buffer);
-
-	/* Get the Type Specific Flags (Byte5) */
-
-	buffer += 1;
-	acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
-
-	if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
-		/* Move past revision_id and Reserved byte */
-
-		buffer += 2;
-	}
-
-	/* Get Granularity (Bytes 6-13) or (Bytes 8-15) */
-
-	buffer += 1;
-	ACPI_MOVE_64_TO_64(&output_struct->data.address64.granularity, buffer);
-
-	/* Get min_address_range (Bytes 14-21) or (Bytes 16-23) */
-
-	buffer += 8;
-	ACPI_MOVE_64_TO_64(&output_struct->data.address64.min_address_range,
-			   buffer);
-
-	/* Get max_address_range (Bytes 22-29) or (Bytes 24-31) */
-
-	buffer += 8;
-	ACPI_MOVE_64_TO_64(&output_struct->data.address64.max_address_range,
-			   buffer);
-
-	/* Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */
-
-	buffer += 8;
-	ACPI_MOVE_64_TO_64(&output_struct->data.address64.
-			   address_translation_offset, buffer);
-
-	/* Get address_length (Bytes 38-45) or (Bytes 40-47) */
-
-	buffer += 8;
-	ACPI_MOVE_64_TO_64(&output_struct->data.address64.address_length,
-			   buffer);
-
-	output_struct->data.address64.resource_source.index = 0;
-	output_struct->data.address64.resource_source.string_length = 0;
-	output_struct->data.address64.resource_source.string_ptr = NULL;
-
-	if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
-		/* Get type_specific_attribute (Bytes 48-55) */
-
-		buffer += 8;
-		ACPI_MOVE_64_TO_64(&output_struct->data.address64.
-				   type_specific_attributes, buffer);
-	} else {
-		output_struct->data.address64.type_specific_attributes = 0;
-
-		/* Resource Source Index (if present) */
-
-		buffer += 8;
-
-		/*
-		 * This will leave us pointing to the Resource Source Index
-		 * If it is present, then save it off and calculate the
-		 * pointer to where the null terminated string goes:
-		 * Each Interrupt takes 32-bits + the 5 bytes of the
-		 * stream that are default.
-		 *
-		 * Note: Some resource descriptors will have an additional null, so
-		 * we add 1 to the length.
-		 */
-		if (*bytes_consumed > (46 + 1)) {
-			/* Dereference the Index */
-
-			output_struct->data.address64.resource_source.index =
-			    (u32) * buffer;
-
-			/* Point to the String */
-
-			buffer += 1;
-
-			/* Point the String pointer to the end of this structure */
-
-			output_struct->data.address64.resource_source.
-			    string_ptr =
-			    (char *)((u8 *) output_struct + struct_size);
-
-			temp_ptr = (u8 *)
-			    output_struct->data.address64.resource_source.
-			    string_ptr;
-
-			/* Copy the resource_source string into the buffer */
-
-			index = 0;
-			while (*buffer) {
-				*temp_ptr = *buffer;
-
-				temp_ptr++;
-				buffer++;
-				index++;
-			}
-
-			/*
-			 * Add the terminating null and set the string length
-			 */
-			*temp_ptr = 0;
-			output_struct->data.address64.resource_source.
-			    string_length = index + 1;
-
-			/*
-			 * In order for the struct_size to fall on a 32-bit boundary,
-			 * calculate the length of the string and expand the
-			 * struct_size to the next 32-bit boundary.
-			 */
-			temp8 = (u8) (index + 1);
-			struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
-		}
-	}
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_address64_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_address64_stream(struct acpi_resource *linked_list,
-			 u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer;
-	u16 *length_field;
-
-	ACPI_FUNCTION_TRACE("rs_address64_stream");
-
-	buffer = *output_buffer;
-
-	/* Set the Descriptor Type field */
-
-	*buffer = ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE;
-	buffer += 1;
-
-	/* Save a pointer to the Length field - to be filled in later */
-
-	length_field = ACPI_CAST_PTR(u16, buffer);
-	buffer += 2;
-
-	/* Set the Resource Type (Memory, Io, bus_number) */
-
-	*buffer = (u8) (linked_list->data.address64.resource_type & 0x03);
-	buffer += 1;
-
-	/* Set the general flags */
-
-	*buffer = acpi_rs_encode_general_flags(&linked_list->data);
-	buffer += 1;
-
-	/* Set the type specific flags */
-
-	*buffer = acpi_rs_encode_specific_flags(&linked_list->data);
-	buffer += 1;
-
-	/* Set the address space granularity */
-
-	ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.granularity);
-	buffer += 8;
-
-	/* Set the address range minimum */
-
-	ACPI_MOVE_64_TO_64(buffer,
-			   &linked_list->data.address64.min_address_range);
-	buffer += 8;
-
-	/* Set the address range maximum */
-
-	ACPI_MOVE_64_TO_64(buffer,
-			   &linked_list->data.address64.max_address_range);
-	buffer += 8;
-
-	/* Set the address translation offset */
-
-	ACPI_MOVE_64_TO_64(buffer,
-			   &linked_list->data.address64.
-			   address_translation_offset);
-	buffer += 8;
-
-	/* Set the address length */
-
-	ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.address_length);
-	buffer += 8;
-
-	/* Resource Source Index and Resource Source are optional */
-
-	if (linked_list->data.address64.resource_source.string_length) {
-		*buffer =
-		    (u8) linked_list->data.address64.resource_source.index;
-		buffer += 1;
-
-		/* Copy the resource_source string */
-
-		ACPI_STRCPY((char *)buffer,
-			    linked_list->data.address64.resource_source.
-			    string_ptr);
-
-		/*
-		 * Buffer needs to be set to the length of the string + one for the
-		 * terminating null
-		 */
-		buffer +=
-		    (acpi_size) (ACPI_STRLEN
-				 (linked_list->data.address64.resource_source.
-				  string_ptr) + 1);
-	}
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-
-	/*
-	 * Set the length field to the number of bytes consumed
-	 * minus the header size (3 bytes)
-	 */
-	*length_field = (u16) (*bytes_consumed - 3);
-	return_ACPI_STATUS(AE_OK);
 }
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 378f583..7d6481d 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,652 +49,433 @@
 #define _COMPONENT          ACPI_RESOURCES
 ACPI_MODULE_NAME("rscalc")
 
+/* Local prototypes */
+static u8 acpi_rs_count_set_bits(u16 bit_field);
+
+static acpi_rs_length
+acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
+
+static u32
+acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
+
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_get_byte_stream_length
+ * FUNCTION:    acpi_rs_count_set_bits
  *
- * PARAMETERS:  linked_list         - Pointer to the resource linked list
- *              size_needed         - u32 pointer of the size buffer needed
- *                                    to properly return the parsed data
+ * PARAMETERS:  bit_field       - Field in which to count bits
+ *
+ * RETURN:      Number of bits set within the field
+ *
+ * DESCRIPTION: Count the number of bits set in a resource field. Used for
+ *              (Short descriptor) interrupt and DMA lists.
+ *
+ ******************************************************************************/
+
+static u8 acpi_rs_count_set_bits(u16 bit_field)
+{
+	u8 bits_set;
+
+	ACPI_FUNCTION_ENTRY();
+
+	for (bits_set = 0; bit_field; bits_set++) {
+		/* Zero the least significant bit that is set */
+
+		bit_field &= (bit_field - 1);
+	}
+
+	return (bits_set);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_struct_option_length
+ *
+ * PARAMETERS:  resource_source     - Pointer to optional descriptor field
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
- *              the size buffer needed to hold the linked list that conveys
- *              the resource data.
+ * DESCRIPTION: Common code to handle optional resource_source_index and
+ *              resource_source fields in some Large descriptors. Used during
+ *              list-to-stream conversion
  *
  ******************************************************************************/
-acpi_status
-acpi_rs_get_byte_stream_length(struct acpi_resource *linked_list,
-			       acpi_size * size_needed)
+
+static acpi_rs_length
+acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
 {
-	acpi_size byte_stream_size_needed = 0;
-	acpi_size segment_size;
-	u8 done = FALSE;
+	ACPI_FUNCTION_ENTRY();
 
-	ACPI_FUNCTION_TRACE("rs_get_byte_stream_length");
+	/*
+	 * If the resource_source string is valid, return the size of the string
+	 * (string_length includes the NULL terminator) plus the size of the
+	 * resource_source_index (1).
+	 */
+	if (resource_source->string_ptr) {
+		return ((acpi_rs_length) (resource_source->string_length + 1));
+	}
 
-	while (!done) {
-		/* Init the variable that will hold the size to add to the total. */
+	return (0);
+}
 
-		segment_size = 0;
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_stream_option_length
+ *
+ * PARAMETERS:  resource_length     - Length from the resource header
+ *              minimum_total_length - Minimum length of this resource, before
+ *                                    any optional fields. Includes header size
+ *
+ * RETURN:      Length of optional string (0 if no string present)
+ *
+ * DESCRIPTION: Common code to handle optional resource_source_index and
+ *              resource_source fields in some Large descriptors. Used during
+ *              stream-to-list conversion
+ *
+ ******************************************************************************/
 
-		switch (linked_list->id) {
-		case ACPI_RSTYPE_IRQ:
+static u32
+acpi_rs_stream_option_length(u32 resource_length,
+			     u32 minimum_aml_resource_length)
+{
+	u32 string_length = 0;
+
+	ACPI_FUNCTION_ENTRY();
+
+	/*
+	 * The resource_source_index and resource_source are optional elements of some
+	 * Large-type resource descriptors.
+	 */
+
+	/*
+	 * If the length of the actual resource descriptor is greater than the ACPI
+	 * spec-defined minimum length, it means that a resource_source_index exists
+	 * and is followed by a (required) null terminated string. The string length
+	 * (including the null terminator) is the resource length minus the minimum
+	 * length, minus one byte for the resource_source_index itself.
+	 */
+	if (resource_length > minimum_aml_resource_length) {
+		/* Compute the length of the optional string */
+
+		string_length =
+		    resource_length - minimum_aml_resource_length - 1;
+	}
+
+	/* Round up length to 32 bits for internal structure alignment */
+
+	return (ACPI_ROUND_UP_to_32_bITS(string_length));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_get_aml_length
+ *
+ * PARAMETERS:  Resource            - Pointer to the resource linked list
+ *              size_needed         - Where the required size is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Takes a linked list of internal resource descriptors and
+ *              calculates the size buffer needed to hold the corresponding
+ *              external resource byte stream.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
+{
+	acpi_size aml_size_needed = 0;
+	acpi_rs_length total_size;
+
+	ACPI_FUNCTION_TRACE("rs_get_aml_length");
+
+	/* Traverse entire list of internal resource descriptors */
+
+	while (resource) {
+		/* Validate the descriptor type */
+
+		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
+			return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
+		}
+
+		/* Get the base size of the (external stream) resource descriptor */
+
+		total_size = acpi_gbl_aml_resource_sizes[resource->type];
+
+		/*
+		 * Augment the base size for descriptors with optional and/or
+		 * variable-length fields
+		 */
+		switch (resource->type) {
+		case ACPI_RESOURCE_TYPE_VENDOR:
 			/*
-			 * IRQ Resource
-			 * For an IRQ Resource, Byte 3, although optional, will always be
-			 * created - it holds IRQ information.
-			 */
-			segment_size = 4;
-			break;
-
-		case ACPI_RSTYPE_DMA:
-			/*
-			 * DMA Resource
-			 * For this resource the size is static
-			 */
-			segment_size = 3;
-			break;
-
-		case ACPI_RSTYPE_START_DPF:
-			/*
-			 * Start Dependent Functions Resource
-			 * For a start_dependent_functions Resource, Byte 1, although
-			 * optional, will always be created.
-			 */
-			segment_size = 2;
-			break;
-
-		case ACPI_RSTYPE_END_DPF:
-			/*
-			 * End Dependent Functions Resource
-			 * For this resource the size is static
-			 */
-			segment_size = 1;
-			break;
-
-		case ACPI_RSTYPE_IO:
-			/*
-			 * IO Port Resource
-			 * For this resource the size is static
-			 */
-			segment_size = 8;
-			break;
-
-		case ACPI_RSTYPE_FIXED_IO:
-			/*
-			 * Fixed IO Port Resource
-			 * For this resource the size is static
-			 */
-			segment_size = 4;
-			break;
-
-		case ACPI_RSTYPE_VENDOR:
-			/*
-			 * Vendor Defined Resource
+			 * Vendor Defined Resource:
 			 * For a Vendor Specific resource, if the Length is between 1 and 7
 			 * it will be created as a Small Resource data type, otherwise it
 			 * is a Large Resource data type.
 			 */
-			if (linked_list->data.vendor_specific.length > 7) {
-				segment_size = 3;
-			} else {
-				segment_size = 1;
+			if (resource->data.vendor.byte_length > 7) {
+				/* Base size of a Large resource descriptor */
+
+				total_size =
+				    sizeof(struct aml_resource_large_header);
 			}
-			segment_size +=
-			    linked_list->data.vendor_specific.length;
+
+			/* Add the size of the vendor-specific data */
+
+			total_size = (acpi_rs_length)
+			    (total_size + resource->data.vendor.byte_length);
 			break;
 
-		case ACPI_RSTYPE_END_TAG:
+		case ACPI_RESOURCE_TYPE_END_TAG:
 			/*
-			 * End Tag
-			 * For this resource the size is static
+			 * End Tag:
+			 * We are done -- return the accumulated total size.
 			 */
-			segment_size = 2;
-			done = TRUE;
+			*size_needed = aml_size_needed + total_size;
+
+			/* Normal exit */
+
+			return_ACPI_STATUS(AE_OK);
+
+		case ACPI_RESOURCE_TYPE_ADDRESS16:
+			/*
+			 * 16-Bit Address Resource:
+			 * Add the size of the optional resource_source info
+			 */
+			total_size = (acpi_rs_length)
+			    (total_size +
+			     acpi_rs_struct_option_length(&resource->data.
+							  address16.
+							  resource_source));
 			break;
 
-		case ACPI_RSTYPE_MEM24:
+		case ACPI_RESOURCE_TYPE_ADDRESS32:
 			/*
-			 * 24-Bit Memory Resource
-			 * For this resource the size is static
+			 * 32-Bit Address Resource:
+			 * Add the size of the optional resource_source info
 			 */
-			segment_size = 12;
+			total_size = (acpi_rs_length)
+			    (total_size +
+			     acpi_rs_struct_option_length(&resource->data.
+							  address32.
+							  resource_source));
 			break;
 
-		case ACPI_RSTYPE_MEM32:
+		case ACPI_RESOURCE_TYPE_ADDRESS64:
 			/*
-			 * 32-Bit Memory Range Resource
-			 * For this resource the size is static
+			 * 64-Bit Address Resource:
+			 * Add the size of the optional resource_source info
 			 */
-			segment_size = 20;
+			total_size = (acpi_rs_length)
+			    (total_size +
+			     acpi_rs_struct_option_length(&resource->data.
+							  address64.
+							  resource_source));
 			break;
 
-		case ACPI_RSTYPE_FIXED_MEM32:
+		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 			/*
-			 * 32-Bit Fixed Memory Resource
-			 * For this resource the size is static
+			 * Extended IRQ Resource:
+			 * Add the size of each additional optional interrupt beyond the
+			 * required 1 (4 bytes for each u32 interrupt number)
 			 */
-			segment_size = 12;
-			break;
-
-		case ACPI_RSTYPE_ADDRESS16:
-			/*
-			 * 16-Bit Address Resource
-			 * The base size of this byte stream is 16. If a Resource Source
-			 * string is not NULL, add 1 for the Index + the length of the null
-			 * terminated string Resource Source + 1 for the null.
-			 */
-			segment_size = 16;
-
-			if (linked_list->data.address16.resource_source.
-			    string_ptr) {
-				segment_size +=
-				    linked_list->data.address16.resource_source.
-				    string_length;
-				segment_size++;
-			}
-			break;
-
-		case ACPI_RSTYPE_ADDRESS32:
-			/*
-			 * 32-Bit Address Resource
-			 * The base size of this byte stream is 26. If a Resource
-			 * Source string is not NULL, add 1 for the Index + the
-			 * length of the null terminated string Resource Source +
-			 * 1 for the null.
-			 */
-			segment_size = 26;
-
-			if (linked_list->data.address32.resource_source.
-			    string_ptr) {
-				segment_size +=
-				    linked_list->data.address32.resource_source.
-				    string_length;
-				segment_size++;
-			}
-			break;
-
-		case ACPI_RSTYPE_ADDRESS64:
-			/*
-			 * 64-Bit Address Resource
-			 * The base size of this byte stream is 46. If a resource_source
-			 * string is not NULL, add 1 for the Index + the length of the null
-			 * terminated string Resource Source + 1 for the null.
-			 */
-			segment_size = 46;
-
-			if (linked_list->data.address64.resource_source.
-			    string_ptr) {
-				segment_size +=
-				    linked_list->data.address64.resource_source.
-				    string_length;
-				segment_size++;
-			}
-			break;
-
-		case ACPI_RSTYPE_EXT_IRQ:
-			/*
-			 * Extended IRQ Resource
-			 * The base size of this byte stream is 9. This is for an Interrupt
-			 * table length of 1.  For each additional interrupt, add 4.
-			 * If a Resource Source string is not NULL, add 1 for the
-			 * Index + the length of the null terminated string
-			 * Resource Source + 1 for the null.
-			 */
-			segment_size = 9 + (((acpi_size)
-					     linked_list->data.extended_irq.
-					     number_of_interrupts - 1) * 4);
-
-			if (linked_list->data.extended_irq.resource_source.
-			    string_ptr) {
-				segment_size +=
-				    linked_list->data.extended_irq.
-				    resource_source.string_length;
-				segment_size++;
-			}
+			total_size = (acpi_rs_length)
+			    (total_size +
+			     ((resource->data.extended_irq.interrupt_count -
+			       1) * 4) +
+			     /* Add the size of the optional resource_source info */
+			     acpi_rs_struct_option_length(&resource->data.
+							  extended_irq.
+							  resource_source));
 			break;
 
 		default:
-
-			/* If we get here, everything is out of sync, exit with error */
-
-			return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
-
-		}		/* switch (linked_list->Id) */
+			break;
+		}
 
 		/* Update the total */
 
-		byte_stream_size_needed += segment_size;
+		aml_size_needed += total_size;
 
 		/* Point to the next object */
 
-		linked_list = ACPI_PTR_ADD(struct acpi_resource,
-					   linked_list, linked_list->length);
+		resource =
+		    ACPI_ADD_PTR(struct acpi_resource, resource,
+				 resource->length);
 	}
 
-	/* This is the data the caller needs */
+	/* Did not find an end_tag resource descriptor */
 
-	*size_needed = byte_stream_size_needed;
-	return_ACPI_STATUS(AE_OK);
+	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
 }
 
 /*******************************************************************************
  *
  * FUNCTION:    acpi_rs_get_list_length
  *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource byte stream
- *              byte_stream_buffer_length - Size of byte_stream_buffer
- *              size_needed             - u32 pointer of the size buffer
- *                                        needed to properly return the
- *                                        parsed data
+ * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
+ *              aml_buffer_length   - Size of aml_buffer
+ *              size_needed         - Where the size needed is returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
- *              the size buffer needed to hold the linked list that conveys
- *              the resource data.
+ * DESCRIPTION: Takes an external resource byte stream and calculates the size
+ *              buffer needed to hold the corresponding internal resource
+ *              descriptor linked list.
  *
  ******************************************************************************/
 
 acpi_status
-acpi_rs_get_list_length(u8 * byte_stream_buffer,
-			u32 byte_stream_buffer_length, acpi_size * size_needed)
+acpi_rs_get_list_length(u8 * aml_buffer,
+			u32 aml_buffer_length, acpi_size * size_needed)
 {
-	u32 buffer_size = 0;
-	u32 bytes_parsed = 0;
-	u8 number_of_interrupts = 0;
-	u8 number_of_channels = 0;
-	u8 resource_type;
-	u32 structure_size;
-	u32 bytes_consumed;
+	acpi_status status;
+	u8 *end_aml;
 	u8 *buffer;
-	u8 temp8;
+	u32 buffer_size = 0;
 	u16 temp16;
-	u8 index;
-	u8 additional_bytes;
+	u16 resource_length;
+	u32 extra_struct_bytes;
+	u8 resource_index;
+	u8 minimum_aml_resource_length;
 
 	ACPI_FUNCTION_TRACE("rs_get_list_length");
 
-	while (bytes_parsed < byte_stream_buffer_length) {
-		/* The next byte in the stream is the resource type */
+	end_aml = aml_buffer + aml_buffer_length;
 
-		resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
+	/* Walk the list of AML resource descriptors */
 
-		switch (resource_type) {
-		case ACPI_RDESC_TYPE_MEMORY_24:
+	while (aml_buffer < end_aml) {
+		/* Validate the Resource Type and Resource Length */
+
+		status = acpi_ut_validate_resource(aml_buffer, &resource_index);
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+
+		/* Get the resource length and base (minimum) AML size */
+
+		resource_length = acpi_ut_get_resource_length(aml_buffer);
+		minimum_aml_resource_length =
+		    acpi_gbl_resource_aml_sizes[resource_index];
+
+		/*
+		 * Augment the size for descriptors with optional
+		 * and/or variable length fields
+		 */
+		extra_struct_bytes = 0;
+		buffer =
+		    aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
+
+		switch (acpi_ut_get_resource_type(aml_buffer)) {
+		case ACPI_RESOURCE_NAME_IRQ:
 			/*
-			 * 24-Bit Memory Resource
+			 * IRQ Resource:
+			 * Get the number of bits set in the 16-bit IRQ mask
 			 */
-			bytes_consumed = 12;
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24);
-			break;
-
-		case ACPI_RDESC_TYPE_LARGE_VENDOR:
-			/*
-			 * Vendor Defined Resource
-			 */
-			buffer = byte_stream_buffer;
-			++buffer;
-
 			ACPI_MOVE_16_TO_16(&temp16, buffer);
-			bytes_consumed = temp16 + 3;
-
-			/* Ensure a 32-bit boundary for the structure */
-
-			temp16 = (u16) ACPI_ROUND_UP_to_32_bITS(temp16);
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) +
-			    (temp16 * sizeof(u8));
+			extra_struct_bytes = acpi_rs_count_set_bits(temp16);
 			break;
 
-		case ACPI_RDESC_TYPE_MEMORY_32:
+		case ACPI_RESOURCE_NAME_DMA:
 			/*
-			 * 32-Bit Memory Range Resource
+			 * DMA Resource:
+			 * Get the number of bits set in the 8-bit DMA mask
 			 */
-			bytes_consumed = 20;
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32);
+			extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
 			break;
 
-		case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
+		case ACPI_RESOURCE_NAME_VENDOR_SMALL:
 			/*
-			 * 32-Bit Fixed Memory Resource
+			 * Vendor Resource:
+			 * Ensure a 32-bit boundary for the structure
 			 */
-			bytes_consumed = 12;
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct
-						 acpi_resource_fixed_mem32);
+			extra_struct_bytes =
+			    ACPI_ROUND_UP_to_32_bITS(resource_length) -
+			    resource_length;
 			break;
 
-		case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
+		case ACPI_RESOURCE_NAME_END_TAG:
 			/*
-			 * 64-Bit Address Resource
+			 * End Tag: This is the normal exit, add size of end_tag
 			 */
-			buffer = byte_stream_buffer;
+			*size_needed = buffer_size + ACPI_RS_SIZE_MIN;
+			return_ACPI_STATUS(AE_OK);
 
-			++buffer;
-			ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-			bytes_consumed = temp16 + 3;
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct
-						 acpi_resource_address64);
+		case ACPI_RESOURCE_NAME_VENDOR_LARGE:
+			/*
+			 * Vendor Resource:
+			 * Add vendor data and ensure a 32-bit boundary for the structure
+			 */
+			extra_struct_bytes =
+			    ACPI_ROUND_UP_to_32_bITS(resource_length) -
+			    resource_length;
 			break;
 
-		case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
+		case ACPI_RESOURCE_NAME_ADDRESS32:
+		case ACPI_RESOURCE_NAME_ADDRESS16:
 			/*
-			 * 64-Bit Address Resource
+			 * 32-Bit or 16-bit Address Resource:
+			 * Add the size of any optional data (resource_source)
 			 */
-			buffer = byte_stream_buffer;
-
-			++buffer;
-			ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-			bytes_consumed = temp16 + 3;
-
-			/*
-			 * Resource Source Index and Resource Source are optional elements.
-			 * Check the length of the Bytestream.  If it is greater than 43,
-			 * that means that an Index exists and is followed by a null
-			 * terminated string.  Therefore, set the temp variable to the
-			 * length minus the minimum byte stream length plus the byte for
-			 * the Index to determine the size of the NULL terminated string.
-			 */
-			if (43 < temp16) {
-				temp8 = (u8) (temp16 - 44);
-			} else {
-				temp8 = 0;
-			}
-
-			/* Ensure a 64-bit boundary for the structure */
-
-			temp8 = (u8) ACPI_ROUND_UP_to_64_bITS(temp8);
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64)
-			    + (temp8 * sizeof(u8));
+			extra_struct_bytes =
+			    acpi_rs_stream_option_length(resource_length,
+							 minimum_aml_resource_length);
 			break;
 
-		case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
+		case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
 			/*
-			 * 32-Bit Address Resource
+			 * Extended IRQ:
+			 * Point past the interrupt_vector_flags to get the
+			 * interrupt_table_length.
 			 */
-			buffer = byte_stream_buffer;
+			buffer++;
 
-			++buffer;
-			ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-			bytes_consumed = temp16 + 3;
-
-			/*
-			 * Resource Source Index and Resource Source are optional elements.
-			 * Check the length of the Bytestream.  If it is greater than 23,
-			 * that means that an Index exists and is followed by a null
-			 * terminated string.  Therefore, set the temp variable to the
-			 * length minus the minimum byte stream length plus the byte for
-			 * the Index to determine the size of the NULL terminated string.
-			 */
-			if (23 < temp16) {
-				temp8 = (u8) (temp16 - 24);
-			} else {
-				temp8 = 0;
-			}
-
-			/* Ensure a 32-bit boundary for the structure */
-
-			temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32)
-			    + (temp8 * sizeof(u8));
+			extra_struct_bytes =
+			    /*
+			     * Add 4 bytes for each additional interrupt. Note: at
+			     * least one interrupt is required and is included in
+			     * the minimum descriptor size
+			     */
+			    ((*buffer - 1) * sizeof(u32)) +
+			    /* Add the size of any optional data (resource_source) */
+			    acpi_rs_stream_option_length(resource_length -
+							 extra_struct_bytes,
+							 minimum_aml_resource_length);
 			break;
 
-		case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
+		case ACPI_RESOURCE_NAME_ADDRESS64:
 			/*
-			 * 16-Bit Address Resource
+			 * 64-Bit Address Resource:
+			 * Add the size of any optional data (resource_source)
+			 * Ensure a 64-bit boundary for the structure
 			 */
-			buffer = byte_stream_buffer;
-
-			++buffer;
-			ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-			bytes_consumed = temp16 + 3;
-
-			/*
-			 * Resource Source Index and Resource Source are optional elements.
-			 * Check the length of the Bytestream.  If it is greater than 13,
-			 * that means that an Index exists and is followed by a null
-			 * terminated string.  Therefore, set the temp variable to the
-			 * length minus the minimum byte stream length plus the byte for
-			 * the Index to determine the size of the NULL terminated string.
-			 */
-			if (13 < temp16) {
-				temp8 = (u8) (temp16 - 14);
-			} else {
-				temp8 = 0;
-			}
-
-			/* Ensure a 32-bit boundary for the structure */
-
-			temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16)
-			    + (temp8 * sizeof(u8));
-			break;
-
-		case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
-			/*
-			 * Extended IRQ
-			 */
-			buffer = byte_stream_buffer;
-
-			++buffer;
-			ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-			bytes_consumed = temp16 + 3;
-
-			/*
-			 * Point past the length field and the Interrupt vector flags to
-			 * save off the Interrupt table length to the Temp8 variable.
-			 */
-			buffer += 3;
-			temp8 = *buffer;
-
-			/*
-			 * To compensate for multiple interrupt numbers, add 4 bytes for
-			 * each additional interrupts greater than 1
-			 */
-			additional_bytes = (u8) ((temp8 - 1) * 4);
-
-			/*
-			 * Resource Source Index and Resource Source are optional elements.
-			 * Check the length of the Bytestream.  If it is greater than 9,
-			 * that means that an Index exists and is followed by a null
-			 * terminated string.  Therefore, set the temp variable to the
-			 * length minus the minimum byte stream length plus the byte for
-			 * the Index to determine the size of the NULL terminated string.
-			 */
-			if (9 + additional_bytes < temp16) {
-				temp8 = (u8) (temp16 - (9 + additional_bytes));
-			} else {
-				temp8 = 0;
-			}
-
-			/* Ensure a 32-bit boundary for the structure */
-
-			temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq) +
-			    (additional_bytes * sizeof(u8)) +
-			    (temp8 * sizeof(u8));
-			break;
-
-		case ACPI_RDESC_TYPE_IRQ_FORMAT:
-			/*
-			 * IRQ Resource.
-			 * Determine if it there are two or three trailing bytes
-			 */
-			buffer = byte_stream_buffer;
-			temp8 = *buffer;
-
-			if (temp8 & 0x01) {
-				bytes_consumed = 4;
-			} else {
-				bytes_consumed = 3;
-			}
-
-			/* Point past the descriptor */
-
-			++buffer;
-
-			/* Look at the number of bits set */
-
-			ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-			for (index = 0; index < 16; index++) {
-				if (temp16 & 0x1) {
-					++number_of_interrupts;
-				}
-
-				temp16 >>= 1;
-			}
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_io) +
-			    (number_of_interrupts * sizeof(u32));
-			break;
-
-		case ACPI_RDESC_TYPE_DMA_FORMAT:
-			/*
-			 * DMA Resource
-			 */
-			buffer = byte_stream_buffer;
-			bytes_consumed = 3;
-
-			/* Point past the descriptor */
-
-			++buffer;
-
-			/* Look at the number of bits set */
-
-			temp8 = *buffer;
-
-			for (index = 0; index < 8; index++) {
-				if (temp8 & 0x1) {
-					++number_of_channels;
-				}
-
-				temp8 >>= 1;
-			}
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma) +
-			    (number_of_channels * sizeof(u32));
-			break;
-
-		case ACPI_RDESC_TYPE_START_DEPENDENT:
-			/*
-			 * Start Dependent Functions Resource
-			 * Determine if it there are two or three trailing bytes
-			 */
-			buffer = byte_stream_buffer;
-			temp8 = *buffer;
-
-			if (temp8 & 0x01) {
-				bytes_consumed = 2;
-			} else {
-				bytes_consumed = 1;
-			}
-
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct
-						 acpi_resource_start_dpf);
-			break;
-
-		case ACPI_RDESC_TYPE_END_DEPENDENT:
-			/*
-			 * End Dependent Functions Resource
-			 */
-			bytes_consumed = 1;
-			structure_size = ACPI_RESOURCE_LENGTH;
-			break;
-
-		case ACPI_RDESC_TYPE_IO_PORT:
-			/*
-			 * IO Port Resource
-			 */
-			bytes_consumed = 8;
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_io);
-			break;
-
-		case ACPI_RDESC_TYPE_FIXED_IO_PORT:
-			/*
-			 * Fixed IO Port Resource
-			 */
-			bytes_consumed = 4;
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io);
-			break;
-
-		case ACPI_RDESC_TYPE_SMALL_VENDOR:
-			/*
-			 * Vendor Specific Resource
-			 */
-			buffer = byte_stream_buffer;
-
-			temp8 = *buffer;
-			temp8 = (u8) (temp8 & 0x7);
-			bytes_consumed = temp8 + 1;
-
-			/* Ensure a 32-bit boundary for the structure */
-
-			temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
-			structure_size =
-			    ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) +
-			    (temp8 * sizeof(u8));
-			break;
-
-		case ACPI_RDESC_TYPE_END_TAG:
-			/*
-			 * End Tag
-			 */
-			bytes_consumed = 2;
-			structure_size = ACPI_RESOURCE_LENGTH;
-			byte_stream_buffer_length = bytes_parsed;
+			extra_struct_bytes =
+			    ACPI_ROUND_UP_to_64_bITS
+			    (acpi_rs_stream_option_length
+			     (resource_length, minimum_aml_resource_length));
 			break;
 
 		default:
-			/*
-			 * If we get here, everything is out of sync,
-			 * exit with an error
-			 */
-			return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
+			break;
 		}
 
-		/* Update the return value and counter */
+		/* Update the required buffer size for the internal descriptor structs */
 
-		buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(structure_size);
-		bytes_parsed += bytes_consumed;
+		temp16 = (u16) (acpi_gbl_resource_struct_sizes[resource_index] +
+				extra_struct_bytes);
+		buffer_size += (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(temp16);
 
-		/* Set the byte stream to point to the next resource */
-
-		byte_stream_buffer += bytes_consumed;
+		/*
+		 * Point to the next resource within the stream
+		 * using the size of the header plus the length contained in the header
+		 */
+		aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
 	}
 
-	/* This is the data the caller needs */
+	/* Did not find an end_tag resource descriptor */
 
-	*size_needed = buffer_size;
-	return_ACPI_STATUS(AE_OK);
+	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
 }
 
 /*******************************************************************************
@@ -760,13 +541,13 @@
 
 		for (table_index = 0; table_index < 4 && !name_found;
 		     table_index++) {
-			if ((ACPI_TYPE_STRING ==
-			     ACPI_GET_OBJECT_TYPE(*sub_object_list))
-			    ||
-			    ((ACPI_TYPE_LOCAL_REFERENCE ==
-			      ACPI_GET_OBJECT_TYPE(*sub_object_list))
-			     && ((*sub_object_list)->reference.opcode ==
-				 AML_INT_NAMEPATH_OP))) {
+			if (*sub_object_list &&	/* Null object allowed */
+			    ((ACPI_TYPE_STRING ==
+			      ACPI_GET_OBJECT_TYPE(*sub_object_list)) ||
+			     ((ACPI_TYPE_LOCAL_REFERENCE ==
+			       ACPI_GET_OBJECT_TYPE(*sub_object_list)) &&
+			      ((*sub_object_list)->reference.opcode ==
+			       AML_INT_NAMEPATH_OP)))) {
 				name_found = TRUE;
 			} else {
 				/* Look at the next element */
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 0911526..8c128de 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -53,10 +53,10 @@
  *
  * FUNCTION:    acpi_rs_create_resource_list
  *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource byte stream
- *              output_buffer           - Pointer to the user's buffer
+ * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
+ *              output_buffer       - Pointer to the user's buffer
  *
- * RETURN:      Status  - AE_OK if okay, else a valid acpi_status code
+ * RETURN:      Status: AE_OK if okay, else a valid acpi_status code
  *              If output_buffer is not large enough, output_buffer_length
  *              indicates how large output_buffer should be, else it
  *              indicates how may u8 elements of output_buffer are valid.
@@ -67,33 +67,30 @@
  *
  ******************************************************************************/
 acpi_status
-acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer,
+acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
 			     struct acpi_buffer *output_buffer)
 {
 
 	acpi_status status;
-	u8 *byte_stream_start;
+	u8 *aml_start;
 	acpi_size list_size_needed = 0;
-	u32 byte_stream_buffer_length;
+	u32 aml_buffer_length;
 
 	ACPI_FUNCTION_TRACE("rs_create_resource_list");
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_buffer = %p\n",
-			  byte_stream_buffer));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_buffer = %p\n", aml_buffer));
 
 	/* Params already validated, so we don't re-validate here */
 
-	byte_stream_buffer_length = byte_stream_buffer->buffer.length;
-	byte_stream_start = byte_stream_buffer->buffer.pointer;
+	aml_buffer_length = aml_buffer->buffer.length;
+	aml_start = aml_buffer->buffer.pointer;
 
 	/*
-	 * Pass the byte_stream_buffer into a module that can calculate
+	 * Pass the aml_buffer into a module that can calculate
 	 * the buffer size needed for the linked list
 	 */
-	status =
-	    acpi_rs_get_list_length(byte_stream_start,
-				    byte_stream_buffer_length,
-				    &list_size_needed);
+	status = acpi_rs_get_list_length(aml_start, aml_buffer_length,
+					 &list_size_needed);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n",
 			  status, (u32) list_size_needed));
@@ -110,10 +107,8 @@
 
 	/* Do the conversion */
 
-	status =
-	    acpi_rs_byte_stream_to_list(byte_stream_start,
-					byte_stream_buffer_length,
-					output_buffer->pointer);
+	status = acpi_rs_convert_aml_to_resources(aml_start, aml_buffer_length,
+						  output_buffer->pointer);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
@@ -212,21 +207,20 @@
 		/* Each element of the top-level package must also be a package */
 
 		if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "(PRT[%X]) Need sub-package, found %s\n",
-					  index,
-					  acpi_ut_get_object_type_name
-					  (*top_object_list)));
+			ACPI_ERROR((AE_INFO,
+				    "(PRT[%X]) Need sub-package, found %s",
+				    index,
+				    acpi_ut_get_object_type_name
+				    (*top_object_list)));
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 
 		/* Each sub-package must be of length 4 */
 
 		if ((*top_object_list)->package.count != 4) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "(PRT[%X]) Need package of length 4, found length %d\n",
-					  index,
-					  (*top_object_list)->package.count));
+			ACPI_ERROR((AE_INFO,
+				    "(PRT[%X]) Need package of length 4, found length %d",
+				    index, (*top_object_list)->package.count));
 			return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT);
 		}
 
@@ -243,11 +237,10 @@
 		if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
 			user_prt->address = obj_desc->integer.value;
 		} else {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "(PRT[%X].Address) Need Integer, found %s\n",
-					  index,
-					  acpi_ut_get_object_type_name
-					  (obj_desc)));
+			ACPI_ERROR((AE_INFO,
+				    "(PRT[%X].Address) Need Integer, found %s",
+				    index,
+				    acpi_ut_get_object_type_name(obj_desc)));
 			return_ACPI_STATUS(AE_BAD_DATA);
 		}
 
@@ -257,76 +250,83 @@
 		if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
 			user_prt->pin = (u32) obj_desc->integer.value;
 		} else {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "(PRT[%X].Pin) Need Integer, found %s\n",
-					  index,
-					  acpi_ut_get_object_type_name
-					  (obj_desc)));
+			ACPI_ERROR((AE_INFO,
+				    "(PRT[%X].Pin) Need Integer, found %s",
+				    index,
+				    acpi_ut_get_object_type_name(obj_desc)));
 			return_ACPI_STATUS(AE_BAD_DATA);
 		}
 
-		/* 3) Third subobject: Dereference the PRT.source_name */
-
+		/*
+		 * 3) Third subobject: Dereference the PRT.source_name
+		 * The name may be unresolved (slack mode), so allow a null object
+		 */
 		obj_desc = sub_object_list[2];
-		switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
-		case ACPI_TYPE_LOCAL_REFERENCE:
+		if (obj_desc) {
+			switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
+			case ACPI_TYPE_LOCAL_REFERENCE:
 
-			if (obj_desc->reference.opcode != AML_INT_NAMEPATH_OP) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "(PRT[%X].Source) Need name, found reference op %X\n",
-						  index,
-						  obj_desc->reference.opcode));
+				if (obj_desc->reference.opcode !=
+				    AML_INT_NAMEPATH_OP) {
+					ACPI_ERROR((AE_INFO,
+						    "(PRT[%X].Source) Need name, found reference op %X",
+						    index,
+						    obj_desc->reference.
+						    opcode));
+					return_ACPI_STATUS(AE_BAD_DATA);
+				}
+
+				node = obj_desc->reference.node;
+
+				/* Use *remaining* length of the buffer as max for pathname */
+
+				path_buffer.length = output_buffer->length -
+				    (u32) ((u8 *) user_prt->source -
+					   (u8 *) output_buffer->pointer);
+				path_buffer.pointer = user_prt->source;
+
+				status =
+				    acpi_ns_handle_to_pathname((acpi_handle)
+							       node,
+							       &path_buffer);
+
+				/* +1 to include null terminator */
+
+				user_prt->length +=
+				    (u32) ACPI_STRLEN(user_prt->source) + 1;
+				break;
+
+			case ACPI_TYPE_STRING:
+
+				ACPI_STRCPY(user_prt->source,
+					    obj_desc->string.pointer);
+
+				/*
+				 * Add to the Length field the length of the string
+				 * (add 1 for terminator)
+				 */
+				user_prt->length += obj_desc->string.length + 1;
+				break;
+
+			case ACPI_TYPE_INTEGER:
+				/*
+				 * If this is a number, then the Source Name is NULL, since the
+				 * entire buffer was zeroed out, we can leave this alone.
+				 *
+				 * Add to the Length field the length of the u32 NULL
+				 */
+				user_prt->length += sizeof(u32);
+				break;
+
+			default:
+
+				ACPI_ERROR((AE_INFO,
+					    "(PRT[%X].Source) Need Ref/String/Integer, found %s",
+					    index,
+					    acpi_ut_get_object_type_name
+					    (obj_desc)));
 				return_ACPI_STATUS(AE_BAD_DATA);
 			}
-
-			node = obj_desc->reference.node;
-
-			/* Use *remaining* length of the buffer as max for pathname */
-
-			path_buffer.length = output_buffer->length -
-			    (u32) ((u8 *) user_prt->source -
-				   (u8 *) output_buffer->pointer);
-			path_buffer.pointer = user_prt->source;
-
-			status =
-			    acpi_ns_handle_to_pathname((acpi_handle) node,
-						       &path_buffer);
-
-			/* +1 to include null terminator */
-
-			user_prt->length +=
-			    (u32) ACPI_STRLEN(user_prt->source) + 1;
-			break;
-
-		case ACPI_TYPE_STRING:
-
-			ACPI_STRCPY(user_prt->source, obj_desc->string.pointer);
-
-			/*
-			 * Add to the Length field the length of the string
-			 * (add 1 for terminator)
-			 */
-			user_prt->length += obj_desc->string.length + 1;
-			break;
-
-		case ACPI_TYPE_INTEGER:
-			/*
-			 * If this is a number, then the Source Name is NULL, since the
-			 * entire buffer was zeroed out, we can leave this alone.
-			 *
-			 * Add to the Length field the length of the u32 NULL
-			 */
-			user_prt->length += sizeof(u32);
-			break;
-
-		default:
-
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "(PRT[%X].Source) Need Ref/String/Integer, found %s\n",
-					  index,
-					  acpi_ut_get_object_type_name
-					  (obj_desc)));
-			return_ACPI_STATUS(AE_BAD_DATA);
 		}
 
 		/* Now align the current length */
@@ -340,11 +340,10 @@
 		if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
 			user_prt->source_index = (u32) obj_desc->integer.value;
 		} else {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "(PRT[%X].source_index) Need Integer, found %s\n",
-					  index,
-					  acpi_ut_get_object_type_name
-					  (obj_desc)));
+			ACPI_ERROR((AE_INFO,
+				    "(PRT[%X].source_index) Need Integer, found %s",
+				    index,
+				    acpi_ut_get_object_type_name(obj_desc)));
 			return_ACPI_STATUS(AE_BAD_DATA);
 		}
 
@@ -360,7 +359,7 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_create_byte_stream
+ * FUNCTION:    acpi_rs_create_aml_resources
  *
  * PARAMETERS:  linked_list_buffer      - Pointer to the resource linked list
  *              output_buffer           - Pointer to the user's buffer
@@ -377,13 +376,13 @@
  ******************************************************************************/
 
 acpi_status
-acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer,
-			   struct acpi_buffer *output_buffer)
+acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
+			     struct acpi_buffer *output_buffer)
 {
 	acpi_status status;
-	acpi_size byte_stream_size_needed = 0;
+	acpi_size aml_size_needed = 0;
 
-	ACPI_FUNCTION_TRACE("rs_create_byte_stream");
+	ACPI_FUNCTION_TRACE("rs_create_aml_resources");
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "linked_list_buffer = %p\n",
 			  linked_list_buffer));
@@ -394,11 +393,10 @@
 	 * Pass the linked_list_buffer into a module that calculates
 	 * the buffer size needed for the byte stream.
 	 */
-	status = acpi_rs_get_byte_stream_length(linked_list_buffer,
-						&byte_stream_size_needed);
+	status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_size_needed=%X, %s\n",
-			  (u32) byte_stream_size_needed,
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_size_needed=%X, %s\n",
+			  (u32) aml_size_needed,
 			  acpi_format_exception(status)));
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
@@ -406,8 +404,7 @@
 
 	/* Validate/Allocate/Clear caller buffer */
 
-	status =
-	    acpi_ut_initialize_buffer(output_buffer, byte_stream_size_needed);
+	status = acpi_ut_initialize_buffer(output_buffer, aml_size_needed);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
@@ -415,9 +412,9 @@
 	/* Do the conversion */
 
 	status =
-	    acpi_rs_list_to_byte_stream(linked_list_buffer,
-					byte_stream_size_needed,
-					output_buffer->pointer);
+	    acpi_rs_convert_resources_to_aml(linked_list_buffer,
+					     aml_size_needed,
+					     output_buffer->pointer);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
index 75bd34d..e7de061 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,914 +49,544 @@
 
 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
 /* Local prototypes */
-static void acpi_rs_dump_irq(union acpi_resource_data *data);
+static void acpi_rs_out_string(char *title, char *value);
 
-static void acpi_rs_dump_address16(union acpi_resource_data *data);
+static void acpi_rs_out_integer8(char *title, u8 value);
 
-static void acpi_rs_dump_address32(union acpi_resource_data *data);
+static void acpi_rs_out_integer16(char *title, u16 value);
 
-static void acpi_rs_dump_address64(union acpi_resource_data *data);
+static void acpi_rs_out_integer32(char *title, u32 value);
 
-static void acpi_rs_dump_dma(union acpi_resource_data *data);
+static void acpi_rs_out_integer64(char *title, u64 value);
 
-static void acpi_rs_dump_io(union acpi_resource_data *data);
+static void acpi_rs_out_title(char *title);
 
-static void acpi_rs_dump_extended_irq(union acpi_resource_data *data);
+static void acpi_rs_dump_byte_list(u16 length, u8 * data);
 
-static void acpi_rs_dump_fixed_io(union acpi_resource_data *data);
+static void acpi_rs_dump_dword_list(u8 length, u32 * data);
 
-static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data);
+static void acpi_rs_dump_short_byte_list(u8 length, u8 * data);
 
-static void acpi_rs_dump_memory24(union acpi_resource_data *data);
+static void
+acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source);
 
-static void acpi_rs_dump_memory32(union acpi_resource_data *data);
+static void acpi_rs_dump_address_common(union acpi_resource_data *resource);
 
-static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data);
+static void
+acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table);
 
-static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data);
+#define ACPI_RSD_OFFSET(f)          (u8) ACPI_OFFSET (union acpi_resource_data,f)
+#define ACPI_PRT_OFFSET(f)          (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f)
+#define ACPI_RSD_TABLE_SIZE(name)   (sizeof(name) / sizeof (struct acpi_rsdump_info))
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_dump_irq
+ * Resource Descriptor info tables
  *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
+ * Note: The first table entry must be a Title or Literal and must contain
+ * the table length (number of table entries)
+ *
+ ******************************************************************************/
+
+struct acpi_rsdump_info acpi_rs_dump_irq[6] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering",
+	 acpi_gbl_HEdecode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity",
+	 acpi_gbl_LLdecode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing",
+	 acpi_gbl_SHRdecode},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count),
+	 "Interrupt Count", NULL},
+	{ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]),
+	 "Interrupt List", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_dma[6] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL},
+	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed",
+	 acpi_gbl_TYPdecode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering",
+	 acpi_gbl_BMdecode},
+	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type",
+	 acpi_gbl_SIZdecode},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count",
+	 NULL},
+	{ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List",
+	 NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_start_dpf[3] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf),
+	 "Start-Dependent-Functions", NULL},
+	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority),
+	 "Compatibility Priority", acpi_gbl_config_decode},
+	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness),
+	 "Performance/Robustness", acpi_gbl_config_decode}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf),
+	 "End-Dependent-Functions", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_io[6] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding",
+	 acpi_gbl_io_decode},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length",
+	 NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io),
+	 "Fixed I/O", NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length),
+	 "Address Length", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_vendor[3] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor),
+	 "Vendor Specific", NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL},
+	{ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data",
+	 NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "end_tag",
+	 NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_memory24[6] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24),
+	 "24-Bit Memory Range", NULL},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect),
+	 "Write Protect", acpi_gbl_RWdecode},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum",
+	 NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum",
+	 NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment",
+	 NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length),
+	 "Address Length", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_memory32[6] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32),
+	 "32-Bit Memory Range", NULL},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect),
+	 "Write Protect", acpi_gbl_RWdecode},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum",
+	 NULL},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum",
+	 NULL},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment",
+	 NULL},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length),
+	 "Address Length", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32),
+	 "32-Bit Fixed Memory Range", NULL},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect),
+	 "Write Protect", acpi_gbl_RWdecode},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address",
+	 NULL},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length),
+	 "Address Length", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_address16[8] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16),
+	 "16-Bit WORD Address Space", NULL},
+	{ACPI_RSD_ADDRESS, 0, NULL, NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity",
+	 NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum",
+	 NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum",
+	 NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset),
+	 "Translation Offset", NULL},
+	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length),
+	 "Address Length", NULL},
+	{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_address32[8] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32),
+	 "32-Bit DWORD Address Space", NULL},
+	{ACPI_RSD_ADDRESS, 0, NULL, NULL},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity",
+	 NULL},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum",
+	 NULL},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum",
+	 NULL},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset),
+	 "Translation Offset", NULL},
+	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length),
+	 "Address Length", NULL},
+	{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_address64[8] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64),
+	 "64-Bit QWORD Address Space", NULL},
+	{ACPI_RSD_ADDRESS, 0, NULL, NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity",
+	 NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum",
+	 NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum",
+	 NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset),
+	 "Translation Offset", NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length),
+	 "Address Length", NULL},
+	{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64),
+	 "64-Bit Extended Address Space", NULL},
+	{ACPI_RSD_ADDRESS, 0, NULL, NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity),
+	 "Granularity", NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum),
+	 "Address Minimum", NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum),
+	 "Address Maximum", NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset),
+	 "Translation Offset", NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length),
+	 "Address Length", NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific),
+	 "Type-Specific Attribute", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq),
+	 "Extended IRQ", NULL},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer),
+	 "Type", acpi_gbl_consume_decode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering),
+	 "Triggering", acpi_gbl_HEdecode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity",
+	 acpi_gbl_LLdecode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing",
+	 acpi_gbl_SHRdecode},
+	{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL,
+	 NULL},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count),
+	 "Interrupt Count", NULL},
+	{ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]),
+	 "Interrupt List", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg),
+	 "Generic Register", NULL},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID",
+	 NULL},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width",
+	 NULL},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset",
+	 NULL},
+	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size),
+	 "Access Size", NULL},
+	{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL}
+};
+
+/*
+ * Tables used for common address descriptor flag fields
+ */
+static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL,
+	 NULL},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer),
+	 "Consumer/Producer", acpi_gbl_consume_decode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode",
+	 acpi_gbl_DECdecode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed),
+	 "Min Relocatability", acpi_gbl_min_decode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed),
+	 "Max Relocatability", acpi_gbl_max_decode}
+};
+
+static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = {
+	{ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags),
+	 "Resource Type", (void *)"Memory Range"},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect),
+	 "Write Protect", acpi_gbl_RWdecode},
+	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching),
+	 "Caching", acpi_gbl_MEMdecode},
+	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type),
+	 "Range Type", acpi_gbl_MTPdecode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation),
+	 "Translation", acpi_gbl_TTPdecode}
+};
+
+static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = {
+	{ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags),
+	 "Resource Type", (void *)"I/O Range"},
+	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type),
+	 "Range Type", acpi_gbl_RNGdecode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation),
+	 "Translation", acpi_gbl_TTPdecode},
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type),
+	 "Translation Type", acpi_gbl_TRSdecode}
+};
+
+/*
+ * Table used to dump _PRT contents
+ */
+static struct acpi_rsdump_info acpi_rs_dump_prt[5] = {
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL},
+	{ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL},
+	{ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL},
+	{ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL},
+	{ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL}
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_dump_descriptor
+ *
+ * PARAMETERS:  Resource
  *
  * RETURN:      None
  *
- * DESCRIPTION: Prints out the various members of the Data structure type.
+ * DESCRIPTION:
  *
  ******************************************************************************/
 
-static void acpi_rs_dump_irq(union acpi_resource_data *data)
+static void
+acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
 {
-	struct acpi_resource_irq *irq_data = (struct acpi_resource_irq *)data;
-	u8 index = 0;
+	u8 *target = NULL;
+	u8 *previous_target;
+	char *name;
+	u8 count;
 
-	ACPI_FUNCTION_ENTRY();
+	/* First table entry must contain the table length (# of table entries) */
 
-	acpi_os_printf("IRQ Resource\n");
+	count = table->offset;
 
-	acpi_os_printf("  %s Triggered\n",
-		       ACPI_LEVEL_SENSITIVE ==
-		       irq_data->edge_level ? "Level" : "Edge");
+	while (count) {
+		previous_target = target;
+		target = ACPI_ADD_PTR(u8, resource, table->offset);
+		name = table->name;
 
-	acpi_os_printf("  Active %s\n",
-		       ACPI_ACTIVE_LOW ==
-		       irq_data->active_high_low ? "Low" : "High");
-
-	acpi_os_printf("  %s\n",
-		       ACPI_SHARED ==
-		       irq_data->shared_exclusive ? "Shared" : "Exclusive");
-
-	acpi_os_printf("  %X Interrupts ( ", irq_data->number_of_interrupts);
-
-	for (index = 0; index < irq_data->number_of_interrupts; index++) {
-		acpi_os_printf("%X ", irq_data->interrupts[index]);
-	}
-
-	acpi_os_printf(")\n");
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_dma
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_dma(union acpi_resource_data *data)
-{
-	struct acpi_resource_dma *dma_data = (struct acpi_resource_dma *)data;
-	u8 index = 0;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("DMA Resource\n");
-
-	switch (dma_data->type) {
-	case ACPI_COMPATIBILITY:
-		acpi_os_printf("  Compatibility mode\n");
-		break;
-
-	case ACPI_TYPE_A:
-		acpi_os_printf("  Type A\n");
-		break;
-
-	case ACPI_TYPE_B:
-		acpi_os_printf("  Type B\n");
-		break;
-
-	case ACPI_TYPE_F:
-		acpi_os_printf("  Type F\n");
-		break;
-
-	default:
-		acpi_os_printf("  Invalid DMA type\n");
-		break;
-	}
-
-	acpi_os_printf("  %sBus Master\n",
-		       ACPI_BUS_MASTER == dma_data->bus_master ? "" : "Not a ");
-
-	switch (dma_data->transfer) {
-	case ACPI_TRANSFER_8:
-		acpi_os_printf("  8-bit only transfer\n");
-		break;
-
-	case ACPI_TRANSFER_8_16:
-		acpi_os_printf("  8 and 16-bit transfer\n");
-		break;
-
-	case ACPI_TRANSFER_16:
-		acpi_os_printf("  16 bit only transfer\n");
-		break;
-
-	default:
-		acpi_os_printf("  Invalid transfer preference\n");
-		break;
-	}
-
-	acpi_os_printf("  Number of Channels: %X ( ",
-		       dma_data->number_of_channels);
-
-	for (index = 0; index < dma_data->number_of_channels; index++) {
-		acpi_os_printf("%X ", dma_data->channels[index]);
-	}
-
-	acpi_os_printf(")\n");
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_start_depend_fns
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data)
-{
-	struct acpi_resource_start_dpf *sdf_data =
-	    (struct acpi_resource_start_dpf *)data;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("Start Dependent Functions Resource\n");
-
-	switch (sdf_data->compatibility_priority) {
-	case ACPI_GOOD_CONFIGURATION:
-		acpi_os_printf("  Good configuration\n");
-		break;
-
-	case ACPI_ACCEPTABLE_CONFIGURATION:
-		acpi_os_printf("  Acceptable configuration\n");
-		break;
-
-	case ACPI_SUB_OPTIMAL_CONFIGURATION:
-		acpi_os_printf("  Sub-optimal configuration\n");
-		break;
-
-	default:
-		acpi_os_printf("  Invalid compatibility priority\n");
-		break;
-	}
-
-	switch (sdf_data->performance_robustness) {
-	case ACPI_GOOD_CONFIGURATION:
-		acpi_os_printf("  Good configuration\n");
-		break;
-
-	case ACPI_ACCEPTABLE_CONFIGURATION:
-		acpi_os_printf("  Acceptable configuration\n");
-		break;
-
-	case ACPI_SUB_OPTIMAL_CONFIGURATION:
-		acpi_os_printf("  Sub-optimal configuration\n");
-		break;
-
-	default:
-		acpi_os_printf("  Invalid performance robustness preference\n");
-		break;
-	}
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_io
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_io(union acpi_resource_data *data)
-{
-	struct acpi_resource_io *io_data = (struct acpi_resource_io *)data;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("Io Resource\n");
-
-	acpi_os_printf("  %d bit decode\n",
-		       ACPI_DECODE_16 == io_data->io_decode ? 16 : 10);
-
-	acpi_os_printf("  Range minimum base: %08X\n",
-		       io_data->min_base_address);
-
-	acpi_os_printf("  Range maximum base: %08X\n",
-		       io_data->max_base_address);
-
-	acpi_os_printf("  Alignment: %08X\n", io_data->alignment);
-
-	acpi_os_printf("  Range Length: %08X\n", io_data->range_length);
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_fixed_io
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_fixed_io(union acpi_resource_data *data)
-{
-	struct acpi_resource_fixed_io *fixed_io_data =
-	    (struct acpi_resource_fixed_io *)data;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("Fixed Io Resource\n");
-	acpi_os_printf("  Range base address: %08X",
-		       fixed_io_data->base_address);
-
-	acpi_os_printf("  Range length: %08X", fixed_io_data->range_length);
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_vendor_specific
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data)
-{
-	struct acpi_resource_vendor *vendor_data =
-	    (struct acpi_resource_vendor *)data;
-	u16 index = 0;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("Vendor Specific Resource\n");
-
-	acpi_os_printf("  Length: %08X\n", vendor_data->length);
-
-	for (index = 0; index < vendor_data->length; index++) {
-		acpi_os_printf("  Byte %X: %08X\n",
-			       index, vendor_data->reserved[index]);
-	}
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_memory24
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_memory24(union acpi_resource_data *data)
-{
-	struct acpi_resource_mem24 *memory24_data =
-	    (struct acpi_resource_mem24 *)data;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("24-Bit Memory Range Resource\n");
-
-	acpi_os_printf("  Read%s\n",
-		       ACPI_READ_WRITE_MEMORY ==
-		       memory24_data->read_write_attribute ?
-		       "/Write" : " only");
-
-	acpi_os_printf("  Range minimum base: %08X\n",
-		       memory24_data->min_base_address);
-
-	acpi_os_printf("  Range maximum base: %08X\n",
-		       memory24_data->max_base_address);
-
-	acpi_os_printf("  Alignment: %08X\n", memory24_data->alignment);
-
-	acpi_os_printf("  Range length: %08X\n", memory24_data->range_length);
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_memory32
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_memory32(union acpi_resource_data *data)
-{
-	struct acpi_resource_mem32 *memory32_data =
-	    (struct acpi_resource_mem32 *)data;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("32-Bit Memory Range Resource\n");
-
-	acpi_os_printf("  Read%s\n",
-		       ACPI_READ_WRITE_MEMORY ==
-		       memory32_data->read_write_attribute ?
-		       "/Write" : " only");
-
-	acpi_os_printf("  Range minimum base: %08X\n",
-		       memory32_data->min_base_address);
-
-	acpi_os_printf("  Range maximum base: %08X\n",
-		       memory32_data->max_base_address);
-
-	acpi_os_printf("  Alignment: %08X\n", memory32_data->alignment);
-
-	acpi_os_printf("  Range length: %08X\n", memory32_data->range_length);
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_fixed_memory32
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data)
-{
-	struct acpi_resource_fixed_mem32 *fixed_memory32_data =
-	    (struct acpi_resource_fixed_mem32 *)data;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("32-Bit Fixed Location Memory Range Resource\n");
-
-	acpi_os_printf("  Read%s\n",
-		       ACPI_READ_WRITE_MEMORY ==
-		       fixed_memory32_data->
-		       read_write_attribute ? "/Write" : " Only");
-
-	acpi_os_printf("  Range base address: %08X\n",
-		       fixed_memory32_data->range_base_address);
-
-	acpi_os_printf("  Range length: %08X\n",
-		       fixed_memory32_data->range_length);
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_address16
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_address16(union acpi_resource_data *data)
-{
-	struct acpi_resource_address16 *address16_data =
-	    (struct acpi_resource_address16 *)data;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("16-Bit Address Space Resource\n");
-	acpi_os_printf("  Resource Type: ");
-
-	switch (address16_data->resource_type) {
-	case ACPI_MEMORY_RANGE:
-
-		acpi_os_printf("Memory Range\n");
-
-		switch (address16_data->attribute.memory.cache_attribute) {
-		case ACPI_NON_CACHEABLE_MEMORY:
-			acpi_os_printf
-			    ("  Type Specific: Noncacheable memory\n");
+		switch (table->opcode) {
+		case ACPI_RSD_TITLE:
+			/*
+			 * Optional resource title
+			 */
+			if (table->name) {
+				acpi_os_printf("%s Resource\n", name);
+			}
 			break;
 
-		case ACPI_CACHABLE_MEMORY:
-			acpi_os_printf("  Type Specific: Cacheable memory\n");
+			/* Strings */
+
+		case ACPI_RSD_LITERAL:
+			acpi_rs_out_string(name,
+					   ACPI_CAST_PTR(char, table->pointer));
 			break;
 
-		case ACPI_WRITE_COMBINING_MEMORY:
-			acpi_os_printf
-			    ("  Type Specific: Write-combining memory\n");
+		case ACPI_RSD_STRING:
+			acpi_rs_out_string(name, ACPI_CAST_PTR(char, target));
 			break;
 
-		case ACPI_PREFETCHABLE_MEMORY:
-			acpi_os_printf
-			    ("  Type Specific: Prefetchable memory\n");
+			/* Data items, 8/16/32/64 bit */
+
+		case ACPI_RSD_UINT8:
+			acpi_rs_out_integer8(name, ACPI_GET8(target));
+			break;
+
+		case ACPI_RSD_UINT16:
+			acpi_rs_out_integer16(name, ACPI_GET16(target));
+			break;
+
+		case ACPI_RSD_UINT32:
+			acpi_rs_out_integer32(name, ACPI_GET32(target));
+			break;
+
+		case ACPI_RSD_UINT64:
+			acpi_rs_out_integer64(name, ACPI_GET64(target));
+			break;
+
+			/* Flags: 1-bit and 2-bit flags supported */
+
+		case ACPI_RSD_1BITFLAG:
+			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
+							       table->
+							       pointer[*target &
+								       0x01]));
+			break;
+
+		case ACPI_RSD_2BITFLAG:
+			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
+							       table->
+							       pointer[*target &
+								       0x03]));
+			break;
+
+		case ACPI_RSD_SHORTLIST:
+			/*
+			 * Short byte list (single line output) for DMA and IRQ resources
+			 * Note: The list length is obtained from the previous table entry
+			 */
+			if (previous_target) {
+				acpi_rs_out_title(name);
+				acpi_rs_dump_short_byte_list(*previous_target,
+							     target);
+			}
+			break;
+
+		case ACPI_RSD_LONGLIST:
+			/*
+			 * Long byte list for Vendor resource data
+			 * Note: The list length is obtained from the previous table entry
+			 */
+			if (previous_target) {
+				acpi_rs_dump_byte_list(ACPI_GET16
+						       (previous_target),
+						       target);
+			}
+			break;
+
+		case ACPI_RSD_DWORDLIST:
+			/*
+			 * Dword list for Extended Interrupt resources
+			 * Note: The list length is obtained from the previous table entry
+			 */
+			if (previous_target) {
+				acpi_rs_dump_dword_list(*previous_target,
+							ACPI_CAST_PTR(u32,
+								      target));
+			}
+			break;
+
+		case ACPI_RSD_ADDRESS:
+			/*
+			 * Common flags for all Address resources
+			 */
+			acpi_rs_dump_address_common(ACPI_CAST_PTR
+						    (union acpi_resource_data,
+						     target));
+			break;
+
+		case ACPI_RSD_SOURCE:
+			/*
+			 * Optional resource_source for Address resources
+			 */
+			acpi_rs_dump_resource_source(ACPI_CAST_PTR
+						     (struct
+						      acpi_resource_source,
+						      target));
 			break;
 
 		default:
-			acpi_os_printf
-			    ("  Type Specific: Invalid cache attribute\n");
-			break;
+			acpi_os_printf("**** Invalid table opcode [%X] ****\n",
+				       table->opcode);
+			return;
 		}
 
-		acpi_os_printf("  Type Specific: Read%s\n",
-			       ACPI_READ_WRITE_MEMORY ==
-			       address16_data->attribute.memory.
-			       read_write_attribute ? "/Write" : " Only");
+		table++;
+		count--;
+	}
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_dump_resource_source
+ *
+ * PARAMETERS:  resource_source     - Pointer to a Resource Source struct
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Common routine for dumping the optional resource_source and the
+ *              corresponding resource_source_index.
+ *
+ ******************************************************************************/
+
+static void
+acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source)
+{
+	ACPI_FUNCTION_ENTRY();
+
+	if (resource_source->index == 0xFF) {
+		return;
+	}
+
+	acpi_rs_out_integer8("Resource Source Index", resource_source->index);
+
+	acpi_rs_out_string("Resource Source",
+			   resource_source->string_ptr ?
+			   resource_source->string_ptr : "[Not Specified]");
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_dump_address_common
+ *
+ * PARAMETERS:  Resource        - Pointer to an internal resource descriptor
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Dump the fields that are common to all Address resource
+ *              descriptors
+ *
+ ******************************************************************************/
+
+static void acpi_rs_dump_address_common(union acpi_resource_data *resource)
+{
+	ACPI_FUNCTION_ENTRY();
+
+	/* Decode the type-specific flags */
+
+	switch (resource->address.resource_type) {
+	case ACPI_MEMORY_RANGE:
+
+		acpi_rs_dump_descriptor(resource, acpi_rs_dump_memory_flags);
 		break;
 
 	case ACPI_IO_RANGE:
 
-		acpi_os_printf("I/O Range\n");
-
-		switch (address16_data->attribute.io.range_attribute) {
-		case ACPI_NON_ISA_ONLY_RANGES:
-			acpi_os_printf
-			    ("  Type Specific: Non-ISA Io Addresses\n");
-			break;
-
-		case ACPI_ISA_ONLY_RANGES:
-			acpi_os_printf("  Type Specific: ISA Io Addresses\n");
-			break;
-
-		case ACPI_ENTIRE_RANGE:
-			acpi_os_printf
-			    ("  Type Specific: ISA and non-ISA Io Addresses\n");
-			break;
-
-		default:
-			acpi_os_printf
-			    ("  Type Specific: Invalid range attribute\n");
-			break;
-		}
-
-		acpi_os_printf("  Type Specific: %s Translation\n",
-			       ACPI_SPARSE_TRANSLATION ==
-			       address16_data->attribute.io.
-			       translation_attribute ? "Sparse" : "Dense");
+		acpi_rs_dump_descriptor(resource, acpi_rs_dump_io_flags);
 		break;
 
 	case ACPI_BUS_NUMBER_RANGE:
 
-		acpi_os_printf("Bus Number Range\n");
+		acpi_rs_out_string("Resource Type", "Bus Number Range");
 		break;
 
 	default:
 
-		acpi_os_printf("0x%2.2X\n", address16_data->resource_type);
+		acpi_rs_out_integer8("Resource Type",
+				     (u8) resource->address.resource_type);
 		break;
 	}
 
-	acpi_os_printf("  Resource %s\n",
-		       ACPI_CONSUMER == address16_data->producer_consumer ?
-		       "Consumer" : "Producer");
+	/* Decode the general flags */
 
-	acpi_os_printf("  %s decode\n",
-		       ACPI_SUB_DECODE == address16_data->decode ?
-		       "Subtractive" : "Positive");
-
-	acpi_os_printf("  Min address is %s fixed\n",
-		       ACPI_ADDRESS_FIXED == address16_data->min_address_fixed ?
-		       "" : "not");
-
-	acpi_os_printf("  Max address is %s fixed\n",
-		       ACPI_ADDRESS_FIXED == address16_data->max_address_fixed ?
-		       "" : "not");
-
-	acpi_os_printf("  Granularity: %08X\n", address16_data->granularity);
-
-	acpi_os_printf("  Address range min: %08X\n",
-		       address16_data->min_address_range);
-
-	acpi_os_printf("  Address range max: %08X\n",
-		       address16_data->max_address_range);
-
-	acpi_os_printf("  Address translation offset: %08X\n",
-		       address16_data->address_translation_offset);
-
-	acpi_os_printf("  Address Length: %08X\n",
-		       address16_data->address_length);
-
-	if (0xFF != address16_data->resource_source.index) {
-		acpi_os_printf("  Resource Source Index: %X\n",
-			       address16_data->resource_source.index);
-
-		acpi_os_printf("  Resource Source: %s\n",
-			       address16_data->resource_source.string_ptr);
-	}
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_address32
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_address32(union acpi_resource_data *data)
-{
-	struct acpi_resource_address32 *address32_data =
-	    (struct acpi_resource_address32 *)data;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("32-Bit Address Space Resource\n");
-
-	switch (address32_data->resource_type) {
-	case ACPI_MEMORY_RANGE:
-
-		acpi_os_printf("  Resource Type: Memory Range\n");
-
-		switch (address32_data->attribute.memory.cache_attribute) {
-		case ACPI_NON_CACHEABLE_MEMORY:
-			acpi_os_printf
-			    ("  Type Specific: Noncacheable memory\n");
-			break;
-
-		case ACPI_CACHABLE_MEMORY:
-			acpi_os_printf("  Type Specific: Cacheable memory\n");
-			break;
-
-		case ACPI_WRITE_COMBINING_MEMORY:
-			acpi_os_printf
-			    ("  Type Specific: Write-combining memory\n");
-			break;
-
-		case ACPI_PREFETCHABLE_MEMORY:
-			acpi_os_printf
-			    ("  Type Specific: Prefetchable memory\n");
-			break;
-
-		default:
-			acpi_os_printf
-			    ("  Type Specific: Invalid cache attribute\n");
-			break;
-		}
-
-		acpi_os_printf("  Type Specific: Read%s\n",
-			       ACPI_READ_WRITE_MEMORY ==
-			       address32_data->attribute.memory.
-			       read_write_attribute ? "/Write" : " Only");
-		break;
-
-	case ACPI_IO_RANGE:
-
-		acpi_os_printf("  Resource Type: Io Range\n");
-
-		switch (address32_data->attribute.io.range_attribute) {
-		case ACPI_NON_ISA_ONLY_RANGES:
-			acpi_os_printf
-			    ("  Type Specific: Non-ISA Io Addresses\n");
-			break;
-
-		case ACPI_ISA_ONLY_RANGES:
-			acpi_os_printf("  Type Specific: ISA Io Addresses\n");
-			break;
-
-		case ACPI_ENTIRE_RANGE:
-			acpi_os_printf
-			    ("  Type Specific: ISA and non-ISA Io Addresses\n");
-			break;
-
-		default:
-			acpi_os_printf
-			    ("  Type Specific: Invalid Range attribute");
-			break;
-		}
-
-		acpi_os_printf("  Type Specific: %s Translation\n",
-			       ACPI_SPARSE_TRANSLATION ==
-			       address32_data->attribute.io.
-			       translation_attribute ? "Sparse" : "Dense");
-		break;
-
-	case ACPI_BUS_NUMBER_RANGE:
-
-		acpi_os_printf("  Resource Type: Bus Number Range\n");
-		break;
-
-	default:
-
-		acpi_os_printf("  Resource Type: 0x%2.2X\n",
-			       address32_data->resource_type);
-		break;
-	}
-
-	acpi_os_printf("  Resource %s\n",
-		       ACPI_CONSUMER == address32_data->producer_consumer ?
-		       "Consumer" : "Producer");
-
-	acpi_os_printf("  %s decode\n",
-		       ACPI_SUB_DECODE == address32_data->decode ?
-		       "Subtractive" : "Positive");
-
-	acpi_os_printf("  Min address is %s fixed\n",
-		       ACPI_ADDRESS_FIXED == address32_data->min_address_fixed ?
-		       "" : "not ");
-
-	acpi_os_printf("  Max address is %s fixed\n",
-		       ACPI_ADDRESS_FIXED == address32_data->max_address_fixed ?
-		       "" : "not ");
-
-	acpi_os_printf("  Granularity: %08X\n", address32_data->granularity);
-
-	acpi_os_printf("  Address range min: %08X\n",
-		       address32_data->min_address_range);
-
-	acpi_os_printf("  Address range max: %08X\n",
-		       address32_data->max_address_range);
-
-	acpi_os_printf("  Address translation offset: %08X\n",
-		       address32_data->address_translation_offset);
-
-	acpi_os_printf("  Address Length: %08X\n",
-		       address32_data->address_length);
-
-	if (0xFF != address32_data->resource_source.index) {
-		acpi_os_printf("  Resource Source Index: %X\n",
-			       address32_data->resource_source.index);
-
-		acpi_os_printf("  Resource Source: %s\n",
-			       address32_data->resource_source.string_ptr);
-	}
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_address64
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_address64(union acpi_resource_data *data)
-{
-	struct acpi_resource_address64 *address64_data =
-	    (struct acpi_resource_address64 *)data;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("64-Bit Address Space Resource\n");
-
-	switch (address64_data->resource_type) {
-	case ACPI_MEMORY_RANGE:
-
-		acpi_os_printf("  Resource Type: Memory Range\n");
-
-		switch (address64_data->attribute.memory.cache_attribute) {
-		case ACPI_NON_CACHEABLE_MEMORY:
-			acpi_os_printf
-			    ("  Type Specific: Noncacheable memory\n");
-			break;
-
-		case ACPI_CACHABLE_MEMORY:
-			acpi_os_printf("  Type Specific: Cacheable memory\n");
-			break;
-
-		case ACPI_WRITE_COMBINING_MEMORY:
-			acpi_os_printf
-			    ("  Type Specific: Write-combining memory\n");
-			break;
-
-		case ACPI_PREFETCHABLE_MEMORY:
-			acpi_os_printf
-			    ("  Type Specific: Prefetchable memory\n");
-			break;
-
-		default:
-			acpi_os_printf
-			    ("  Type Specific: Invalid cache attribute\n");
-			break;
-		}
-
-		acpi_os_printf("  Type Specific: Read%s\n",
-			       ACPI_READ_WRITE_MEMORY ==
-			       address64_data->attribute.memory.
-			       read_write_attribute ? "/Write" : " Only");
-		break;
-
-	case ACPI_IO_RANGE:
-
-		acpi_os_printf("  Resource Type: Io Range\n");
-
-		switch (address64_data->attribute.io.range_attribute) {
-		case ACPI_NON_ISA_ONLY_RANGES:
-			acpi_os_printf
-			    ("  Type Specific: Non-ISA Io Addresses\n");
-			break;
-
-		case ACPI_ISA_ONLY_RANGES:
-			acpi_os_printf("  Type Specific: ISA Io Addresses\n");
-			break;
-
-		case ACPI_ENTIRE_RANGE:
-			acpi_os_printf
-			    ("  Type Specific: ISA and non-ISA Io Addresses\n");
-			break;
-
-		default:
-			acpi_os_printf
-			    ("  Type Specific: Invalid Range attribute");
-			break;
-		}
-
-		acpi_os_printf("  Type Specific: %s Translation\n",
-			       ACPI_SPARSE_TRANSLATION ==
-			       address64_data->attribute.io.
-			       translation_attribute ? "Sparse" : "Dense");
-		break;
-
-	case ACPI_BUS_NUMBER_RANGE:
-
-		acpi_os_printf("  Resource Type: Bus Number Range\n");
-		break;
-
-	default:
-
-		acpi_os_printf("  Resource Type: 0x%2.2X\n",
-			       address64_data->resource_type);
-		break;
-	}
-
-	acpi_os_printf("  Resource %s\n",
-		       ACPI_CONSUMER == address64_data->producer_consumer ?
-		       "Consumer" : "Producer");
-
-	acpi_os_printf("  %s decode\n",
-		       ACPI_SUB_DECODE == address64_data->decode ?
-		       "Subtractive" : "Positive");
-
-	acpi_os_printf("  Min address is %s fixed\n",
-		       ACPI_ADDRESS_FIXED == address64_data->min_address_fixed ?
-		       "" : "not ");
-
-	acpi_os_printf("  Max address is %s fixed\n",
-		       ACPI_ADDRESS_FIXED == address64_data->max_address_fixed ?
-		       "" : "not ");
-
-	acpi_os_printf("  Granularity: %8.8X%8.8X\n",
-		       ACPI_FORMAT_UINT64(address64_data->granularity));
-
-	acpi_os_printf("  Address range min: %8.8X%8.8X\n",
-		       ACPI_FORMAT_UINT64(address64_data->min_address_range));
-
-	acpi_os_printf("  Address range max: %8.8X%8.8X\n",
-		       ACPI_FORMAT_UINT64(address64_data->max_address_range));
-
-	acpi_os_printf("  Address translation offset: %8.8X%8.8X\n",
-		       ACPI_FORMAT_UINT64(address64_data->
-					  address_translation_offset));
-
-	acpi_os_printf("  Address Length: %8.8X%8.8X\n",
-		       ACPI_FORMAT_UINT64(address64_data->address_length));
-
-	acpi_os_printf("  Type Specific Attributes: %8.8X%8.8X\n",
-		       ACPI_FORMAT_UINT64(address64_data->
-					  type_specific_attributes));
-
-	if (0xFF != address64_data->resource_source.index) {
-		acpi_os_printf("  Resource Source Index: %X\n",
-			       address64_data->resource_source.index);
-
-		acpi_os_printf("  Resource Source: %s\n",
-			       address64_data->resource_source.string_ptr);
-	}
-
-	return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_dump_extended_irq
- *
- * PARAMETERS:  Data            - pointer to the resource structure to dump.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_extended_irq(union acpi_resource_data *data)
-{
-	struct acpi_resource_ext_irq *ext_irq_data =
-	    (struct acpi_resource_ext_irq *)data;
-	u8 index = 0;
-
-	ACPI_FUNCTION_ENTRY();
-
-	acpi_os_printf("Extended IRQ Resource\n");
-
-	acpi_os_printf("  Resource %s\n",
-		       ACPI_CONSUMER == ext_irq_data->producer_consumer ?
-		       "Consumer" : "Producer");
-
-	acpi_os_printf("  %s\n",
-		       ACPI_LEVEL_SENSITIVE == ext_irq_data->edge_level ?
-		       "Level" : "Edge");
-
-	acpi_os_printf("  Active %s\n",
-		       ACPI_ACTIVE_LOW == ext_irq_data->active_high_low ?
-		       "low" : "high");
-
-	acpi_os_printf("  %s\n",
-		       ACPI_SHARED == ext_irq_data->shared_exclusive ?
-		       "Shared" : "Exclusive");
-
-	acpi_os_printf("  Interrupts : %X ( ",
-		       ext_irq_data->number_of_interrupts);
-
-	for (index = 0; index < ext_irq_data->number_of_interrupts; index++) {
-		acpi_os_printf("%X ", ext_irq_data->interrupts[index]);
-	}
-
-	acpi_os_printf(")\n");
-
-	if (0xFF != ext_irq_data->resource_source.index) {
-		acpi_os_printf("  Resource Source Index: %X",
-			       ext_irq_data->resource_source.index);
-
-		acpi_os_printf("  Resource Source: %s",
-			       ext_irq_data->resource_source.string_ptr);
-	}
-
-	return;
+	acpi_rs_dump_descriptor(resource, acpi_rs_dump_general_flags);
 }
 
 /*******************************************************************************
  *
  * FUNCTION:    acpi_rs_dump_resource_list
  *
- * PARAMETERS:  Resource        - pointer to the resource structure to dump.
+ * PARAMETERS:  resource_list       - Pointer to a resource descriptor list
  *
  * RETURN:      None
  *
@@ -964,148 +594,175 @@
  *
  ******************************************************************************/
 
-void acpi_rs_dump_resource_list(struct acpi_resource *resource)
+void acpi_rs_dump_resource_list(struct acpi_resource *resource_list)
 {
-	u8 count = 0;
-	u8 done = FALSE;
+	u32 count = 0;
+	u32 type;
 
 	ACPI_FUNCTION_ENTRY();
 
-	if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
-		while (!done) {
-			acpi_os_printf("Resource structure %X.\n", count++);
-
-			switch (resource->id) {
-			case ACPI_RSTYPE_IRQ:
-				acpi_rs_dump_irq(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_DMA:
-				acpi_rs_dump_dma(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_START_DPF:
-				acpi_rs_dump_start_depend_fns(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_END_DPF:
-				acpi_os_printf
-				    ("end_dependent_functions Resource\n");
-				/* acpi_rs_dump_end_dependent_functions (Resource->Data); */
-				break;
-
-			case ACPI_RSTYPE_IO:
-				acpi_rs_dump_io(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_FIXED_IO:
-				acpi_rs_dump_fixed_io(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_VENDOR:
-				acpi_rs_dump_vendor_specific(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_END_TAG:
-				/*rs_dump_end_tag (Resource->Data); */
-				acpi_os_printf("end_tag Resource\n");
-				done = TRUE;
-				break;
-
-			case ACPI_RSTYPE_MEM24:
-				acpi_rs_dump_memory24(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_MEM32:
-				acpi_rs_dump_memory32(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_FIXED_MEM32:
-				acpi_rs_dump_fixed_memory32(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_ADDRESS16:
-				acpi_rs_dump_address16(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_ADDRESS32:
-				acpi_rs_dump_address32(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_ADDRESS64:
-				acpi_rs_dump_address64(&resource->data);
-				break;
-
-			case ACPI_RSTYPE_EXT_IRQ:
-				acpi_rs_dump_extended_irq(&resource->data);
-				break;
-
-			default:
-				acpi_os_printf("Invalid resource type\n");
-				break;
-
-			}
-
-			resource =
-			    ACPI_PTR_ADD(struct acpi_resource, resource,
-					 resource->length);
-		}
+	if (!(acpi_dbg_level & ACPI_LV_RESOURCES)
+	    || !(_COMPONENT & acpi_dbg_layer)) {
+		return;
 	}
 
-	return;
+	/* Walk list and dump all resource descriptors (END_TAG terminates) */
+
+	do {
+		acpi_os_printf("\n[%02X] ", count);
+		count++;
+
+		/* Validate Type before dispatch */
+
+		type = resource_list->type;
+		if (type > ACPI_RESOURCE_TYPE_MAX) {
+			acpi_os_printf
+			    ("Invalid descriptor type (%X) in resource list\n",
+			     resource_list->type);
+			return;
+		}
+
+		/* Dump the resource descriptor */
+
+		acpi_rs_dump_descriptor(&resource_list->data,
+					acpi_gbl_dump_resource_dispatch[type]);
+
+		/* Point to the next resource structure */
+
+		resource_list =
+		    ACPI_ADD_PTR(struct acpi_resource, resource_list,
+				 resource_list->length);
+
+		/* Exit when END_TAG descriptor is reached */
+
+	} while (type != ACPI_RESOURCE_TYPE_END_TAG);
 }
 
 /*******************************************************************************
  *
  * FUNCTION:    acpi_rs_dump_irq_list
  *
- * PARAMETERS:  route_table     - pointer to the routing table to dump.
+ * PARAMETERS:  route_table     - Pointer to the routing table to dump.
  *
  * RETURN:      None
  *
- * DESCRIPTION: Dispatches the structures to the correct dump routine.
+ * DESCRIPTION: Print IRQ routing table
  *
  ******************************************************************************/
 
 void acpi_rs_dump_irq_list(u8 * route_table)
 {
-	u8 *buffer = route_table;
-	u8 count = 0;
-	u8 done = FALSE;
 	struct acpi_pci_routing_table *prt_element;
+	u8 count;
 
 	ACPI_FUNCTION_ENTRY();
 
-	if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
-		prt_element =
-		    ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
-
-		while (!done) {
-			acpi_os_printf("PCI IRQ Routing Table structure %X.\n",
-				       count++);
-
-			acpi_os_printf("  Address: %8.8X%8.8X\n",
-				       ACPI_FORMAT_UINT64(prt_element->
-							  address));
-
-			acpi_os_printf("  Pin: %X\n", prt_element->pin);
-
-			acpi_os_printf("  Source: %s\n", prt_element->source);
-
-			acpi_os_printf("  source_index: %X\n",
-				       prt_element->source_index);
-
-			buffer += prt_element->length;
-			prt_element =
-			    ACPI_CAST_PTR(struct acpi_pci_routing_table,
-					  buffer);
-			if (0 == prt_element->length) {
-				done = TRUE;
-			}
-		}
+	if (!(acpi_dbg_level & ACPI_LV_RESOURCES)
+	    || !(_COMPONENT & acpi_dbg_layer)) {
+		return;
 	}
 
-	return;
+	prt_element = ACPI_CAST_PTR(struct acpi_pci_routing_table, route_table);
+
+	/* Dump all table elements, Exit on zero length element */
+
+	for (count = 0; prt_element->length; count++) {
+		acpi_os_printf("\n[%02X] PCI IRQ Routing Table Package\n",
+			       count);
+		acpi_rs_dump_descriptor(prt_element, acpi_rs_dump_prt);
+
+		prt_element = ACPI_ADD_PTR(struct acpi_pci_routing_table,
+					   prt_element, prt_element->length);
+	}
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_out*
+ *
+ * PARAMETERS:  Title       - Name of the resource field
+ *              Value       - Value of the resource field
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Miscellaneous helper functions to consistently format the
+ *              output of the resource dump routines
+ *
+ ******************************************************************************/
+
+static void acpi_rs_out_string(char *title, char *value)
+{
+	acpi_os_printf("%27s : %s", title, value);
+	if (!*value) {
+		acpi_os_printf("[NULL NAMESTRING]");
+	}
+	acpi_os_printf("\n");
+}
+
+static void acpi_rs_out_integer8(char *title, u8 value)
+{
+	acpi_os_printf("%27s : %2.2X\n", title, value);
+}
+
+static void acpi_rs_out_integer16(char *title, u16 value)
+{
+	acpi_os_printf("%27s : %4.4X\n", title, value);
+}
+
+static void acpi_rs_out_integer32(char *title, u32 value)
+{
+	acpi_os_printf("%27s : %8.8X\n", title, value);
+}
+
+static void acpi_rs_out_integer64(char *title, u64 value)
+{
+	acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value));
+}
+
+static void acpi_rs_out_title(char *title)
+{
+	acpi_os_printf("%27s : ", title);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_dump*List
+ *
+ * PARAMETERS:  Length      - Number of elements in the list
+ *              Data        - Start of the list
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Miscellaneous functions to dump lists of raw data
+ *
+ ******************************************************************************/
+
+static void acpi_rs_dump_byte_list(u16 length, u8 * data)
+{
+	u8 i;
+
+	for (i = 0; i < length; i++) {
+		acpi_os_printf("%25s%2.2X : %2.2X\n", "Byte", i, data[i]);
+	}
+}
+
+static void acpi_rs_dump_short_byte_list(u8 length, u8 * data)
+{
+	u8 i;
+
+	for (i = 0; i < length; i++) {
+		acpi_os_printf("%X ", data[i]);
+	}
+	acpi_os_printf("\n");
+}
+
+static void acpi_rs_dump_dword_list(u8 length, u32 * data)
+{
+	u8 i;
+
+	for (i = 0; i < length; i++) {
+		acpi_os_printf("%25s%2.2X : %8.8X\n", "Dword", i, data[i]);
+	}
 }
 
 #endif
diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c
new file mode 100644
index 0000000..d9ae64b
--- /dev/null
+++ b/drivers/acpi/resources/rsinfo.c
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ *
+ * Module Name: rsinfo - Dispatch and Info tables
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2006, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include <acpi/acresrc.h>
+
+#define _COMPONENT          ACPI_RESOURCES
+ACPI_MODULE_NAME("rsinfo")
+
+/*
+ * Resource dispatch and information tables. Any new resource types (either
+ * Large or Small) must be reflected in each of these tables, so they are here
+ * in one place.
+ *
+ * The tables for Large descriptors are indexed by bits 6:0 of the AML
+ * descriptor type byte. The tables for Small descriptors are indexed by
+ * bits 6:3 of the descriptor byte. The tables for internal resource
+ * descriptors are indexed by the acpi_resource_type field.
+ */
+/* Dispatch table for resource-to-AML (Set Resource) conversion functions */
+struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[] = {
+	acpi_rs_set_irq,	/* 0x00, ACPI_RESOURCE_TYPE_IRQ */
+	acpi_rs_convert_dma,	/* 0x01, ACPI_RESOURCE_TYPE_DMA */
+	acpi_rs_set_start_dpf,	/* 0x02, ACPI_RESOURCE_TYPE_START_DEPENDENT */
+	acpi_rs_convert_end_dpf,	/* 0x03, ACPI_RESOURCE_TYPE_END_DEPENDENT */
+	acpi_rs_convert_io,	/* 0x04, ACPI_RESOURCE_TYPE_IO */
+	acpi_rs_convert_fixed_io,	/* 0x05, ACPI_RESOURCE_TYPE_FIXED_IO */
+	acpi_rs_set_vendor,	/* 0x06, ACPI_RESOURCE_TYPE_VENDOR */
+	acpi_rs_convert_end_tag,	/* 0x07, ACPI_RESOURCE_TYPE_END_TAG */
+	acpi_rs_convert_memory24,	/* 0x08, ACPI_RESOURCE_TYPE_MEMORY24 */
+	acpi_rs_convert_memory32,	/* 0x09, ACPI_RESOURCE_TYPE_MEMORY32 */
+	acpi_rs_convert_fixed_memory32,	/* 0x0A, ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */
+	acpi_rs_convert_address16,	/* 0x0B, ACPI_RESOURCE_TYPE_ADDRESS16 */
+	acpi_rs_convert_address32,	/* 0x0C, ACPI_RESOURCE_TYPE_ADDRESS32 */
+	acpi_rs_convert_address64,	/* 0x0D, ACPI_RESOURCE_TYPE_ADDRESS64 */
+	acpi_rs_convert_ext_address64,	/* 0x0E, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
+	acpi_rs_convert_ext_irq,	/* 0x0F, ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
+	acpi_rs_convert_generic_reg	/* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+};
+
+/* Dispatch tables for AML-to-resource (Get Resource) conversion functions */
+
+struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = {
+	/* Small descriptors */
+
+	NULL,			/* 0x00, Reserved */
+	NULL,			/* 0x01, Reserved */
+	NULL,			/* 0x02, Reserved */
+	NULL,			/* 0x03, Reserved */
+	acpi_rs_get_irq,	/* 0x04, ACPI_RESOURCE_NAME_IRQ */
+	acpi_rs_convert_dma,	/* 0x05, ACPI_RESOURCE_NAME_DMA */
+	acpi_rs_get_start_dpf,	/* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */
+	acpi_rs_convert_end_dpf,	/* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */
+	acpi_rs_convert_io,	/* 0x08, ACPI_RESOURCE_NAME_IO */
+	acpi_rs_convert_fixed_io,	/* 0x09, ACPI_RESOURCE_NAME_FIXED_IO */
+	NULL,			/* 0x0A, Reserved */
+	NULL,			/* 0x0B, Reserved */
+	NULL,			/* 0x0C, Reserved */
+	NULL,			/* 0x0D, Reserved */
+	acpi_rs_get_vendor_small,	/* 0x0E, ACPI_RESOURCE_NAME_VENDOR_SMALL */
+	acpi_rs_convert_end_tag,	/* 0x0F, ACPI_RESOURCE_NAME_END_TAG */
+
+	/* Large descriptors */
+
+	NULL,			/* 0x00, Reserved */
+	acpi_rs_convert_memory24,	/* 0x01, ACPI_RESOURCE_NAME_MEMORY24 */
+	acpi_rs_convert_generic_reg,	/* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */
+	NULL,			/* 0x03, Reserved */
+	acpi_rs_get_vendor_large,	/* 0x04, ACPI_RESOURCE_NAME_VENDOR_LARGE */
+	acpi_rs_convert_memory32,	/* 0x05, ACPI_RESOURCE_NAME_MEMORY32 */
+	acpi_rs_convert_fixed_memory32,	/* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY32 */
+	acpi_rs_convert_address32,	/* 0x07, ACPI_RESOURCE_NAME_ADDRESS32 */
+	acpi_rs_convert_address16,	/* 0x08, ACPI_RESOURCE_NAME_ADDRESS16 */
+	acpi_rs_convert_ext_irq,	/* 0x09, ACPI_RESOURCE_NAME_EXTENDED_IRQ */
+	acpi_rs_convert_address64,	/* 0x0A, ACPI_RESOURCE_NAME_ADDRESS64 */
+	acpi_rs_convert_ext_address64	/* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */
+};
+
+#ifdef ACPI_FUTURE_USAGE
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+
+/* Dispatch table for resource dump functions */
+
+struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = {
+	acpi_rs_dump_irq,	/* ACPI_RESOURCE_TYPE_IRQ */
+	acpi_rs_dump_dma,	/* ACPI_RESOURCE_TYPE_DMA */
+	acpi_rs_dump_start_dpf,	/* ACPI_RESOURCE_TYPE_START_DEPENDENT */
+	acpi_rs_dump_end_dpf,	/* ACPI_RESOURCE_TYPE_END_DEPENDENT */
+	acpi_rs_dump_io,	/* ACPI_RESOURCE_TYPE_IO */
+	acpi_rs_dump_fixed_io,	/* ACPI_RESOURCE_TYPE_FIXED_IO */
+	acpi_rs_dump_vendor,	/* ACPI_RESOURCE_TYPE_VENDOR */
+	acpi_rs_dump_end_tag,	/* ACPI_RESOURCE_TYPE_END_TAG */
+	acpi_rs_dump_memory24,	/* ACPI_RESOURCE_TYPE_MEMORY24 */
+	acpi_rs_dump_memory32,	/* ACPI_RESOURCE_TYPE_MEMORY32 */
+	acpi_rs_dump_fixed_memory32,	/* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */
+	acpi_rs_dump_address16,	/* ACPI_RESOURCE_TYPE_ADDRESS16 */
+	acpi_rs_dump_address32,	/* ACPI_RESOURCE_TYPE_ADDRESS32 */
+	acpi_rs_dump_address64,	/* ACPI_RESOURCE_TYPE_ADDRESS64 */
+	acpi_rs_dump_ext_address64,	/* ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
+	acpi_rs_dump_ext_irq,	/* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
+	acpi_rs_dump_generic_reg,	/* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+};
+#endif
+#endif	/* ACPI_FUTURE_USAGE */
+/*
+ * Base sizes for external AML resource descriptors, indexed by internal type.
+ * Includes size of the descriptor header (1 byte for small descriptors,
+ * 3 bytes for large descriptors)
+ */
+const u8 acpi_gbl_aml_resource_sizes[] = {
+	sizeof(struct aml_resource_irq),	/* ACPI_RESOURCE_TYPE_IRQ (optional Byte 3 always created) */
+	sizeof(struct aml_resource_dma),	/* ACPI_RESOURCE_TYPE_DMA */
+	sizeof(struct aml_resource_start_dependent),	/* ACPI_RESOURCE_TYPE_START_DEPENDENT (optional Byte 1 always created) */
+	sizeof(struct aml_resource_end_dependent),	/* ACPI_RESOURCE_TYPE_END_DEPENDENT */
+	sizeof(struct aml_resource_io),	/* ACPI_RESOURCE_TYPE_IO */
+	sizeof(struct aml_resource_fixed_io),	/* ACPI_RESOURCE_TYPE_FIXED_IO */
+	sizeof(struct aml_resource_vendor_small),	/* ACPI_RESOURCE_TYPE_VENDOR */
+	sizeof(struct aml_resource_end_tag),	/* ACPI_RESOURCE_TYPE_END_TAG */
+	sizeof(struct aml_resource_memory24),	/* ACPI_RESOURCE_TYPE_MEMORY24 */
+	sizeof(struct aml_resource_memory32),	/* ACPI_RESOURCE_TYPE_MEMORY32 */
+	sizeof(struct aml_resource_fixed_memory32),	/* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */
+	sizeof(struct aml_resource_address16),	/* ACPI_RESOURCE_TYPE_ADDRESS16 */
+	sizeof(struct aml_resource_address32),	/* ACPI_RESOURCE_TYPE_ADDRESS32 */
+	sizeof(struct aml_resource_address64),	/* ACPI_RESOURCE_TYPE_ADDRESS64 */
+	sizeof(struct aml_resource_extended_address64),	/*ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
+	sizeof(struct aml_resource_extended_irq),	/* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
+	sizeof(struct aml_resource_generic_register)	/* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+};
+
+const u8 acpi_gbl_resource_struct_sizes[] = {
+	/* Small descriptors */
+
+	0,
+	0,
+	0,
+	0,
+	ACPI_RS_SIZE(struct acpi_resource_irq),
+	ACPI_RS_SIZE(struct acpi_resource_dma),
+	ACPI_RS_SIZE(struct acpi_resource_start_dependent),
+	ACPI_RS_SIZE_MIN,
+	ACPI_RS_SIZE(struct acpi_resource_io),
+	ACPI_RS_SIZE(struct acpi_resource_fixed_io),
+	0,
+	0,
+	0,
+	0,
+	ACPI_RS_SIZE(struct acpi_resource_vendor),
+	ACPI_RS_SIZE_MIN,
+
+	/* Large descriptors */
+
+	0,
+	ACPI_RS_SIZE(struct acpi_resource_memory24),
+	ACPI_RS_SIZE(struct acpi_resource_generic_register),
+	0,
+	ACPI_RS_SIZE(struct acpi_resource_vendor),
+	ACPI_RS_SIZE(struct acpi_resource_memory32),
+	ACPI_RS_SIZE(struct acpi_resource_fixed_memory32),
+	ACPI_RS_SIZE(struct acpi_resource_address32),
+	ACPI_RS_SIZE(struct acpi_resource_address16),
+	ACPI_RS_SIZE(struct acpi_resource_extended_irq),
+	ACPI_RS_SIZE(struct acpi_resource_address64),
+	ACPI_RS_SIZE(struct acpi_resource_extended_address64)
+};
diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c
index d53bbe8..ea56716 100644
--- a/drivers/acpi/resources/rsio.c
+++ b/drivers/acpi/resources/rsio.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,428 +49,206 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_io_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
+ * acpi_rs_convert_io
  *
  ******************************************************************************/
-acpi_status
-acpi_rs_io_resource(u8 * byte_stream_buffer,
-		    acpi_size * bytes_consumed,
-		    u8 ** output_buffer, acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_io);
+struct acpi_rsconvert_info acpi_rs_convert_io[5] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IO,
+	 ACPI_RS_SIZE(struct acpi_resource_io),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io)},
 
-	ACPI_FUNCTION_TRACE("rs_io_resource");
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IO,
+	 sizeof(struct aml_resource_io),
+	 0},
 
-	/* The number of bytes consumed are Constant */
+	/* Decode flag */
 
-	*bytes_consumed = 8;
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.io.io_decode),
+	 AML_OFFSET(io.flags),
+	 0},
+	/*
+	 * These fields are contiguous in both the source and destination:
+	 * Address Alignment
+	 * Length
+	 * Minimum Base Address
+	 * Maximum Base Address
+	 */
+	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.io.alignment),
+	 AML_OFFSET(io.alignment),
+	 2},
 
-	output_struct->id = ACPI_RSTYPE_IO;
-
-	/* Check Decode */
-
-	buffer += 1;
-	temp8 = *buffer;
-
-	output_struct->data.io.io_decode = temp8 & 0x01;
-
-	/* Check min_base Address */
-
-	buffer += 1;
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-	output_struct->data.io.min_base_address = temp16;
-
-	/* Check max_base Address */
-
-	buffer += 2;
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-	output_struct->data.io.max_base_address = temp16;
-
-	/* Check Base alignment */
-
-	buffer += 2;
-	temp8 = *buffer;
-
-	output_struct->data.io.alignment = temp8;
-
-	/* Check range_length */
-
-	buffer += 1;
-	temp8 = *buffer;
-
-	output_struct->data.io.range_length = temp8;
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.io.minimum),
+	 AML_OFFSET(io.minimum),
+	 2}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_fixed_io_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
+ * acpi_rs_convert_fixed_io
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_fixed_io_resource(u8 * byte_stream_buffer,
-			  acpi_size * bytes_consumed,
-			  u8 ** output_buffer, acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io);
+struct acpi_rsconvert_info acpi_rs_convert_fixed_io[4] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_IO,
+	 ACPI_RS_SIZE(struct acpi_resource_fixed_io),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_io)},
 
-	ACPI_FUNCTION_TRACE("rs_fixed_io_resource");
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_IO,
+	 sizeof(struct aml_resource_fixed_io),
+	 0},
+	/*
+	 * These fields are contiguous in both the source and destination:
+	 * Base Address
+	 * Length
+	 */
+	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_io.address_length),
+	 AML_OFFSET(fixed_io.address_length),
+	 1},
 
-	/* The number of bytes consumed are Constant */
-
-	*bytes_consumed = 4;
-
-	output_struct->id = ACPI_RSTYPE_FIXED_IO;
-
-	/* Check Range Base Address */
-
-	buffer += 1;
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-	output_struct->data.fixed_io.base_address = temp16;
-
-	/* Check range_length */
-
-	buffer += 2;
-	temp8 = *buffer;
-
-	output_struct->data.fixed_io.range_length = temp8;
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_io.address),
+	 AML_OFFSET(fixed_io.address),
+	 1}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_io_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
+ * acpi_rs_convert_generic_reg
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_io_stream(struct acpi_resource *linked_list,
-		  u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
+struct acpi_rsconvert_info acpi_rs_convert_generic_reg[4] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GENERIC_REGISTER,
+	 ACPI_RS_SIZE(struct acpi_resource_generic_register),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_generic_reg)},
 
-	ACPI_FUNCTION_TRACE("rs_io_stream");
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GENERIC_REGISTER,
+	 sizeof(struct aml_resource_generic_register),
+	 0},
+	/*
+	 * These fields are contiguous in both the source and destination:
+	 * Address Space ID
+	 * Register Bit Width
+	 * Register Bit Offset
+	 * Access Size
+	 */
+	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.generic_reg.space_id),
+	 AML_OFFSET(generic_reg.address_space_id),
+	 4},
 
-	/* The descriptor field is static */
+	/* Get the Register Address */
 
-	*buffer = 0x47;
-	buffer += 1;
-
-	/* Io Information Byte */
-
-	temp8 = (u8) (linked_list->data.io.io_decode & 0x01);
-
-	*buffer = temp8;
-	buffer += 1;
-
-	/* Set the Range minimum base address */
-
-	temp16 = (u16) linked_list->data.io.min_base_address;
-
-	ACPI_MOVE_16_TO_16(buffer, &temp16);
-	buffer += 2;
-
-	/* Set the Range maximum base address */
-
-	temp16 = (u16) linked_list->data.io.max_base_address;
-
-	ACPI_MOVE_16_TO_16(buffer, &temp16);
-	buffer += 2;
-
-	/* Set the base alignment */
-
-	temp8 = (u8) linked_list->data.io.alignment;
-
-	*buffer = temp8;
-	buffer += 1;
-
-	/* Set the range length */
-
-	temp8 = (u8) linked_list->data.io.range_length;
-
-	*buffer = temp8;
-	buffer += 1;
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.generic_reg.address),
+	 AML_OFFSET(generic_reg.address),
+	 1}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_fixed_io_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
+ * acpi_rs_convert_end_dpf
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_fixed_io_stream(struct acpi_resource *linked_list,
-			u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
+struct acpi_rsconvert_info acpi_rs_convert_end_dpf[2] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_DEPENDENT,
+	 ACPI_RS_SIZE_MIN,
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_dpf)},
 
-	ACPI_FUNCTION_TRACE("rs_fixed_io_stream");
-
-	/* The descriptor field is static */
-
-	*buffer = 0x4B;
-
-	buffer += 1;
-
-	/* Set the Range base address */
-
-	temp16 = (u16) linked_list->data.fixed_io.base_address;
-
-	ACPI_MOVE_16_TO_16(buffer, &temp16);
-	buffer += 2;
-
-	/* Set the range length */
-
-	temp8 = (u8) linked_list->data.fixed_io.range_length;
-
-	*buffer = temp8;
-	buffer += 1;
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_DEPENDENT,
+	 sizeof(struct aml_resource_end_dependent),
+	 0}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_dma_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
+ * acpi_rs_convert_end_tag
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_dma_resource(u8 * byte_stream_buffer,
-		     acpi_size * bytes_consumed,
-		     u8 ** output_buffer, acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u8 temp8 = 0;
-	u8 index;
-	u8 i;
-	acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma);
+struct acpi_rsconvert_info acpi_rs_convert_end_tag[2] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_TAG,
+	 ACPI_RS_SIZE_MIN,
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_tag)},
 
-	ACPI_FUNCTION_TRACE("rs_dma_resource");
-
-	/* The number of bytes consumed are Constant */
-
-	*bytes_consumed = 3;
-	output_struct->id = ACPI_RSTYPE_DMA;
-
-	/* Point to the 8-bits of Byte 1 */
-
-	buffer += 1;
-	temp8 = *buffer;
-
-	/* Decode the DMA channel bits */
-
-	for (i = 0, index = 0; index < 8; index++) {
-		if ((temp8 >> index) & 0x01) {
-			output_struct->data.dma.channels[i] = index;
-			i++;
-		}
-	}
-
-	/* Zero DMA channels is valid */
-
-	output_struct->data.dma.number_of_channels = i;
-	if (i > 0) {
-		/* Calculate the structure size based upon the number of interrupts */
-
-		struct_size += ((acpi_size) i - 1) * 4;
-	}
-
-	/* Point to Byte 2 */
-
-	buffer += 1;
-	temp8 = *buffer;
-
-	/* Check for transfer preference (Bits[1:0]) */
-
-	output_struct->data.dma.transfer = temp8 & 0x03;
-
-	if (0x03 == output_struct->data.dma.transfer) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Invalid DMA.Transfer preference (3)\n"));
-		return_ACPI_STATUS(AE_BAD_DATA);
-	}
-
-	/* Get bus master preference (Bit[2]) */
-
-	output_struct->data.dma.bus_master = (temp8 >> 2) & 0x01;
-
-	/* Get channel speed support (Bits[6:5]) */
-
-	output_struct->data.dma.type = (temp8 >> 5) & 0x03;
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
+	/*
+	 * Note: The checksum field is set to zero, meaning that the resource
+	 * data is treated as if the checksum operation succeeded.
+	 * (ACPI Spec 1.0b Section 6.4.2.8)
+	 */
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_TAG,
+	 sizeof(struct aml_resource_end_tag),
+	 0}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_dma_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
+ * acpi_rs_get_start_dpf
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_dma_stream(struct acpi_resource *linked_list,
-		   u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	u8 index;
+struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT,
+	 ACPI_RS_SIZE(struct acpi_resource_start_dependent),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)},
 
-	ACPI_FUNCTION_TRACE("rs_dma_stream");
+	/* Defaults for Compatibility and Performance priorities */
 
-	/* The descriptor field is static */
+	{ACPI_RSC_SET8, ACPI_RS_OFFSET(data.start_dpf.compatibility_priority),
+	 ACPI_ACCEPTABLE_CONFIGURATION,
+	 2},
 
-	*buffer = 0x2A;
-	buffer += 1;
-	temp8 = 0;
+	/* All done if there is no flag byte present in the descriptor */
 
-	/* Loop through all of the Channels and set the mask bits */
+	{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1},
 
-	for (index = 0;
-	     index < linked_list->data.dma.number_of_channels; index++) {
-		temp16 = (u16) linked_list->data.dma.channels[index];
-		temp8 |= 0x1 << temp16;
-	}
+	/* Flag byte is present, get the flags */
 
-	*buffer = temp8;
-	buffer += 1;
+	{ACPI_RSC_2BITFLAG,
+	 ACPI_RS_OFFSET(data.start_dpf.compatibility_priority),
+	 AML_OFFSET(start_dpf.flags),
+	 0},
 
-	/* Set the DMA Info */
+	{ACPI_RSC_2BITFLAG,
+	 ACPI_RS_OFFSET(data.start_dpf.performance_robustness),
+	 AML_OFFSET(start_dpf.flags),
+	 2}
+};
 
-	temp8 = (u8) ((linked_list->data.dma.type & 0x03) << 5);
-	temp8 |= ((linked_list->data.dma.bus_master & 0x01) << 2);
-	temp8 |= (linked_list->data.dma.transfer & 0x03);
+/*******************************************************************************
+ *
+ * acpi_rs_set_start_dpf
+ *
+ ******************************************************************************/
 
-	*buffer = temp8;
-	buffer += 1;
+struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = {
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT,
+	 sizeof(struct aml_resource_start_dependent),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)},
 
-	/* Return the number of bytes consumed in this operation */
+	/* Set the default flag values */
 
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_2BITFLAG,
+	 ACPI_RS_OFFSET(data.start_dpf.compatibility_priority),
+	 AML_OFFSET(start_dpf.flags),
+	 0},
+
+	{ACPI_RSC_2BITFLAG,
+	 ACPI_RS_OFFSET(data.start_dpf.performance_robustness),
+	 AML_OFFSET(start_dpf.flags),
+	 2},
+	/*
+	 * All done if flags byte is necessary -- if either priority value
+	 * is not ACPI_ACCEPTABLE_CONFIGURATION
+	 */
+	{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+	 ACPI_RS_OFFSET(data.start_dpf.compatibility_priority),
+	 ACPI_ACCEPTABLE_CONFIGURATION},
+
+	{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+	 ACPI_RS_OFFSET(data.start_dpf.performance_robustness),
+	 ACPI_ACCEPTABLE_CONFIGURATION},
+
+	/* Flag byte is not necessary */
+
+	{ACPI_RSC_LENGTH, 0, 0,
+	 sizeof(struct aml_resource_start_dependent_noprio)}
+};
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c
index 56043fe..1fa63bc 100644
--- a/drivers/acpi/resources/rsirq.c
+++ b/drivers/acpi/resources/rsirq.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,504 +49,182 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_irq_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
+ * acpi_rs_get_irq
  *
  ******************************************************************************/
-acpi_status
-acpi_rs_irq_resource(u8 * byte_stream_buffer,
-		     acpi_size * bytes_consumed,
-		     u8 ** output_buffer, acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	u8 index;
-	u8 i;
-	acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq);
+struct acpi_rsconvert_info acpi_rs_get_irq[7] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ,
+	 ACPI_RS_SIZE(struct acpi_resource_irq),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)},
 
-	ACPI_FUNCTION_TRACE("rs_irq_resource");
+	/* Get the IRQ mask (bytes 1:2) */
 
-	/*
-	 * The number of bytes consumed are contained in the descriptor
-	 * (Bits:0-1)
-	 */
-	temp8 = *buffer;
-	*bytes_consumed = (temp8 & 0x03) + 1;
-	output_struct->id = ACPI_RSTYPE_IRQ;
+	{ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]),
+	 AML_OFFSET(irq.irq_mask),
+	 ACPI_RS_OFFSET(data.irq.interrupt_count)},
 
-	/* Point to the 16-bits of Bytes 1 and 2 */
+	/* Set default flags (others are zero) */
 
-	buffer += 1;
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
+	{ACPI_RSC_SET8, ACPI_RS_OFFSET(data.irq.triggering),
+	 ACPI_EDGE_SENSITIVE,
+	 1},
 
-	output_struct->data.irq.number_of_interrupts = 0;
+	/* All done if no flag byte present in descriptor */
 
-	/* Decode the IRQ bits */
+	{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3},
 
-	for (i = 0, index = 0; index < 16; index++) {
-		if ((temp16 >> index) & 0x01) {
-			output_struct->data.irq.interrupts[i] = index;
-			i++;
-		}
-	}
+	/* Get flags: Triggering[0], Polarity[3], Sharing[4] */
 
-	/* Zero interrupts is valid */
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering),
+	 AML_OFFSET(irq.flags),
+	 0},
 
-	output_struct->data.irq.number_of_interrupts = i;
-	if (i > 0) {
-		/* Calculate the structure size based upon the number of interrupts */
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity),
+	 AML_OFFSET(irq.flags),
+	 3},
 
-		struct_size += ((acpi_size) i - 1) * 4;
-	}
-
-	/* Point to Byte 3 if it is used */
-
-	if (4 == *bytes_consumed) {
-		buffer += 2;
-		temp8 = *buffer;
-
-		/* Check for HE, LL interrupts */
-
-		switch (temp8 & 0x09) {
-		case 0x01:	/* HE */
-			output_struct->data.irq.edge_level =
-			    ACPI_EDGE_SENSITIVE;
-			output_struct->data.irq.active_high_low =
-			    ACPI_ACTIVE_HIGH;
-			break;
-
-		case 0x08:	/* LL */
-			output_struct->data.irq.edge_level =
-			    ACPI_LEVEL_SENSITIVE;
-			output_struct->data.irq.active_high_low =
-			    ACPI_ACTIVE_LOW;
-			break;
-
-		default:
-			/*
-			 * Only _LL and _HE polarity/trigger interrupts
-			 * are allowed (ACPI spec, section "IRQ Format")
-			 * so 0x00 and 0x09 are illegal.
-			 */
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Invalid interrupt polarity/trigger in resource list, %X\n",
-					  temp8));
-			return_ACPI_STATUS(AE_BAD_DATA);
-		}
-
-		/* Check for sharable */
-
-		output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01;
-	} else {
-		/*
-		 * Assume Edge Sensitive, Active High, Non-Sharable
-		 * per ACPI Specification
-		 */
-		output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE;
-		output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH;
-		output_struct->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
-	}
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable),
+	 AML_OFFSET(irq.flags),
+	 4}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_irq_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
+ * acpi_rs_set_irq
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_irq_stream(struct acpi_resource *linked_list,
-		   u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	u8 index;
-	u8 IRqinfo_byte_needed;
+struct acpi_rsconvert_info acpi_rs_set_irq[9] = {
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ,
+	 sizeof(struct aml_resource_irq),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)},
 
-	ACPI_FUNCTION_TRACE("rs_irq_stream");
+	/* Convert interrupt list to 16-bit IRQ bitmask */
 
+	{ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]),
+	 AML_OFFSET(irq.irq_mask),
+	 ACPI_RS_OFFSET(data.irq.interrupt_count)},
+
+	/* Set the flags byte by default */
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering),
+	 AML_OFFSET(irq.flags),
+	 0},
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity),
+	 AML_OFFSET(irq.flags),
+	 3},
+
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable),
+	 AML_OFFSET(irq.flags),
+	 4},
 	/*
-	 * The descriptor field is set based upon whether a third byte is
-	 * needed to contain the IRQ Information.
+	 * Check if the flags byte is necessary. Not needed if the flags are:
+	 * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE
 	 */
-	if (ACPI_EDGE_SENSITIVE == linked_list->data.irq.edge_level &&
-	    ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
-	    ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) {
-		*buffer = 0x22;
-		IRqinfo_byte_needed = FALSE;
-	} else {
-		*buffer = 0x23;
-		IRqinfo_byte_needed = TRUE;
-	}
+	{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+	 ACPI_RS_OFFSET(data.irq.triggering),
+	 ACPI_EDGE_SENSITIVE},
 
-	buffer += 1;
-	temp16 = 0;
+	{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+	 ACPI_RS_OFFSET(data.irq.polarity),
+	 ACPI_ACTIVE_HIGH},
 
-	/* Loop through all of the interrupts and set the mask bits */
+	{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+	 ACPI_RS_OFFSET(data.irq.sharable),
+	 ACPI_EXCLUSIVE},
 
-	for (index = 0;
-	     index < linked_list->data.irq.number_of_interrupts; index++) {
-		temp8 = (u8) linked_list->data.irq.interrupts[index];
-		temp16 |= 0x1 << temp8;
-	}
+	/* irq_no_flags() descriptor can be used */
 
-	ACPI_MOVE_16_TO_16(buffer, &temp16);
-	buffer += 2;
-
-	/* Set the IRQ Info byte if needed. */
-
-	if (IRqinfo_byte_needed) {
-		temp8 = 0;
-		temp8 = (u8) ((linked_list->data.irq.shared_exclusive &
-			       0x01) << 4);
-
-		if (ACPI_LEVEL_SENSITIVE == linked_list->data.irq.edge_level &&
-		    ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) {
-			temp8 |= 0x08;
-		} else {
-			temp8 |= 0x01;
-		}
-
-		*buffer = temp8;
-		buffer += 1;
-	}
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_extended_irq_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
+ * acpi_rs_convert_ext_irq
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_extended_irq_resource(u8 * byte_stream_buffer,
-			      acpi_size * bytes_consumed,
-			      u8 ** output_buffer, acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	u8 *temp_ptr;
-	u8 index;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq);
+struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ,
+	 ACPI_RS_SIZE(struct acpi_resource_extended_irq),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_irq)},
 
-	ACPI_FUNCTION_TRACE("rs_extended_irq_resource");
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_IRQ,
+	 sizeof(struct aml_resource_extended_irq),
+	 0},
 
-	/* Get the Descriptor Length field */
+	/* Flag bits */
 
-	buffer += 1;
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.producer_consumer),
+	 AML_OFFSET(extended_irq.flags),
+	 0},
 
-	/* Validate minimum descriptor length */
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.triggering),
+	 AML_OFFSET(extended_irq.flags),
+	 1},
 
-	if (temp16 < 6) {
-		return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
-	}
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.polarity),
+	 AML_OFFSET(extended_irq.flags),
+	 2},
 
-	*bytes_consumed = temp16 + 3;
-	output_struct->id = ACPI_RSTYPE_EXT_IRQ;
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.sharable),
+	 AML_OFFSET(extended_irq.flags),
+	 3},
 
-	/* Point to the Byte3 */
+	/* IRQ Table length (Byte4) */
 
-	buffer += 2;
-	temp8 = *buffer;
+	{ACPI_RSC_COUNT, ACPI_RS_OFFSET(data.extended_irq.interrupt_count),
+	 AML_OFFSET(extended_irq.interrupt_count),
+	 sizeof(u32)}
+	,
 
-	output_struct->data.extended_irq.producer_consumer = temp8 & 0x01;
+	/* Copy every IRQ in the table, each is 32 bits */
 
-	/*
-	 * Check for Interrupt Mode
-	 *
-	 * The definition of an Extended IRQ changed between ACPI spec v1.0b
-	 * and ACPI spec 2.0 (section 6.4.3.6 in both).
-	 *
-	 * - Edge/Level are defined opposite in the table vs the headers
-	 */
-	output_struct->data.extended_irq.edge_level =
-	    (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
+	{ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.extended_irq.interrupts[0]),
+	 AML_OFFSET(extended_irq.interrupts[0]),
+	 0}
+	,
 
-	/* Check Interrupt Polarity */
+	/* Optional resource_source (Index and String) */
 
-	output_struct->data.extended_irq.active_high_low = (temp8 >> 2) & 0x1;
-
-	/* Check for sharable */
-
-	output_struct->data.extended_irq.shared_exclusive = (temp8 >> 3) & 0x01;
-
-	/* Point to Byte4 (IRQ Table length) */
-
-	buffer += 1;
-	temp8 = *buffer;
-
-	/* Must have at least one IRQ */
-
-	if (temp8 < 1) {
-		return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
-	}
-
-	output_struct->data.extended_irq.number_of_interrupts = temp8;
-
-	/*
-	 * Add any additional structure size to properly calculate
-	 * the next pointer at the end of this function
-	 */
-	struct_size += (temp8 - 1) * 4;
-
-	/* Point to Byte5 (First IRQ Number) */
-
-	buffer += 1;
-
-	/* Cycle through every IRQ in the table */
-
-	for (index = 0; index < temp8; index++) {
-		ACPI_MOVE_32_TO_32(&output_struct->data.extended_irq.
-				   interrupts[index], buffer);
-
-		/* Point to the next IRQ */
-
-		buffer += 4;
-	}
-
-	/*
-	 * This will leave us pointing to the Resource Source Index
-	 * If it is present, then save it off and calculate the
-	 * pointer to where the null terminated string goes:
-	 * Each Interrupt takes 32-bits + the 5 bytes of the
-	 * stream that are default.
-	 *
-	 * Note: Some resource descriptors will have an additional null, so
-	 * we add 1 to the length.
-	 */
-	if (*bytes_consumed >
-	    ((acpi_size) output_struct->data.extended_irq.number_of_interrupts *
-	     4) + (5 + 1)) {
-		/* Dereference the Index */
-
-		temp8 = *buffer;
-		output_struct->data.extended_irq.resource_source.index =
-		    (u32) temp8;
-
-		/* Point to the String */
-
-		buffer += 1;
-
-		/* Point the String pointer to the end of this structure. */
-
-		output_struct->data.extended_irq.resource_source.string_ptr =
-		    (char *)((char *)output_struct + struct_size);
-
-		temp_ptr = (u8 *)
-		    output_struct->data.extended_irq.resource_source.string_ptr;
-
-		/* Copy the string into the buffer */
-
-		index = 0;
-		while (*buffer) {
-			*temp_ptr = *buffer;
-
-			temp_ptr += 1;
-			buffer += 1;
-			index += 1;
-		}
-
-		/* Add the terminating null */
-
-		*temp_ptr = 0;
-		output_struct->data.extended_irq.resource_source.string_length =
-		    index + 1;
-
-		/*
-		 * In order for the struct_size to fall on a 32-bit boundary,
-		 * calculate the length of the string and expand the
-		 * struct_size to the next 32-bit boundary.
-		 */
-		temp8 = (u8) (index + 1);
-		struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
-	} else {
-		output_struct->data.extended_irq.resource_source.index = 0;
-		output_struct->data.extended_irq.resource_source.string_length =
-		    0;
-		output_struct->data.extended_irq.resource_source.string_ptr =
-		    NULL;
-	}
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_SOURCEX, ACPI_RS_OFFSET(data.extended_irq.resource_source),
+	 ACPI_RS_OFFSET(data.extended_irq.interrupts[0]),
+	 sizeof(struct aml_resource_extended_irq)}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_extended_irq_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
+ * acpi_rs_convert_dma
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_extended_irq_stream(struct acpi_resource *linked_list,
-			    u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u16 *length_field;
-	u8 temp8 = 0;
-	u8 index;
+struct acpi_rsconvert_info acpi_rs_convert_dma[6] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_DMA,
+	 ACPI_RS_SIZE(struct acpi_resource_dma),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_dma)},
 
-	ACPI_FUNCTION_TRACE("rs_extended_irq_stream");
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_DMA,
+	 sizeof(struct aml_resource_dma),
+	 0},
 
-	/* Set the Descriptor Type field */
+	/* Flags: transfer preference, bus mastering, channel speed */
 
-	*buffer = ACPI_RDESC_TYPE_EXTENDED_XRUPT;
-	buffer += 1;
+	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.transfer),
+	 AML_OFFSET(dma.flags),
+	 0},
 
-	/* Save a pointer to the Length field - to be filled in later */
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.dma.bus_master),
+	 AML_OFFSET(dma.flags),
+	 2},
 
-	length_field = ACPI_CAST_PTR(u16, buffer);
-	buffer += 2;
+	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.type),
+	 AML_OFFSET(dma.flags),
+	 5},
 
-	/* Set the Interrupt vector flags */
+	/* DMA channel mask bits */
 
-	temp8 = (u8) (linked_list->data.extended_irq.producer_consumer & 0x01);
-	temp8 |=
-	    ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
-
-	/*
-	 * Set the Interrupt Mode
-	 *
-	 * The definition of an Extended IRQ changed between ACPI spec v1.0b
-	 * and ACPI spec 2.0 (section 6.4.3.6 in both).  This code does not
-	 * implement the more restrictive definition of 1.0b
-	 *
-	 * - Edge/Level are defined opposite in the table vs the headers
-	 */
-	if (ACPI_EDGE_SENSITIVE == linked_list->data.extended_irq.edge_level) {
-		temp8 |= 0x2;
-	}
-
-	/* Set the Interrupt Polarity */
-
-	temp8 |= ((linked_list->data.extended_irq.active_high_low & 0x1) << 2);
-
-	*buffer = temp8;
-	buffer += 1;
-
-	/* Set the Interrupt table length */
-
-	temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts;
-
-	*buffer = temp8;
-	buffer += 1;
-
-	for (index = 0;
-	     index < linked_list->data.extended_irq.number_of_interrupts;
-	     index++) {
-		ACPI_MOVE_32_TO_32(buffer,
-				   &linked_list->data.extended_irq.
-				   interrupts[index]);
-		buffer += 4;
-	}
-
-	/* Resource Source Index and Resource Source are optional */
-
-	if (0 != linked_list->data.extended_irq.resource_source.string_length) {
-		*buffer =
-		    (u8) linked_list->data.extended_irq.resource_source.index;
-		buffer += 1;
-
-		/* Copy the string */
-
-		ACPI_STRCPY((char *)buffer,
-			    linked_list->data.extended_irq.resource_source.
-			    string_ptr);
-
-		/*
-		 * Buffer needs to be set to the length of the string + one for the
-		 * terminating null
-		 */
-		buffer +=
-		    (acpi_size) (ACPI_STRLEN
-				 (linked_list->data.extended_irq.
-				  resource_source.string_ptr) + 1);
-	}
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-
-	/*
-	 * Set the length field to the number of bytes consumed
-	 * minus the header size (3 bytes)
-	 */
-	*length_field = (u16) (*bytes_consumed - 3);
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_BITMASK, ACPI_RS_OFFSET(data.dma.channels[0]),
+	 AML_OFFSET(dma.dma_channel_mask),
+	 ACPI_RS_OFFSET(data.dma.channel_count)}
+};
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index 103eb31..1434e78 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,52 +49,12 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_get_resource_type
+ * FUNCTION:    acpi_rs_convert_aml_to_resources
  *
- * PARAMETERS:  resource_start_byte     - Byte 0 of a resource descriptor
- *
- * RETURN:      The Resource Type with no extraneous bits
- *
- * DESCRIPTION: Extract the Resource Type/Name from the first byte of
- *              a resource descriptor.
- *
- ******************************************************************************/
-u8 acpi_rs_get_resource_type(u8 resource_start_byte)
-{
-
-	ACPI_FUNCTION_ENTRY();
-
-	/* Determine if this is a small or large resource */
-
-	switch (resource_start_byte & ACPI_RDESC_TYPE_MASK) {
-	case ACPI_RDESC_TYPE_SMALL:
-
-		/* Small Resource Type -- Only bits 6:3 are valid */
-
-		return ((u8) (resource_start_byte & ACPI_RDESC_SMALL_MASK));
-
-	case ACPI_RDESC_TYPE_LARGE:
-
-		/* Large Resource Type -- All bits are valid */
-
-		return (resource_start_byte);
-
-	default:
-		/* Invalid type */
-		break;
-	}
-
-	return (0xFF);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_byte_stream_to_list
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource byte stream
- *              byte_stream_buffer_length - Length of byte_stream_buffer
- *              output_buffer           - Pointer to the buffer that will
- *                                        contain the output structures
+ * PARAMETERS:  Aml                 - Pointer to the resource byte stream
+ *              aml_length          - Length of Aml
+ *              output_buffer       - Pointer to the buffer that will
+ *                                    contain the output structures
  *
  * RETURN:      Status
  *
@@ -102,241 +62,78 @@
  *              linked list of resources in the caller's output buffer
  *
  ******************************************************************************/
-
 acpi_status
-acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer,
-			    u32 byte_stream_buffer_length, u8 * output_buffer)
+acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer)
 {
+	struct acpi_resource *resource = (void *)output_buffer;
 	acpi_status status;
-	acpi_size bytes_parsed = 0;
-	u8 resource_type = 0;
-	acpi_size bytes_consumed = 0;
-	u8 *buffer = output_buffer;
-	acpi_size structure_size = 0;
-	u8 end_tag_processed = FALSE;
-	struct acpi_resource *resource;
+	u8 resource_index;
+	u8 *end_aml;
 
-	ACPI_FUNCTION_TRACE("rs_byte_stream_to_list");
+	ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources");
 
-	while (bytes_parsed < byte_stream_buffer_length && !end_tag_processed) {
-		/* The next byte in the stream is the resource type */
+	end_aml = aml + aml_length;
 
-		resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
+	/* Loop until end-of-buffer or an end_tag is found */
 
-		switch (resource_type) {
-		case ACPI_RDESC_TYPE_MEMORY_24:
-			/*
-			 * 24-Bit Memory Resource
-			 */
-			status = acpi_rs_memory24_resource(byte_stream_buffer,
-							   &bytes_consumed,
-							   &buffer,
-							   &structure_size);
-			break;
+	while (aml < end_aml) {
+		/* Validate the Resource Type and Resource Length */
 
-		case ACPI_RDESC_TYPE_LARGE_VENDOR:
-			/*
-			 * Vendor Defined Resource
-			 */
-			status = acpi_rs_vendor_resource(byte_stream_buffer,
-							 &bytes_consumed,
-							 &buffer,
-							 &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_MEMORY_32:
-			/*
-			 * 32-Bit Memory Range Resource
-			 */
-			status =
-			    acpi_rs_memory32_range_resource(byte_stream_buffer,
-							    &bytes_consumed,
-							    &buffer,
-							    &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
-			/*
-			 * 32-Bit Fixed Memory Resource
-			 */
-			status =
-			    acpi_rs_fixed_memory32_resource(byte_stream_buffer,
-							    &bytes_consumed,
-							    &buffer,
-							    &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
-		case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
-			/*
-			 * 64-Bit Address Resource
-			 */
-			status = acpi_rs_address64_resource(byte_stream_buffer,
-							    &bytes_consumed,
-							    &buffer,
-							    &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
-			/*
-			 * 32-Bit Address Resource
-			 */
-			status = acpi_rs_address32_resource(byte_stream_buffer,
-							    &bytes_consumed,
-							    &buffer,
-							    &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
-			/*
-			 * 16-Bit Address Resource
-			 */
-			status = acpi_rs_address16_resource(byte_stream_buffer,
-							    &bytes_consumed,
-							    &buffer,
-							    &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
-			/*
-			 * Extended IRQ
-			 */
-			status =
-			    acpi_rs_extended_irq_resource(byte_stream_buffer,
-							  &bytes_consumed,
-							  &buffer,
-							  &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_IRQ_FORMAT:
-			/*
-			 * IRQ Resource
-			 */
-			status = acpi_rs_irq_resource(byte_stream_buffer,
-						      &bytes_consumed, &buffer,
-						      &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_DMA_FORMAT:
-			/*
-			 * DMA Resource
-			 */
-			status = acpi_rs_dma_resource(byte_stream_buffer,
-						      &bytes_consumed, &buffer,
-						      &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_START_DEPENDENT:
-			/*
-			 * Start Dependent Functions Resource
-			 */
-			status =
-			    acpi_rs_start_depend_fns_resource
-			    (byte_stream_buffer, &bytes_consumed, &buffer,
-			     &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_END_DEPENDENT:
-			/*
-			 * End Dependent Functions Resource
-			 */
-			status =
-			    acpi_rs_end_depend_fns_resource(byte_stream_buffer,
-							    &bytes_consumed,
-							    &buffer,
-							    &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_IO_PORT:
-			/*
-			 * IO Port Resource
-			 */
-			status = acpi_rs_io_resource(byte_stream_buffer,
-						     &bytes_consumed, &buffer,
-						     &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_FIXED_IO_PORT:
-			/*
-			 * Fixed IO Port Resource
-			 */
-			status = acpi_rs_fixed_io_resource(byte_stream_buffer,
-							   &bytes_consumed,
-							   &buffer,
-							   &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_SMALL_VENDOR:
-			/*
-			 * Vendor Specific Resource
-			 */
-			status = acpi_rs_vendor_resource(byte_stream_buffer,
-							 &bytes_consumed,
-							 &buffer,
-							 &structure_size);
-			break;
-
-		case ACPI_RDESC_TYPE_END_TAG:
-			/*
-			 * End Tag
-			 */
-			end_tag_processed = TRUE;
-			status = acpi_rs_end_tag_resource(byte_stream_buffer,
-							  &bytes_consumed,
-							  &buffer,
-							  &structure_size);
-			break;
-
-		default:
-			/*
-			 * Invalid/Unknown resource type
-			 */
-			status = AE_AML_INVALID_RESOURCE_TYPE;
-			break;
-		}
-
+		status = acpi_ut_validate_resource(aml, &resource_index);
 		if (ACPI_FAILURE(status)) {
 			return_ACPI_STATUS(status);
 		}
 
-		/* Update the return value and counter */
+		/* Convert the AML byte stream resource to a local resource struct */
 
-		bytes_parsed += bytes_consumed;
+		status =
+		    acpi_rs_convert_aml_to_resource(resource,
+						    ACPI_CAST_PTR(union
+								  aml_resource,
+								  aml),
+						    acpi_gbl_get_resource_dispatch
+						    [resource_index]);
+		if (ACPI_FAILURE(status)) {
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Could not convert AML resource (Type %X)",
+					*aml));
+			return_ACPI_STATUS(status);
+		}
 
-		/* Set the byte stream to point to the next resource */
+		/* Normal exit on completion of an end_tag resource descriptor */
 
-		byte_stream_buffer += bytes_consumed;
+		if (acpi_ut_get_resource_type(aml) ==
+		    ACPI_RESOURCE_NAME_END_TAG) {
+			return_ACPI_STATUS(AE_OK);
+		}
 
-		/* Set the Buffer to the next structure */
+		/* Point to the next input AML resource */
 
-		resource = ACPI_CAST_PTR(struct acpi_resource, buffer);
-		resource->length =
-		    (u32) ACPI_ALIGN_RESOURCE_SIZE(resource->length);
-		buffer += ACPI_ALIGN_RESOURCE_SIZE(structure_size);
+		aml += acpi_ut_get_descriptor_length(aml);
+
+		/* Point to the next structure in the output buffer */
+
+		resource =
+		    ACPI_ADD_PTR(struct acpi_resource, resource,
+				 resource->length);
 	}
 
-	/* Check the reason for exiting the while loop */
+	/* Did not find an end_tag resource descriptor */
 
-	if (!end_tag_processed) {
-		return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
-	}
-
-	return_ACPI_STATUS(AE_OK);
+	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
 }
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_list_to_byte_stream
+ * FUNCTION:    acpi_rs_convert_resources_to_aml
  *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              byte_steam_size_needed  - Calculated size of the byte stream
- *                                        needed from calling
- *                                        acpi_rs_get_byte_stream_length()
- *                                        The size of the output_buffer is
- *                                        guaranteed to be >=
- *                                        byte_stream_size_needed
- *              output_buffer           - Pointer to the buffer that will
- *                                        contain the byte stream
+ * PARAMETERS:  Resource            - Pointer to the resource linked list
+ *              aml_size_needed     - Calculated size of the byte stream
+ *                                    needed from calling acpi_rs_get_aml_length()
+ *                                    The size of the output_buffer is
+ *                                    guaranteed to be >= aml_size_needed
+ *              output_buffer       - Pointer to the buffer that will
+ *                                    contain the byte stream
  *
  * RETURN:      Status
  *
@@ -346,180 +143,73 @@
  ******************************************************************************/
 
 acpi_status
-acpi_rs_list_to_byte_stream(struct acpi_resource *linked_list,
-			    acpi_size byte_stream_size_needed,
-			    u8 * output_buffer)
+acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
+				 acpi_size aml_size_needed, u8 * output_buffer)
 {
+	u8 *aml = output_buffer;
+	u8 *end_aml = output_buffer + aml_size_needed;
 	acpi_status status;
-	u8 *buffer = output_buffer;
-	acpi_size bytes_consumed = 0;
-	u8 done = FALSE;
 
-	ACPI_FUNCTION_TRACE("rs_list_to_byte_stream");
+	ACPI_FUNCTION_TRACE("rs_convert_resources_to_aml");
 
-	while (!done) {
-		switch (linked_list->id) {
-		case ACPI_RSTYPE_IRQ:
-			/*
-			 * IRQ Resource
-			 */
-			status =
-			    acpi_rs_irq_stream(linked_list, &buffer,
-					       &bytes_consumed);
-			break;
+	/* Walk the resource descriptor list, convert each descriptor */
 
-		case ACPI_RSTYPE_DMA:
-			/*
-			 * DMA Resource
-			 */
-			status =
-			    acpi_rs_dma_stream(linked_list, &buffer,
-					       &bytes_consumed);
-			break;
+	while (aml < end_aml) {
+		/* Validate the (internal) Resource Type */
 
-		case ACPI_RSTYPE_START_DPF:
-			/*
-			 * Start Dependent Functions Resource
-			 */
-			status = acpi_rs_start_depend_fns_stream(linked_list,
-								 &buffer,
-								 &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_END_DPF:
-			/*
-			 * End Dependent Functions Resource
-			 */
-			status = acpi_rs_end_depend_fns_stream(linked_list,
-							       &buffer,
-							       &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_IO:
-			/*
-			 * IO Port Resource
-			 */
-			status =
-			    acpi_rs_io_stream(linked_list, &buffer,
-					      &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_FIXED_IO:
-			/*
-			 * Fixed IO Port Resource
-			 */
-			status =
-			    acpi_rs_fixed_io_stream(linked_list, &buffer,
-						    &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_VENDOR:
-			/*
-			 * Vendor Defined Resource
-			 */
-			status =
-			    acpi_rs_vendor_stream(linked_list, &buffer,
-						  &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_END_TAG:
-			/*
-			 * End Tag
-			 */
-			status =
-			    acpi_rs_end_tag_stream(linked_list, &buffer,
-						   &bytes_consumed);
-
-			/* An End Tag indicates the end of the Resource Template */
-
-			done = TRUE;
-			break;
-
-		case ACPI_RSTYPE_MEM24:
-			/*
-			 * 24-Bit Memory Resource
-			 */
-			status =
-			    acpi_rs_memory24_stream(linked_list, &buffer,
-						    &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_MEM32:
-			/*
-			 * 32-Bit Memory Range Resource
-			 */
-			status =
-			    acpi_rs_memory32_range_stream(linked_list, &buffer,
-							  &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_FIXED_MEM32:
-			/*
-			 * 32-Bit Fixed Memory Resource
-			 */
-			status =
-			    acpi_rs_fixed_memory32_stream(linked_list, &buffer,
-							  &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_ADDRESS16:
-			/*
-			 * 16-Bit Address Descriptor Resource
-			 */
-			status = acpi_rs_address16_stream(linked_list, &buffer,
-							  &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_ADDRESS32:
-			/*
-			 * 32-Bit Address Descriptor Resource
-			 */
-			status = acpi_rs_address32_stream(linked_list, &buffer,
-							  &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_ADDRESS64:
-			/*
-			 * 64-Bit Address Descriptor Resource
-			 */
-			status = acpi_rs_address64_stream(linked_list, &buffer,
-							  &bytes_consumed);
-			break;
-
-		case ACPI_RSTYPE_EXT_IRQ:
-			/*
-			 * Extended IRQ Resource
-			 */
-			status =
-			    acpi_rs_extended_irq_stream(linked_list, &buffer,
-							&bytes_consumed);
-			break;
-
-		default:
-			/*
-			 * If we get here, everything is out of sync,
-			 * so exit with an error
-			 */
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Invalid descriptor type (%X) in resource list\n",
-					  linked_list->id));
-			status = AE_BAD_DATA;
-			break;
+		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
+			ACPI_ERROR((AE_INFO,
+				    "Invalid descriptor type (%X) in resource list",
+				    resource->type));
+			return_ACPI_STATUS(AE_BAD_DATA);
 		}
 
+		/* Perform the conversion */
+
+		status = acpi_rs_convert_resource_to_aml(resource,
+							 ACPI_CAST_PTR(union
+								       aml_resource,
+								       aml),
+							 acpi_gbl_set_resource_dispatch
+							 [resource->type]);
+		if (ACPI_FAILURE(status)) {
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Could not convert resource (type %X) to AML",
+					resource->type));
+			return_ACPI_STATUS(status);
+		}
+
+		/* Perform final sanity check on the new AML resource descriptor */
+
+		status =
+		    acpi_ut_validate_resource(ACPI_CAST_PTR
+					      (union aml_resource, aml), NULL);
 		if (ACPI_FAILURE(status)) {
 			return_ACPI_STATUS(status);
 		}
 
-		/* Set the Buffer to point to the open byte */
+		/* Check for end-of-list, normal exit */
 
-		buffer += bytes_consumed;
+		if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
+			/* An End Tag indicates the end of the input Resource Template */
 
-		/* Point to the next object */
+			return_ACPI_STATUS(AE_OK);
+		}
 
-		linked_list = ACPI_PTR_ADD(struct acpi_resource,
-					   linked_list, linked_list->length);
+		/*
+		 * Extract the total length of the new descriptor and set the
+		 * Aml to point to the next (output) resource descriptor
+		 */
+		aml += acpi_ut_get_descriptor_length(aml);
+
+		/* Point to the next input resource descriptor */
+
+		resource =
+		    ACPI_ADD_PTR(struct acpi_resource, resource,
+				 resource->length);
 	}
 
-	return_ACPI_STATUS(AE_OK);
+	/* Completed buffer, but did not find an end_tag resource descriptor */
+
+	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
 }
diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c
index daba1a1..a513193 100644
--- a/drivers/acpi/resources/rsmemory.c
+++ b/drivers/acpi/resources/rsmemory.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,454 +49,187 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_memory24_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
+ * acpi_rs_convert_memory24
  *
  ******************************************************************************/
-acpi_status
-acpi_rs_memory24_resource(u8 * byte_stream_buffer,
-			  acpi_size * bytes_consumed,
-			  u8 ** output_buffer, acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24);
+struct acpi_rsconvert_info acpi_rs_convert_memory24[4] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY24,
+	 ACPI_RS_SIZE(struct acpi_resource_memory24),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory24)},
 
-	ACPI_FUNCTION_TRACE("rs_memory24_resource");
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY24,
+	 sizeof(struct aml_resource_memory24),
+	 0},
 
-	/* Point past the Descriptor to get the number of bytes consumed */
+	/* Read/Write bit */
 
-	buffer += 1;
-
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-	buffer += 2;
-	*bytes_consumed = (acpi_size) temp16 + 3;
-	output_struct->id = ACPI_RSTYPE_MEM24;
-
-	/* Check Byte 3 the Read/Write bit */
-
-	temp8 = *buffer;
-	buffer += 1;
-	output_struct->data.memory24.read_write_attribute = temp8 & 0x01;
-
-	/* Get min_base_address (Bytes 4-5) */
-
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-	buffer += 2;
-	output_struct->data.memory24.min_base_address = temp16;
-
-	/* Get max_base_address (Bytes 6-7) */
-
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-	buffer += 2;
-	output_struct->data.memory24.max_base_address = temp16;
-
-	/* Get Alignment (Bytes 8-9) */
-
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-	buffer += 2;
-	output_struct->data.memory24.alignment = temp16;
-
-	/* Get range_length (Bytes 10-11) */
-
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-	output_struct->data.memory24.range_length = temp16;
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory24.write_protect),
+	 AML_OFFSET(memory24.flags),
+	 0},
+	/*
+	 * These fields are contiguous in both the source and destination:
+	 * Minimum Base Address
+	 * Maximum Base Address
+	 * Address Base Alignment
+	 * Range Length
+	 */
+	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.memory24.minimum),
+	 AML_OFFSET(memory24.minimum),
+	 4}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_memory24_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
+ * acpi_rs_convert_memory32
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_memory24_stream(struct acpi_resource *linked_list,
-			u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
+struct acpi_rsconvert_info acpi_rs_convert_memory32[4] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY32,
+	 ACPI_RS_SIZE(struct acpi_resource_memory32),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory32)},
 
-	ACPI_FUNCTION_TRACE("rs_memory24_stream");
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY32,
+	 sizeof(struct aml_resource_memory32),
+	 0},
 
-	/* The descriptor field is static */
+	/* Read/Write bit */
 
-	*buffer = 0x81;
-	buffer += 1;
-
-	/* The length field is static */
-
-	temp16 = 0x09;
-	ACPI_MOVE_16_TO_16(buffer, &temp16);
-	buffer += 2;
-
-	/* Set the Information Byte */
-
-	temp8 = (u8) (linked_list->data.memory24.read_write_attribute & 0x01);
-	*buffer = temp8;
-	buffer += 1;
-
-	/* Set the Range minimum base address */
-
-	ACPI_MOVE_32_TO_16(buffer,
-			   &linked_list->data.memory24.min_base_address);
-	buffer += 2;
-
-	/* Set the Range maximum base address */
-
-	ACPI_MOVE_32_TO_16(buffer,
-			   &linked_list->data.memory24.max_base_address);
-	buffer += 2;
-
-	/* Set the base alignment */
-
-	ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.alignment);
-	buffer += 2;
-
-	/* Set the range length */
-
-	ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.range_length);
-	buffer += 2;
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory32.write_protect),
+	 AML_OFFSET(memory32.flags),
+	 0},
+	/*
+	 * These fields are contiguous in both the source and destination:
+	 * Minimum Base Address
+	 * Maximum Base Address
+	 * Address Base Alignment
+	 * Range Length
+	 */
+	{ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.memory32.minimum),
+	 AML_OFFSET(memory32.minimum),
+	 4}
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_memory32_range_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
+ * acpi_rs_convert_fixed_memory32
  *
  ******************************************************************************/
 
-acpi_status
-acpi_rs_memory32_range_resource(u8 * byte_stream_buffer,
-				acpi_size * bytes_consumed,
-				u8 ** output_buffer, acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32);
+struct acpi_rsconvert_info acpi_rs_convert_fixed_memory32[4] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_MEMORY32,
+	 ACPI_RS_SIZE(struct acpi_resource_fixed_memory32),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_memory32)},
 
-	ACPI_FUNCTION_TRACE("rs_memory32_range_resource");
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_MEMORY32,
+	 sizeof(struct aml_resource_fixed_memory32),
+	 0},
 
-	/* Point past the Descriptor to get the number of bytes consumed */
+	/* Read/Write bit */
 
-	buffer += 1;
+	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.fixed_memory32.write_protect),
+	 AML_OFFSET(fixed_memory32.flags),
+	 0},
+	/*
+	 * These fields are contiguous in both the source and destination:
+	 * Base Address
+	 * Range Length
+	 */
+	{ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.fixed_memory32.address),
+	 AML_OFFSET(fixed_memory32.address),
+	 2}
+};
 
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-	buffer += 2;
-	*bytes_consumed = (acpi_size) temp16 + 3;
+/*******************************************************************************
+ *
+ * acpi_rs_get_vendor_small
+ *
+ ******************************************************************************/
 
-	output_struct->id = ACPI_RSTYPE_MEM32;
+struct acpi_rsconvert_info acpi_rs_get_vendor_small[3] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR,
+	 ACPI_RS_SIZE(struct acpi_resource_vendor),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_small)},
+
+	/* Length of the vendor data (byte count) */
+
+	{ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length),
+	 0,
+	 sizeof(u8)}
+	,
+
+	/* Vendor data */
+
+	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]),
+	 sizeof(struct aml_resource_small_header),
+	 0}
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_get_vendor_large
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_get_vendor_large[3] = {
+	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR,
+	 ACPI_RS_SIZE(struct acpi_resource_vendor),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_large)},
+
+	/* Length of the vendor data (byte count) */
+
+	{ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length),
+	 0,
+	 sizeof(u8)}
+	,
+
+	/* Vendor data */
+
+	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]),
+	 sizeof(struct aml_resource_large_header),
+	 0}
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_set_vendor
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_set_vendor[7] = {
+	/* Default is a small vendor descriptor */
+
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_SMALL,
+	 sizeof(struct aml_resource_small_header),
+	 ACPI_RSC_TABLE_SIZE(acpi_rs_set_vendor)},
+
+	/* Get the length and copy the data */
+
+	{ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length),
+	 0,
+	 0},
+
+	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]),
+	 sizeof(struct aml_resource_small_header),
+	 0},
 
 	/*
-	 *  Point to the place in the output buffer where the data portion will
-	 *  begin.
-	 *  1. Set the RESOURCE_DATA * Data to point to its own address, then
-	 *  2. Set the pointer to the next address.
-	 *
-	 *  NOTE: output_struct->Data is cast to u8, otherwise, this addition adds
-	 *  4 * sizeof(RESOURCE_DATA) instead of 4 * sizeof(u8)
+	 * All done if the Vendor byte length is 7 or less, meaning that it will
+	 * fit within a small descriptor
 	 */
+	{ACPI_RSC_EXIT_LE, 0, 0, 7},
 
-	/* Check Byte 3 the Read/Write bit */
+	/* Must create a large vendor descriptor */
 
-	temp8 = *buffer;
-	buffer += 1;
+	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_LARGE,
+	 sizeof(struct aml_resource_large_header),
+	 0},
 
-	output_struct->data.memory32.read_write_attribute = temp8 & 0x01;
+	{ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length),
+	 0,
+	 0},
 
-	/* Get min_base_address (Bytes 4-7) */
-
-	ACPI_MOVE_32_TO_32(&output_struct->data.memory32.min_base_address,
-			   buffer);
-	buffer += 4;
-
-	/* Get max_base_address (Bytes 8-11) */
-
-	ACPI_MOVE_32_TO_32(&output_struct->data.memory32.max_base_address,
-			   buffer);
-	buffer += 4;
-
-	/* Get Alignment (Bytes 12-15) */
-
-	ACPI_MOVE_32_TO_32(&output_struct->data.memory32.alignment, buffer);
-	buffer += 4;
-
-	/* Get range_length (Bytes 16-19) */
-
-	ACPI_MOVE_32_TO_32(&output_struct->data.memory32.range_length, buffer);
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_fixed_memory32_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_fixed_memory32_resource(u8 * byte_stream_buffer,
-				acpi_size * bytes_consumed,
-				u8 ** output_buffer, acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_mem32);
-
-	ACPI_FUNCTION_TRACE("rs_fixed_memory32_resource");
-
-	/* Point past the Descriptor to get the number of bytes consumed */
-
-	buffer += 1;
-	ACPI_MOVE_16_TO_16(&temp16, buffer);
-
-	buffer += 2;
-	*bytes_consumed = (acpi_size) temp16 + 3;
-
-	output_struct->id = ACPI_RSTYPE_FIXED_MEM32;
-
-	/* Check Byte 3 the Read/Write bit */
-
-	temp8 = *buffer;
-	buffer += 1;
-	output_struct->data.fixed_memory32.read_write_attribute = temp8 & 0x01;
-
-	/* Get range_base_address (Bytes 4-7) */
-
-	ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32.
-			   range_base_address, buffer);
-	buffer += 4;
-
-	/* Get range_length (Bytes 8-11) */
-
-	ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32.range_length,
-			   buffer);
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_memory32_range_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_memory32_range_stream(struct acpi_resource *linked_list,
-			      u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-
-	ACPI_FUNCTION_TRACE("rs_memory32_range_stream");
-
-	/* The descriptor field is static */
-
-	*buffer = 0x85;
-	buffer += 1;
-
-	/* The length field is static */
-
-	temp16 = 0x11;
-
-	ACPI_MOVE_16_TO_16(buffer, &temp16);
-	buffer += 2;
-
-	/* Set the Information Byte */
-
-	temp8 = (u8) (linked_list->data.memory32.read_write_attribute & 0x01);
-	*buffer = temp8;
-	buffer += 1;
-
-	/* Set the Range minimum base address */
-
-	ACPI_MOVE_32_TO_32(buffer,
-			   &linked_list->data.memory32.min_base_address);
-	buffer += 4;
-
-	/* Set the Range maximum base address */
-
-	ACPI_MOVE_32_TO_32(buffer,
-			   &linked_list->data.memory32.max_base_address);
-	buffer += 4;
-
-	/* Set the base alignment */
-
-	ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.alignment);
-	buffer += 4;
-
-	/* Set the range length */
-
-	ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.range_length);
-	buffer += 4;
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_fixed_memory32_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_fixed_memory32_stream(struct acpi_resource *linked_list,
-			      u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-
-	ACPI_FUNCTION_TRACE("rs_fixed_memory32_stream");
-
-	/* The descriptor field is static */
-
-	*buffer = 0x86;
-	buffer += 1;
-
-	/* The length field is static */
-
-	temp16 = 0x09;
-
-	ACPI_MOVE_16_TO_16(buffer, &temp16);
-	buffer += 2;
-
-	/* Set the Information Byte */
-
-	temp8 =
-	    (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01);
-	*buffer = temp8;
-	buffer += 1;
-
-	/* Set the Range base address */
-
-	ACPI_MOVE_32_TO_32(buffer,
-			   &linked_list->data.fixed_memory32.
-			   range_base_address);
-	buffer += 4;
-
-	/* Set the range length */
-
-	ACPI_MOVE_32_TO_32(buffer,
-			   &linked_list->data.fixed_memory32.range_length);
-	buffer += 4;
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
-}
+	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]),
+	 sizeof(struct aml_resource_large_header),
+	 0}
+};
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
index 7a8a34e..ed866cf 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/drivers/acpi/resources/rsmisc.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,481 +47,501 @@
 #define _COMPONENT          ACPI_RESOURCES
 ACPI_MODULE_NAME("rsmisc")
 
+#define INIT_RESOURCE_TYPE(i)       i->resource_offset
+#define INIT_RESOURCE_LENGTH(i)     i->aml_offset
+#define INIT_TABLE_LENGTH(i)        i->value
+#define COMPARE_OPCODE(i)           i->resource_offset
+#define COMPARE_TARGET(i)           i->aml_offset
+#define COMPARE_VALUE(i)            i->value
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_end_tag_resource
+ * FUNCTION:    acpi_rs_convert_aml_to_resource
  *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
+ * PARAMETERS:  Resource            - Pointer to the resource descriptor
+ *              Aml                 - Where the AML descriptor is returned
+ *              Info                - Pointer to appropriate conversion table
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
+ * DESCRIPTION: Convert an external AML resource descriptor to the corresponding
+ *              internal resource descriptor
  *
  ******************************************************************************/
 acpi_status
-acpi_rs_end_tag_resource(u8 * byte_stream_buffer,
-			 acpi_size * bytes_consumed,
-			 u8 ** output_buffer, acpi_size * structure_size)
+acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
+				union aml_resource *aml,
+				struct acpi_rsconvert_info *info)
 {
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	acpi_size struct_size = ACPI_RESOURCE_LENGTH;
+	acpi_rs_length aml_resource_length;
+	void *source;
+	void *destination;
+	char *target;
+	u8 count;
+	u8 flags_mode = FALSE;
+	u16 item_count = 0;
+	u16 temp16 = 0;
 
-	ACPI_FUNCTION_TRACE("rs_end_tag_resource");
+	ACPI_FUNCTION_TRACE("rs_get_resource");
 
-	/* The number of bytes consumed is static */
+	if (((acpi_native_uint) resource) & 0x3) {
+		/* Each internal resource struct is expected to be 32-bit aligned */
 
-	*bytes_consumed = 2;
+		ACPI_WARNING((AE_INFO,
+			      "Misaligned resource pointer (get): %p Type %2.2X Len %X",
+			      resource, resource->type, resource->length));
+	}
 
-	/*  Fill out the structure */
+	/* Extract the resource Length field (does not include header length) */
 
-	output_struct->id = ACPI_RSTYPE_END_TAG;
-
-	/* Set the Length parameter */
-
-	output_struct->length = 0;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_end_tag_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_end_tag_stream(struct acpi_resource *linked_list,
-		       u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u8 temp8 = 0;
-
-	ACPI_FUNCTION_TRACE("rs_end_tag_stream");
-
-	/* The descriptor field is static */
-
-	*buffer = 0x79;
-	buffer += 1;
+	aml_resource_length = acpi_ut_get_resource_length(aml);
 
 	/*
-	 * Set the Checksum - zero means that the resource data is treated as if
-	 * the checksum operation succeeded (ACPI Spec 1.0b Section 6.4.2.8)
+	 * First table entry must be ACPI_RSC_INITxxx and must contain the
+	 * table length (# of table entries)
 	 */
-	temp8 = 0;
+	count = INIT_TABLE_LENGTH(info);
 
-	*buffer = temp8;
-	buffer += 1;
+	while (count) {
+		/*
+		 * Source is the external AML byte stream buffer,
+		 * destination is the internal resource descriptor
+		 */
+		source = ACPI_ADD_PTR(void, aml, info->aml_offset);
+		destination =
+		    ACPI_ADD_PTR(void, resource, info->resource_offset);
 
-	/* Return the number of bytes consumed in this operation */
+		switch (info->opcode) {
+		case ACPI_RSC_INITGET:
+			/*
+			 * Get the resource type and the initial (minimum) length
+			 */
+			ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info));
+			resource->type = INIT_RESOURCE_TYPE(info);
+			resource->length = INIT_RESOURCE_LENGTH(info);
+			break;
 
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
-}
+		case ACPI_RSC_INITSET:
+			break;
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_vendor_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
- *
- ******************************************************************************/
+		case ACPI_RSC_FLAGINIT:
 
-acpi_status
-acpi_rs_vendor_resource(u8 * byte_stream_buffer,
-			acpi_size * bytes_consumed,
-			u8 ** output_buffer, acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	u8 index;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor);
+			flags_mode = TRUE;
+			break;
 
-	ACPI_FUNCTION_TRACE("rs_vendor_resource");
+		case ACPI_RSC_1BITFLAG:
+			/*
+			 * Mask and shift the flag bit
+			 */
+			ACPI_SET8(destination) = (u8)
+			    ((ACPI_GET8(source) >> info->value) & 0x01);
+			break;
 
-	/* Dereference the Descriptor to find if this is a large or small item. */
+		case ACPI_RSC_2BITFLAG:
+			/*
+			 * Mask and shift the flag bits
+			 */
+			ACPI_SET8(destination) = (u8)
+			    ((ACPI_GET8(source) >> info->value) & 0x03);
+			break;
 
-	temp8 = *buffer;
+		case ACPI_RSC_COUNT:
 
-	if (temp8 & 0x80) {
-		/* Large Item, point to the length field */
+			item_count = ACPI_GET8(source);
+			ACPI_SET8(destination) = (u8) item_count;
 
-		buffer += 1;
+			resource->length = resource->length +
+			    (info->value * (item_count - 1));
+			break;
 
-		/* Dereference */
+		case ACPI_RSC_COUNT16:
 
-		ACPI_MOVE_16_TO_16(&temp16, buffer);
+			item_count = aml_resource_length;
+			ACPI_SET16(destination) = item_count;
 
-		/* Calculate bytes consumed */
+			resource->length = resource->length +
+			    (info->value * (item_count - 1));
+			break;
 
-		*bytes_consumed = (acpi_size) temp16 + 3;
+		case ACPI_RSC_LENGTH:
 
-		/* Point to the first vendor byte */
+			resource->length = resource->length + info->value;
+			break;
 
-		buffer += 2;
-	} else {
-		/* Small Item, dereference the size */
+		case ACPI_RSC_MOVE8:
+		case ACPI_RSC_MOVE16:
+		case ACPI_RSC_MOVE32:
+		case ACPI_RSC_MOVE64:
+			/*
+			 * Raw data move. Use the Info value field unless item_count has
+			 * been previously initialized via a COUNT opcode
+			 */
+			if (info->value) {
+				item_count = info->value;
+			}
+			acpi_rs_move_data(destination, source, item_count,
+					  info->opcode);
+			break;
 
-		temp16 = (u8) (*buffer & 0x07);
+		case ACPI_RSC_SET8:
 
-		/* Calculate bytes consumed */
+			ACPI_MEMSET(destination, info->aml_offset, info->value);
+			break;
 
-		*bytes_consumed = (acpi_size) temp16 + 1;
+		case ACPI_RSC_DATA8:
 
-		/* Point to the first vendor byte */
+			target = ACPI_ADD_PTR(char, resource, info->value);
+			ACPI_MEMCPY(destination, source, ACPI_GET16(target));
+			break;
 
-		buffer += 1;
-	}
+		case ACPI_RSC_ADDRESS:
+			/*
+			 * Common handler for address descriptor flags
+			 */
+			if (!acpi_rs_get_address_common(resource, aml)) {
+				return_ACPI_STATUS
+				    (AE_AML_INVALID_RESOURCE_TYPE);
+			}
+			break;
 
-	output_struct->id = ACPI_RSTYPE_VENDOR;
-	output_struct->data.vendor_specific.length = temp16;
+		case ACPI_RSC_SOURCE:
+			/*
+			 * Optional resource_source (Index and String)
+			 */
+			resource->length +=
+			    acpi_rs_get_resource_source(aml_resource_length,
+							info->value,
+							destination, aml, NULL);
+			break;
 
-	for (index = 0; index < temp16; index++) {
-		output_struct->data.vendor_specific.reserved[index] = *buffer;
-		buffer += 1;
-	}
+		case ACPI_RSC_SOURCEX:
+			/*
+			 * Optional resource_source (Index and String). This is the more
+			 * complicated case used by the Interrupt() macro
+			 */
+			target =
+			    ACPI_ADD_PTR(char, resource,
+					 info->aml_offset + (item_count * 4));
 
-	/*
-	 * In order for the struct_size to fall on a 32-bit boundary,
-	 * calculate the length of the vendor string and expand the
-	 * struct_size to the next 32-bit boundary.
-	 */
-	struct_size += ACPI_ROUND_UP_to_32_bITS(temp16);
+			resource->length +=
+			    acpi_rs_get_resource_source(aml_resource_length,
+							(acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target);
+			break;
 
-	/* Set the Length parameter */
+		case ACPI_RSC_BITMASK:
+			/*
+			 * 8-bit encoded bitmask (DMA macro)
+			 */
+			item_count =
+			    acpi_rs_decode_bitmask(ACPI_GET8(source),
+						   destination);
+			if (item_count) {
+				resource->length += (item_count - 1);
+			}
 
-	output_struct->length = (u32) struct_size;
+			target = ACPI_ADD_PTR(char, resource, info->value);
+			ACPI_SET8(target) = (u8) item_count;
+			break;
 
-	/* Return the final size of the structure */
+		case ACPI_RSC_BITMASK16:
+			/*
+			 * 16-bit encoded bitmask (IRQ macro)
+			 */
+			ACPI_MOVE_16_TO_16(&temp16, source);
 
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
+			item_count =
+			    acpi_rs_decode_bitmask(temp16, destination);
+			if (item_count) {
+				resource->length += (item_count - 1);
+			}
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_vendor_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
- *
- ******************************************************************************/
+			target = ACPI_ADD_PTR(char, resource, info->value);
+			ACPI_SET8(target) = (u8) item_count;
+			break;
 
-acpi_status
-acpi_rs_vendor_stream(struct acpi_resource *linked_list,
-		      u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u16 temp16 = 0;
-	u8 temp8 = 0;
-	u8 index;
+		case ACPI_RSC_EXIT_NE:
+			/*
+			 * Control - Exit conversion if not equal
+			 */
+			switch (info->resource_offset) {
+			case ACPI_RSC_COMPARE_AML_LENGTH:
+				if (aml_resource_length != info->value) {
+					goto exit;
+				}
+				break;
 
-	ACPI_FUNCTION_TRACE("rs_vendor_stream");
+			case ACPI_RSC_COMPARE_VALUE:
+				if (ACPI_GET8(source) != info->value) {
+					goto exit;
+				}
+				break;
 
-	/* Dereference the length to find if this is a large or small item. */
+			default:
 
-	if (linked_list->data.vendor_specific.length > 7) {
-		/* Large Item, Set the descriptor field and length bytes */
+				ACPI_ERROR((AE_INFO,
+					    "Invalid conversion sub-opcode"));
+				return_ACPI_STATUS(AE_BAD_PARAMETER);
+			}
+			break;
 
-		*buffer = 0x84;
-		buffer += 1;
+		default:
 
-		temp16 = (u16) linked_list->data.vendor_specific.length;
-
-		ACPI_MOVE_16_TO_16(buffer, &temp16);
-		buffer += 2;
-	} else {
-		/* Small Item, Set the descriptor field */
-
-		temp8 = 0x70;
-		temp8 |= (u8) linked_list->data.vendor_specific.length;
-
-		*buffer = temp8;
-		buffer += 1;
-	}
-
-	/* Loop through all of the Vendor Specific fields */
-
-	for (index = 0; index < linked_list->data.vendor_specific.length;
-	     index++) {
-		temp8 = linked_list->data.vendor_specific.reserved[index];
-
-		*buffer = temp8;
-		buffer += 1;
-	}
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_start_depend_fns_resource
- *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_start_depend_fns_resource(u8 * byte_stream_buffer,
-				  acpi_size * bytes_consumed,
-				  u8 ** output_buffer,
-				  acpi_size * structure_size)
-{
-	u8 *buffer = byte_stream_buffer;
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	u8 temp8 = 0;
-	acpi_size struct_size =
-	    ACPI_SIZEOF_RESOURCE(struct acpi_resource_start_dpf);
-
-	ACPI_FUNCTION_TRACE("rs_start_depend_fns_resource");
-
-	/* The number of bytes consumed are found in the descriptor (Bits:0-1) */
-
-	temp8 = *buffer;
-
-	*bytes_consumed = (temp8 & 0x01) + 1;
-
-	output_struct->id = ACPI_RSTYPE_START_DPF;
-
-	/* Point to Byte 1 if it is used */
-
-	if (2 == *bytes_consumed) {
-		buffer += 1;
-		temp8 = *buffer;
-
-		/* Check Compatibility priority */
-
-		output_struct->data.start_dpf.compatibility_priority =
-		    temp8 & 0x03;
-
-		if (3 == output_struct->data.start_dpf.compatibility_priority) {
-			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
+			ACPI_ERROR((AE_INFO, "Invalid conversion opcode"));
+			return_ACPI_STATUS(AE_BAD_PARAMETER);
 		}
 
-		/* Check Performance/Robustness preference */
-
-		output_struct->data.start_dpf.performance_robustness =
-		    (temp8 >> 2) & 0x03;
-
-		if (3 == output_struct->data.start_dpf.performance_robustness) {
-			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
-		}
-	} else {
-		output_struct->data.start_dpf.compatibility_priority =
-		    ACPI_ACCEPTABLE_CONFIGURATION;
-
-		output_struct->data.start_dpf.performance_robustness =
-		    ACPI_ACCEPTABLE_CONFIGURATION;
+		count--;
+		info++;
 	}
 
-	/* Set the Length parameter */
+      exit:
+	if (!flags_mode) {
+		/* Round the resource struct length up to the next 32-bit boundary */
 
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
+		resource->length = ACPI_ROUND_UP_to_32_bITS(resource->length);
+	}
 	return_ACPI_STATUS(AE_OK);
 }
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_rs_end_depend_fns_resource
+ * FUNCTION:    acpi_rs_convert_resource_to_aml
  *
- * PARAMETERS:  byte_stream_buffer      - Pointer to the resource input byte
- *                                        stream
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        consumed the byte_stream_buffer is
- *                                        returned
- *              output_buffer           - Pointer to the return data buffer
- *              structure_size          - Pointer to where the number of bytes
- *                                        in the return data struct is returned
+ * PARAMETERS:  Resource            - Pointer to the resource descriptor
+ *              Aml                 - Where the AML descriptor is returned
+ *              Info                - Pointer to appropriate conversion table
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- *              structure pointed to by the output_buffer. Return the
- *              number of bytes consumed from the byte stream.
+ * DESCRIPTION: Convert an internal resource descriptor to the corresponding
+ *              external AML resource descriptor.
  *
  ******************************************************************************/
 
 acpi_status
-acpi_rs_end_depend_fns_resource(u8 * byte_stream_buffer,
-				acpi_size * bytes_consumed,
-				u8 ** output_buffer, acpi_size * structure_size)
+acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
+				union aml_resource *aml,
+				struct acpi_rsconvert_info *info)
 {
-	struct acpi_resource *output_struct = (void *)*output_buffer;
-	acpi_size struct_size = ACPI_RESOURCE_LENGTH;
+	void *source = NULL;
+	void *destination;
+	acpi_rsdesc_size aml_length = 0;
+	u8 count;
+	u16 temp16 = 0;
+	u16 item_count = 0;
 
-	ACPI_FUNCTION_TRACE("rs_end_depend_fns_resource");
-
-	/* The number of bytes consumed is static */
-
-	*bytes_consumed = 1;
-
-	/*  Fill out the structure */
-
-	output_struct->id = ACPI_RSTYPE_END_DPF;
-
-	/* Set the Length parameter */
-
-	output_struct->length = (u32) struct_size;
-
-	/* Return the final size of the structure */
-
-	*structure_size = struct_size;
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_start_depend_fns_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - u32 pointer that is filled with
- *                                        the number of bytes of the
- *                                        output_buffer used
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_start_depend_fns_stream(struct acpi_resource *linked_list,
-				u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-	u8 temp8 = 0;
-
-	ACPI_FUNCTION_TRACE("rs_start_depend_fns_stream");
+	ACPI_FUNCTION_TRACE("rs_convert_resource_to_aml");
 
 	/*
-	 * The descriptor field is set based upon whether a byte is needed
-	 * to contain Priority data.
+	 * First table entry must be ACPI_RSC_INITxxx and must contain the
+	 * table length (# of table entries)
 	 */
-	if (ACPI_ACCEPTABLE_CONFIGURATION ==
-	    linked_list->data.start_dpf.compatibility_priority &&
-	    ACPI_ACCEPTABLE_CONFIGURATION ==
-	    linked_list->data.start_dpf.performance_robustness) {
-		*buffer = 0x30;
-	} else {
-		*buffer = 0x31;
-		buffer += 1;
+	count = INIT_TABLE_LENGTH(info);
 
-		/* Set the Priority Byte Definition */
+	while (count) {
+		/*
+		 * Source is the internal resource descriptor,
+		 * destination is the external AML byte stream buffer
+		 */
+		source = ACPI_ADD_PTR(void, resource, info->resource_offset);
+		destination = ACPI_ADD_PTR(void, aml, info->aml_offset);
 
-		temp8 = 0;
-		temp8 =
-		    (u8) ((linked_list->data.start_dpf.
-			   performance_robustness & 0x03) << 2);
-		temp8 |=
-		    (linked_list->data.start_dpf.compatibility_priority & 0x03);
-		*buffer = temp8;
+		switch (info->opcode) {
+		case ACPI_RSC_INITSET:
+
+			ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info));
+			aml_length = INIT_RESOURCE_LENGTH(info);
+			acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info),
+						    aml_length, aml);
+			break;
+
+		case ACPI_RSC_INITGET:
+			break;
+
+		case ACPI_RSC_FLAGINIT:
+			/*
+			 * Clear the flag byte
+			 */
+			ACPI_SET8(destination) = 0;
+			break;
+
+		case ACPI_RSC_1BITFLAG:
+			/*
+			 * Mask and shift the flag bit
+			 */
+			ACPI_SET8(destination) |= (u8)
+			    ((ACPI_GET8(source) & 0x01) << info->value);
+			break;
+
+		case ACPI_RSC_2BITFLAG:
+			/*
+			 * Mask and shift the flag bits
+			 */
+			ACPI_SET8(destination) |= (u8)
+			    ((ACPI_GET8(source) & 0x03) << info->value);
+			break;
+
+		case ACPI_RSC_COUNT:
+
+			item_count = ACPI_GET8(source);
+			ACPI_SET8(destination) = (u8) item_count;
+
+			aml_length =
+			    (u16) (aml_length +
+				   (info->value * (item_count - 1)));
+			break;
+
+		case ACPI_RSC_COUNT16:
+
+			item_count = ACPI_GET16(source);
+			aml_length = (u16) (aml_length + item_count);
+			acpi_rs_set_resource_length(aml_length, aml);
+			break;
+
+		case ACPI_RSC_LENGTH:
+
+			acpi_rs_set_resource_length(info->value, aml);
+			break;
+
+		case ACPI_RSC_MOVE8:
+		case ACPI_RSC_MOVE16:
+		case ACPI_RSC_MOVE32:
+		case ACPI_RSC_MOVE64:
+
+			if (info->value) {
+				item_count = info->value;
+			}
+			acpi_rs_move_data(destination, source, item_count,
+					  info->opcode);
+			break;
+
+		case ACPI_RSC_ADDRESS:
+
+			/* Set the Resource Type, General Flags, and Type-Specific Flags */
+
+			acpi_rs_set_address_common(aml, resource);
+			break;
+
+		case ACPI_RSC_SOURCEX:
+			/*
+			 * Optional resource_source (Index and String)
+			 */
+			aml_length =
+			    acpi_rs_set_resource_source(aml,
+							(acpi_rs_length)
+							aml_length, source);
+			acpi_rs_set_resource_length(aml_length, aml);
+			break;
+
+		case ACPI_RSC_SOURCE:
+			/*
+			 * Optional resource_source (Index and String). This is the more
+			 * complicated case used by the Interrupt() macro
+			 */
+			aml_length =
+			    acpi_rs_set_resource_source(aml, info->value,
+							source);
+			acpi_rs_set_resource_length(aml_length, aml);
+			break;
+
+		case ACPI_RSC_BITMASK:
+			/*
+			 * 8-bit encoded bitmask (DMA macro)
+			 */
+			ACPI_SET8(destination) = (u8)
+			    acpi_rs_encode_bitmask(source,
+						   *ACPI_ADD_PTR(u8, resource,
+								 info->value));
+			break;
+
+		case ACPI_RSC_BITMASK16:
+			/*
+			 * 16-bit encoded bitmask (IRQ macro)
+			 */
+			temp16 = acpi_rs_encode_bitmask(source,
+							*ACPI_ADD_PTR(u8,
+								      resource,
+								      info->
+								      value));
+			ACPI_MOVE_16_TO_16(destination, &temp16);
+			break;
+
+		case ACPI_RSC_EXIT_LE:
+			/*
+			 * Control - Exit conversion if less than or equal
+			 */
+			if (item_count <= info->value) {
+				goto exit;
+			}
+			break;
+
+		case ACPI_RSC_EXIT_NE:
+			/*
+			 * Control - Exit conversion if not equal
+			 */
+			switch (COMPARE_OPCODE(info)) {
+			case ACPI_RSC_COMPARE_VALUE:
+
+				if (*ACPI_ADD_PTR(u8, resource,
+						  COMPARE_TARGET(info)) !=
+				    COMPARE_VALUE(info)) {
+					goto exit;
+				}
+				break;
+
+			default:
+
+				ACPI_ERROR((AE_INFO,
+					    "Invalid conversion sub-opcode"));
+				return_ACPI_STATUS(AE_BAD_PARAMETER);
+			}
+			break;
+
+		default:
+
+			ACPI_ERROR((AE_INFO, "Invalid conversion opcode"));
+			return_ACPI_STATUS(AE_BAD_PARAMETER);
+		}
+
+		count--;
+		info++;
 	}
 
-	buffer += 1;
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+      exit:
 	return_ACPI_STATUS(AE_OK);
 }
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_rs_end_depend_fns_stream
- *
- * PARAMETERS:  linked_list             - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's return buffer
- *              bytes_consumed          - Pointer to where the number of bytes
- *                                        used in the output_buffer is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- *              the appropriate bytes in a byte stream
- *
- ******************************************************************************/
+#if 0
+/* Previous resource validations */
 
-acpi_status
-acpi_rs_end_depend_fns_stream(struct acpi_resource *linked_list,
-			      u8 ** output_buffer, acpi_size * bytes_consumed)
-{
-	u8 *buffer = *output_buffer;
-
-	ACPI_FUNCTION_TRACE("rs_end_depend_fns_stream");
-
-	/* The descriptor field is static */
-
-	*buffer = 0x38;
-	buffer += 1;
-
-	/* Return the number of bytes consumed in this operation */
-
-	*bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-	return_ACPI_STATUS(AE_OK);
+if (aml->ext_address64.revision_iD != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) {
+	return_ACPI_STATUS(AE_SUPPORT);
 }
+
+if (resource->data.start_dpf.performance_robustness >= 3) {
+	return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
+}
+
+if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) {
+	/*
+	 * Only [active_high, edge_sensitive] or [active_low, level_sensitive]
+	 * polarity/trigger interrupts are allowed (ACPI spec, section
+	 * "IRQ Format"), so 0x00 and 0x09 are illegal.
+	 */
+	ACPI_ERROR((AE_INFO,
+		    "Invalid interrupt polarity/trigger in resource list, %X",
+		    aml->irq.flags));
+	return_ACPI_STATUS(AE_BAD_DATA);
+}
+
+resource->data.extended_irq.interrupt_count = temp8;
+if (temp8 < 1) {
+	/* Must have at least one IRQ */
+
+	return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
+}
+
+if (resource->data.dma.transfer == 0x03) {
+	ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)"));
+	return_ACPI_STATUS(AE_BAD_DATA);
+}
+#endif
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index 4446778..25b5aed 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,389 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_rs_decode_bitmask
+ *
+ * PARAMETERS:  Mask            - Bitmask to decode
+ *              List            - Where the converted list is returned
+ *
+ * RETURN:      Count of bits set (length of list)
+ *
+ * DESCRIPTION: Convert a bit mask into a list of values
+ *
+ ******************************************************************************/
+u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
+{
+	acpi_native_uint i;
+	u8 bit_count;
+
+	ACPI_FUNCTION_ENTRY();
+
+	/* Decode the mask bits */
+
+	for (i = 0, bit_count = 0; mask; i++) {
+		if (mask & 0x0001) {
+			list[bit_count] = (u8) i;
+			bit_count++;
+		}
+
+		mask >>= 1;
+	}
+
+	return (bit_count);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_encode_bitmask
+ *
+ * PARAMETERS:  List            - List of values to encode
+ *              Count           - Length of list
+ *
+ * RETURN:      Encoded bitmask
+ *
+ * DESCRIPTION: Convert a list of values to an encoded bitmask
+ *
+ ******************************************************************************/
+
+u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
+{
+	acpi_native_uint i;
+	u16 mask;
+
+	ACPI_FUNCTION_ENTRY();
+
+	/* Encode the list into a single bitmask */
+
+	for (i = 0, mask = 0; i < count; i++) {
+		mask |= (0x0001 << list[i]);
+	}
+
+	return (mask);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_move_data
+ *
+ * PARAMETERS:  Destination         - Pointer to the destination descriptor
+ *              Source              - Pointer to the source descriptor
+ *              item_count          - How many items to move
+ *              move_type           - Byte width
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Move multiple data items from one descriptor to another. Handles
+ *              alignment issues and endian issues if necessary, as configured
+ *              via the ACPI_MOVE_* macros. (This is why a memcpy is not used)
+ *
+ ******************************************************************************/
+
+void
+acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
+{
+	acpi_native_uint i;
+
+	ACPI_FUNCTION_ENTRY();
+
+	/* One move per item */
+
+	for (i = 0; i < item_count; i++) {
+		switch (move_type) {
+			/*
+			 * For the 8-bit case, we can perform the move all at once
+			 * since there are no alignment or endian issues
+			 */
+		case ACPI_RSC_MOVE8:
+			ACPI_MEMCPY(destination, source, item_count);
+			return;
+
+			/*
+			 * 16-, 32-, and 64-bit cases must use the move macros that perform
+			 * endian conversion and/or accomodate hardware that cannot perform
+			 * misaligned memory transfers
+			 */
+		case ACPI_RSC_MOVE16:
+			ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i],
+					   &ACPI_CAST_PTR(u16, source)[i]);
+			break;
+
+		case ACPI_RSC_MOVE32:
+			ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i],
+					   &ACPI_CAST_PTR(u32, source)[i]);
+			break;
+
+		case ACPI_RSC_MOVE64:
+			ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i],
+					   &ACPI_CAST_PTR(u64, source)[i]);
+			break;
+
+		default:
+			return;
+		}
+	}
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_set_resource_length
+ *
+ * PARAMETERS:  total_length        - Length of the AML descriptor, including
+ *                                    the header and length fields.
+ *              Aml                 - Pointer to the raw AML descriptor
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Set the resource_length field of an AML
+ *              resource descriptor, both Large and Small descriptors are
+ *              supported automatically. Note: Descriptor Type field must
+ *              be valid.
+ *
+ ******************************************************************************/
+
+void
+acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
+			    union aml_resource *aml)
+{
+	acpi_rs_length resource_length;
+
+	ACPI_FUNCTION_ENTRY();
+
+	/* Length is the total descriptor length minus the header length */
+
+	resource_length = (acpi_rs_length)
+	    (total_length - acpi_ut_get_resource_header_length(aml));
+
+	/* Length is stored differently for large and small descriptors */
+
+	if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
+		/* Large descriptor -- bytes 1-2 contain the 16-bit length */
+
+		ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
+				   &resource_length);
+	} else {
+		/* Small descriptor -- bits 2:0 of byte 0 contain the length */
+
+		aml->small_header.descriptor_type = (u8)
+
+		    /* Clear any existing length, preserving descriptor type bits */
+		    ((aml->small_header.
+		      descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
+
+		     | resource_length);
+	}
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_set_resource_header
+ *
+ * PARAMETERS:  descriptor_type     - Byte to be inserted as the type
+ *              total_length        - Length of the AML descriptor, including
+ *                                    the header and length fields.
+ *              Aml                 - Pointer to the raw AML descriptor
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML
+ *              resource descriptor, both Large and Small descriptors are
+ *              supported automatically
+ *
+ ******************************************************************************/
+
+void
+acpi_rs_set_resource_header(u8 descriptor_type,
+			    acpi_rsdesc_size total_length,
+			    union aml_resource *aml)
+{
+	ACPI_FUNCTION_ENTRY();
+
+	/* Set the Resource Type */
+
+	aml->small_header.descriptor_type = descriptor_type;
+
+	/* Set the Resource Length */
+
+	acpi_rs_set_resource_length(total_length, aml);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_strcpy
+ *
+ * PARAMETERS:  Destination         - Pointer to the destination string
+ *              Source              - Pointer to the source string
+ *
+ * RETURN:      String length, including NULL terminator
+ *
+ * DESCRIPTION: Local string copy that returns the string length, saving a
+ *              strcpy followed by a strlen.
+ *
+ ******************************************************************************/
+
+static u16 acpi_rs_strcpy(char *destination, char *source)
+{
+	u16 i;
+
+	ACPI_FUNCTION_ENTRY();
+
+	for (i = 0; source[i]; i++) {
+		destination[i] = source[i];
+	}
+
+	destination[i] = 0;
+
+	/* Return string length including the NULL terminator */
+
+	return ((u16) (i + 1));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_get_resource_source
+ *
+ * PARAMETERS:  resource_length     - Length field of the descriptor
+ *              minimum_length      - Minimum length of the descriptor (minus
+ *                                    any optional fields)
+ *              resource_source     - Where the resource_source is returned
+ *              Aml                 - Pointer to the raw AML descriptor
+ *              string_ptr          - (optional) where to store the actual
+ *                                    resource_source string
+ *
+ * RETURN:      Length of the string plus NULL terminator, rounded up to 32 bit
+ *
+ * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
+ *              to an internal resource descriptor
+ *
+ ******************************************************************************/
+
+acpi_rs_length
+acpi_rs_get_resource_source(acpi_rs_length resource_length,
+			    acpi_rs_length minimum_length,
+			    struct acpi_resource_source * resource_source,
+			    union aml_resource * aml, char *string_ptr)
+{
+	acpi_rsdesc_size total_length;
+	u8 *aml_resource_source;
+
+	ACPI_FUNCTION_ENTRY();
+
+	total_length =
+	    resource_length + sizeof(struct aml_resource_large_header);
+	aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
+
+	/*
+	 * resource_source is present if the length of the descriptor is longer than
+	 * the minimum length.
+	 *
+	 * Note: Some resource descriptors will have an additional null, so
+	 * we add 1 to the minimum length.
+	 */
+	if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) {
+		/* Get the resource_source_index */
+
+		resource_source->index = aml_resource_source[0];
+
+		resource_source->string_ptr = string_ptr;
+		if (!string_ptr) {
+			/*
+			 * String destination pointer is not specified; Set the String
+			 * pointer to the end of the current resource_source structure.
+			 */
+			resource_source->string_ptr =
+			    ACPI_ADD_PTR(char, resource_source,
+					 sizeof(struct acpi_resource_source));
+		}
+
+		/*
+		 * In order for the struct_size to fall on a 32-bit boundary, calculate
+		 * the length of the string (+1 for the NULL terminator) and expand the
+		 * struct_size to the next 32-bit boundary.
+		 *
+		 * Zero the entire area of the buffer.
+		 */
+		total_length =
+		    ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN
+					     ((char *)&aml_resource_source[1]) +
+					     1);
+		ACPI_MEMSET(resource_source->string_ptr, 0, total_length);
+
+		/* Copy the resource_source string to the destination */
+
+		resource_source->string_length =
+		    acpi_rs_strcpy(resource_source->string_ptr,
+				   (char *)&aml_resource_source[1]);
+
+		return ((acpi_rs_length) total_length);
+	}
+
+	/* resource_source is not present */
+
+	resource_source->index = 0;
+	resource_source->string_length = 0;
+	resource_source->string_ptr = NULL;
+	return (0);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_set_resource_source
+ *
+ * PARAMETERS:  Aml                 - Pointer to the raw AML descriptor
+ *              minimum_length      - Minimum length of the descriptor (minus
+ *                                    any optional fields)
+ *              resource_source     - Internal resource_source
+
+ *
+ * RETURN:      Total length of the AML descriptor
+ *
+ * DESCRIPTION: Convert an optional resource_source from internal format to a
+ *              raw AML resource descriptor
+ *
+ ******************************************************************************/
+
+acpi_rsdesc_size
+acpi_rs_set_resource_source(union aml_resource * aml,
+			    acpi_rs_length minimum_length,
+			    struct acpi_resource_source * resource_source)
+{
+	u8 *aml_resource_source;
+	acpi_rsdesc_size descriptor_length;
+
+	ACPI_FUNCTION_ENTRY();
+
+	descriptor_length = minimum_length;
+
+	/* Non-zero string length indicates presence of a resource_source */
+
+	if (resource_source->string_length) {
+		/* Point to the end of the AML descriptor */
+
+		aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
+
+		/* Copy the resource_source_index */
+
+		aml_resource_source[0] = (u8) resource_source->index;
+
+		/* Copy the resource_source string */
+
+		ACPI_STRCPY((char *)&aml_resource_source[1],
+			    resource_source->string_ptr);
+
+		/*
+		 * Add the length of the string (+ 1 for null terminator) to the
+		 * final descriptor length
+		 */
+		descriptor_length +=
+		    ((acpi_rsdesc_size) resource_source->string_length + 1);
+	}
+
+	/* Return the new total length of the AML descriptor */
+
+	return (descriptor_length);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_rs_get_prt_method_data
  *
  * PARAMETERS:  Handle          - a handle to the containing object
@@ -65,8 +448,9 @@
  *              and the contents of the callers buffer is undefined.
  *
  ******************************************************************************/
+
 acpi_status
-acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
+acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
 {
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
@@ -284,7 +668,7 @@
 	 * Convert the linked list into a byte stream
 	 */
 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
-	status = acpi_rs_create_byte_stream(in_buffer->pointer, &buffer);
+	status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index ee5a5c5..88b6707 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -57,13 +57,17 @@
 	ACPI_COPY_FIELD(out, in, decode);                    \
 	ACPI_COPY_FIELD(out, in, min_address_fixed);         \
 	ACPI_COPY_FIELD(out, in, max_address_fixed);         \
-	ACPI_COPY_FIELD(out, in, attribute);                 \
+	ACPI_COPY_FIELD(out, in, info);                      \
 	ACPI_COPY_FIELD(out, in, granularity);               \
-	ACPI_COPY_FIELD(out, in, min_address_range);         \
-	ACPI_COPY_FIELD(out, in, max_address_range);         \
-	ACPI_COPY_FIELD(out, in, address_translation_offset); \
+	ACPI_COPY_FIELD(out, in, minimum);                   \
+	ACPI_COPY_FIELD(out, in, maximum);                   \
+	ACPI_COPY_FIELD(out, in, translation_offset);        \
 	ACPI_COPY_FIELD(out, in, address_length);            \
 	ACPI_COPY_FIELD(out, in, resource_source);
+/* Local prototypes */
+static acpi_status
+acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_irq_routing_table
@@ -86,6 +90,7 @@
  *              the object indicated by the passed device_handle.
  *
  ******************************************************************************/
+
 acpi_status
 acpi_get_irq_routing_table(acpi_handle device_handle,
 			   struct acpi_buffer *ret_buffer)
@@ -222,12 +227,12 @@
  *
  * FUNCTION:    acpi_walk_resources
  *
- * PARAMETERS:  device_handle   - a handle to the device object for the
+ * PARAMETERS:  device_handle   - Handle to the device object for the
  *                                device we are querying
- *              Path            - method name of the resources we want
+ *              Name            - Method name of the resources we want
  *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
- *              user_function   - called for each resource
- *              Context         - passed to user_function
+ *              user_function   - Called for each resource
+ *              Context         - Passed to user_function
  *
  * RETURN:      Status
  *
@@ -239,79 +244,74 @@
 
 acpi_status
 acpi_walk_resources(acpi_handle device_handle,
-		    char *path,
+		    char *name,
 		    ACPI_WALK_RESOURCE_CALLBACK user_function, void *context)
 {
 	acpi_status status;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_buffer buffer;
 	struct acpi_resource *resource;
-	struct acpi_resource *buffer_end;
+	struct acpi_resource *resource_end;
 
 	ACPI_FUNCTION_TRACE("acpi_walk_resources");
 
-	if (!device_handle ||
-	    (ACPI_STRNCMP(path, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) &&
-	     ACPI_STRNCMP(path, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) {
+	/* Parameter validation */
+
+	if (!device_handle || !user_function || !name ||
+	    (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) &&
+	     ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	status = acpi_rs_get_method_data(device_handle, path, &buffer);
+	/* Get the _CRS or _PRS resource list */
+
+	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+	status = acpi_rs_get_method_data(device_handle, name, &buffer);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
 
-	/* Setup pointers */
+	/* Buffer now contains the resource list */
 
-	resource = (struct acpi_resource *)buffer.pointer;
-	buffer_end = ACPI_CAST_PTR(struct acpi_resource,
-				   ((u8 *) buffer.pointer + buffer.length));
+	resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer);
+	resource_end =
+	    ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length);
 
-	/* Walk the resource list */
+	/* Walk the resource list until the end_tag is found (or buffer end) */
 
-	for (;;) {
-		if (!resource || resource->id == ACPI_RSTYPE_END_TAG) {
+	while (resource < resource_end) {
+		/* Sanity check the resource */
+
+		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
+			status = AE_AML_INVALID_RESOURCE_TYPE;
 			break;
 		}
 
+		/* Invoke the user function, abort on any error returned */
+
 		status = user_function(resource, context);
+		if (ACPI_FAILURE(status)) {
+			if (status == AE_CTRL_TERMINATE) {
+				/* This is an OK termination by the user function */
 
-		switch (status) {
-		case AE_OK:
-		case AE_CTRL_DEPTH:
-
-			/* Just keep going */
-
-			status = AE_OK;
+				status = AE_OK;
+			}
 			break;
+		}
 
-		case AE_CTRL_TERMINATE:
+		/* end_tag indicates end-of-list */
 
-			/* Exit now, with OK stats */
-
-			status = AE_OK;
-			goto cleanup;
-
-		default:
-
-			/* All others are valid exceptions */
-
-			goto cleanup;
+		if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
+			break;
 		}
 
 		/* Get the next resource descriptor */
 
-		resource = ACPI_NEXT_RESOURCE(resource);
-
-		/* Check for end-of-buffer */
-
-		if (resource >= buffer_end) {
-			goto cleanup;
-		}
+		resource =
+		    ACPI_ADD_PTR(struct acpi_resource, resource,
+				 resource->length);
 	}
 
-      cleanup:
-
-	acpi_os_free(buffer.pointer);
+	ACPI_MEM_FREE(buffer.pointer);
 	return_ACPI_STATUS(status);
 }
 
@@ -360,8 +360,8 @@
  *
  * FUNCTION:    acpi_resource_to_address64
  *
- * PARAMETERS:  resource                - Pointer to a resource
- *              out                     - Pointer to the users's return
+ * PARAMETERS:  Resource                - Pointer to a resource
+ *              Out                     - Pointer to the users's return
  *                                        buffer (a struct
  *                                        struct acpi_resource_address64)
  *
@@ -381,20 +381,26 @@
 	struct acpi_resource_address16 *address16;
 	struct acpi_resource_address32 *address32;
 
-	switch (resource->id) {
-	case ACPI_RSTYPE_ADDRESS16:
+	if (!resource || !out) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	/* Convert 16 or 32 address descriptor to 64 */
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
 
 		address16 = (struct acpi_resource_address16 *)&resource->data;
 		ACPI_COPY_ADDRESS(out, address16);
 		break;
 
-	case ACPI_RSTYPE_ADDRESS32:
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
 
 		address32 = (struct acpi_resource_address32 *)&resource->data;
 		ACPI_COPY_ADDRESS(out, address32);
 		break;
 
-	case ACPI_RSTYPE_ADDRESS64:
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
 
 		/* Simple copy for 64 bit source */
 
@@ -410,3 +416,113 @@
 }
 
 EXPORT_SYMBOL(acpi_resource_to_address64);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_get_vendor_resource
+ *
+ * PARAMETERS:  device_handle       - Handle for the parent device object
+ *              Name                - Method name for the parent resource
+ *                                    (METHOD_NAME__CRS or METHOD_NAME__PRS)
+ *              Uuid                - Pointer to the UUID to be matched.
+ *                                    includes both subtype and 16-byte UUID
+ *              ret_buffer          - Where the vendor resource is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Walk a resource template for the specified evice to find a
+ *              vendor-defined resource that matches the supplied UUID and
+ *              UUID subtype. Returns a struct acpi_resource of type Vendor.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_get_vendor_resource(acpi_handle device_handle,
+			 char *name,
+			 struct acpi_vendor_uuid * uuid,
+			 struct acpi_buffer * ret_buffer)
+{
+	struct acpi_vendor_walk_info info;
+	acpi_status status;
+
+	/* Other parameters are validated by acpi_walk_resources */
+
+	if (!uuid || !ret_buffer) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	info.uuid = uuid;
+	info.buffer = ret_buffer;
+	info.status = AE_NOT_EXIST;
+
+	/* Walk the _CRS or _PRS resource list for this device */
+
+	status =
+	    acpi_walk_resources(device_handle, name,
+				acpi_rs_match_vendor_resource, &info);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	return (info.status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_match_vendor_resource
+ *
+ * PARAMETERS:  ACPI_WALK_RESOURCE_CALLBACK
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
+{
+	struct acpi_vendor_walk_info *info = context;
+	struct acpi_resource_vendor_typed *vendor;
+	struct acpi_buffer *buffer;
+	acpi_status status;
+
+	/* Ignore all descriptors except Vendor */
+
+	if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) {
+		return (AE_OK);
+	}
+
+	vendor = &resource->data.vendor_typed;
+
+	/*
+	 * For a valid match, these conditions must hold:
+	 *
+	 * 1) Length of descriptor data must be at least as long as a UUID struct
+	 * 2) The UUID subtypes must match
+	 * 3) The UUID data must match
+	 */
+	if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) ||
+	    (vendor->uuid_subtype != info->uuid->subtype) ||
+	    (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) {
+		return (AE_OK);
+	}
+
+	/* Validate/Allocate/Clear caller buffer */
+
+	buffer = info->buffer;
+	status = acpi_ut_initialize_buffer(buffer, resource->length);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	/* Found the correct resource, copy and return it */
+
+	ACPI_MEMCPY(buffer->pointer, resource, resource->length);
+	buffer->length = resource->length;
+
+	/* Found the desired descriptor, terminate resource walk */
+
+	info->status = AE_OK;
+	return (AE_CTRL_TERMINATE);
+}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 3b26a71..9271e52 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -851,7 +851,7 @@
 	 * ----
 	 * Fix for the system root bus device -- the only root-level device.
 	 */
-	if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
+	if (((acpi_handle)parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
 		hid = ACPI_BUS_HID;
 		strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
 		strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c
index af7935a..47fb4b3 100644
--- a/drivers/acpi/sleep/poweroff.c
+++ b/drivers/acpi/sleep/poweroff.c
@@ -33,9 +33,7 @@
 	ACPI_FLUSH_CPU_CACHE();
 	acpi_enable_wakeup_device_prep(acpi_state);
 #endif
-	if (acpi_state == ACPI_STATE_S5) {
-		acpi_wakeup_gpe_poweroff_prepare();
-	}
+	acpi_gpe_sleep_prepare(acpi_state);
 	acpi_enter_sleep_state_prep(acpi_state);
 	return 0;
 }
@@ -53,11 +51,16 @@
 
 static int acpi_shutdown(struct sys_device *x)
 {
-	if (system_state == SYSTEM_POWER_OFF) {
-		/* Prepare if we are going to power off the system */
+	switch (system_state) {
+	case SYSTEM_POWER_OFF:
+		/* Prepare to power off the system */
 		return acpi_sleep_prepare(ACPI_STATE_S5);
+	case SYSTEM_SUSPEND_DISK:
+		/* Prepare to suspend the system to disk */
+		return acpi_sleep_prepare(ACPI_STATE_S4);
+	default:
+		return 0;
 	}
-	return 0;
 }
 
 static struct sysdev_class acpi_sysclass = {
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
index efd0001..f3e7039 100644
--- a/drivers/acpi/sleep/sleep.h
+++ b/drivers/acpi/sleep/sleep.h
@@ -5,4 +5,4 @@
 extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
 extern void acpi_enable_wakeup_device(u8 sleep_state);
 extern void acpi_disable_wakeup_device(u8 sleep_state);
-extern void acpi_wakeup_gpe_poweroff_prepare(void);
+extern void acpi_gpe_sleep_prepare(u32 sleep_state);
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index 4134ed4..85df0ce 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -192,7 +192,7 @@
  * RUNTIME GPEs, we simply mark all GPES that
  * are not enabled for wakeup from S5 as RUNTIME.
  */
-void acpi_wakeup_gpe_poweroff_prepare(void)
+void acpi_gpe_sleep_prepare(u32 sleep_state)
 {
 	struct list_head *node, *next;
 
@@ -201,8 +201,8 @@
 						       struct acpi_device,
 						       wakeup_list);
 
-		/* The GPE can wakeup system from S5, don't touch it */
-		if ((u32) dev->wakeup.sleep_state == ACPI_STATE_S5)
+		/* The GPE can wakeup system from this state, don't touch it */
+		if ((u32) dev->wakeup.sleep_state >= sleep_state)
 			continue;
 		/* acpi_set_gpe_type will automatically disable GPE */
 		acpi_set_gpe_type(dev->wakeup.gpe_device,
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
index a039393..03b37d2 100644
--- a/drivers/acpi/tables/tbconvrt.c
+++ b/drivers/acpi/tables/tbconvrt.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -501,8 +501,8 @@
 	 * at least as long as the version 1.0 FADT
 	 */
 	if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) {
-		ACPI_REPORT_ERROR(("FADT is invalid, too short: 0x%X\n",
-				   acpi_gbl_FADT->length));
+		ACPI_ERROR((AE_INFO, "FADT is invalid, too short: 0x%X",
+			    acpi_gbl_FADT->length));
 		return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
 	}
 
@@ -517,7 +517,10 @@
 		if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) {
 			/* Length is too short to be a V2.0 table */
 
-			ACPI_REPORT_WARNING(("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n", acpi_gbl_FADT->length, acpi_gbl_FADT->revision));
+			ACPI_WARNING((AE_INFO,
+				      "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table",
+				      acpi_gbl_FADT->length,
+				      acpi_gbl_FADT->revision));
 
 			acpi_tb_convert_fadt1(local_fadt,
 					      (void *)acpi_gbl_FADT);
@@ -554,7 +557,9 @@
 	ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
 			  "Hex dump of common internal FADT, size %d (%X)\n",
 			  acpi_gbl_FADT->length, acpi_gbl_FADT->length));
-	ACPI_DUMP_BUFFER((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length);
+
+	ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_FADT),
+			 acpi_gbl_FADT->length);
 
 	return_ACPI_STATUS(AE_OK);
 }
@@ -580,13 +585,15 @@
 	/* Absolute minimum length is 24, but the ACPI spec says 64 */
 
 	if (acpi_gbl_FACS->length < 24) {
-		ACPI_REPORT_ERROR(("Invalid FACS table length: 0x%X\n",
-				   acpi_gbl_FACS->length));
+		ACPI_ERROR((AE_INFO, "Invalid FACS table length: 0x%X",
+			    acpi_gbl_FACS->length));
 		return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
 	}
 
 	if (acpi_gbl_FACS->length < 64) {
-		ACPI_REPORT_WARNING(("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n", acpi_gbl_FACS->length));
+		ACPI_WARNING((AE_INFO,
+			      "FACS is shorter than the ACPI specification allows: 0x%X, using anyway",
+			      acpi_gbl_FACS->length));
 	}
 
 	/* Copy fields to the new FACS */
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 6acd5ae..09b4ee6 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -91,9 +91,9 @@
 
 	status = acpi_tb_get_table_body(address, &header, table_info);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not get ACPI table (size %X), %s\n",
-				   header.length,
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not get ACPI table (size %X)",
+				header.length));
 		return_ACPI_STATUS(status);
 	}
 
@@ -148,7 +148,6 @@
 					    sizeof(struct acpi_table_header),
 					    (void *)&header);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("Could not map memory at %8.8X%8.8X for length %X\n", ACPI_FORMAT_UINT64(address->pointer.physical), sizeof(struct acpi_table_header)));
 			return_ACPI_STATUS(status);
 		}
 
@@ -161,8 +160,8 @@
 
 	default:
 
-		ACPI_REPORT_ERROR(("Invalid address flags %X\n",
-				   address->pointer_type));
+		ACPI_ERROR((AE_INFO, "Invalid address flags %X",
+			    address->pointer_type));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -253,8 +252,8 @@
 	if (ACPI_FAILURE(status)) {
 		/* Some severe error from the OSL, but we basically ignore it */
 
-		ACPI_REPORT_ERROR(("Could not override ACPI table, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not override ACPI table"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -273,15 +272,14 @@
 
 	status = acpi_tb_get_this_table(&address, new_table, table_info);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not copy override ACPI table, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "Could not copy ACPI table"));
 		return_ACPI_STATUS(status);
 	}
 
 	/* Copy the table info */
 
-	ACPI_REPORT_INFO(("Table [%4.4s] replaced by host OS\n",
-			  table_info->pointer->signature));
+	ACPI_INFO((AE_INFO, "Table [%4.4s] replaced by host OS",
+		   table_info->pointer->signature));
 
 	return_ACPI_STATUS(AE_OK);
 }
@@ -327,7 +325,9 @@
 
 		full_table = ACPI_MEM_ALLOCATE(header->length);
 		if (!full_table) {
-			ACPI_REPORT_ERROR(("Could not allocate table memory for [%4.4s] length %X\n", header->signature, header->length));
+			ACPI_ERROR((AE_INFO,
+				    "Could not allocate table memory for [%4.4s] length %X",
+				    header->signature, header->length));
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
 
@@ -351,7 +351,12 @@
 					    (acpi_size) header->length,
 					    (void *)&full_table);
 		if (ACPI_FAILURE(status)) {
-			ACPI_REPORT_ERROR(("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n", header->signature, ACPI_FORMAT_UINT64(address->pointer.physical), header->length));
+			ACPI_ERROR((AE_INFO,
+				    "Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X",
+				    header->signature,
+				    ACPI_FORMAT_UINT64(address->pointer.
+						       physical),
+				    header->length));
 			return (status);
 		}
 
@@ -362,8 +367,8 @@
 
 	default:
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid address flags %X\n",
-				  address->pointer_type));
+		ACPI_ERROR((AE_INFO, "Invalid address flags %X",
+			    address->pointer_type));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c
index 8d72343..134e5dc 100644
--- a/drivers/acpi/tables/tbgetall.c
+++ b/drivers/acpi/tables/tbgetall.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -152,7 +152,9 @@
 	/* Signature must match request */
 
 	if (ACPI_STRNCMP(header.signature, signature, ACPI_NAME_SIZE)) {
-		ACPI_REPORT_ERROR(("Incorrect table signature - wanted [%s] found [%4.4s]\n", signature, header.signature));
+		ACPI_ERROR((AE_INFO,
+			    "Incorrect table signature - wanted [%s] found [%4.4s]",
+			    signature, header.signature));
 		return_ACPI_STATUS(AE_BAD_SIGNATURE);
 	}
 
@@ -231,14 +233,18 @@
 		 */
 		status = acpi_tb_get_primary_table(&address, &table_info);
 		if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) {
-			ACPI_REPORT_WARNING(("%s, while getting table at %8.8X%8.8X\n", acpi_format_exception(status), ACPI_FORMAT_UINT64(address.pointer.value)));
+			ACPI_WARNING((AE_INFO,
+				      "%s, while getting table at %8.8X%8.8X",
+				      acpi_format_exception(status),
+				      ACPI_FORMAT_UINT64(address.pointer.
+							 value)));
 		}
 	}
 
 	/* We must have a FADT to continue */
 
 	if (!acpi_gbl_FADT) {
-		ACPI_REPORT_ERROR(("No FADT present in RSDT/XSDT\n"));
+		ACPI_ERROR((AE_INFO, "No FADT present in RSDT/XSDT"));
 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
 	}
 
@@ -248,7 +254,8 @@
 	 */
 	status = acpi_tb_convert_table_fadt();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not convert FADT to internal common format\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Could not convert FADT to internal common format"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -258,8 +265,8 @@
 
 	status = acpi_tb_get_secondary_table(&address, FACS_SIG, &table_info);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not get/install the FACS, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not get/install the FACS"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -278,7 +285,7 @@
 
 	status = acpi_tb_get_secondary_table(&address, DSDT_SIG, &table_info);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not get/install the DSDT\n"));
+		ACPI_ERROR((AE_INFO, "Could not get/install the DSDT"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -292,7 +299,9 @@
 			  "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n",
 			  acpi_gbl_DSDT->length, acpi_gbl_DSDT->length,
 			  acpi_gbl_integer_bit_width));
-	ACPI_DUMP_BUFFER((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length);
+
+	ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_DSDT),
+			 acpi_gbl_DSDT->length);
 
 	/* Always delete the RSDP mapping, we are done with it */
 
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 10db848..7ffd0fd 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -128,8 +128,8 @@
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not acquire table mutex, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not acquire table mutex"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -146,9 +146,9 @@
 
 	status = acpi_tb_init_table_descriptor(table_info->type, table_info);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Could not install table [%4.4s], %s\n",
-				   table_info->pointer->signature,
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not install table [%4.4s]",
+				table_info->pointer->signature));
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n",
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
index ad0252c..4d30822 100644
--- a/drivers/acpi/tables/tbrsdt.c
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -176,7 +176,7 @@
 {
 	int no_match;
 
-	ACPI_FUNCTION_NAME("tb_validate_rsdt");
+	ACPI_FUNCTION_ENTRY();
 
 	/*
 	 * Search for appropriate signature, RSDT or XSDT
@@ -192,24 +192,24 @@
 	if (no_match) {
 		/* Invalid RSDT or XSDT signature */
 
-		ACPI_REPORT_ERROR(("Invalid signature where RSDP indicates RSDT/XSDT should be located\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Invalid signature where RSDP indicates RSDT/XSDT should be located. RSDP:"));
 
 		ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20);
 
-		ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR,
-				      "RSDT/XSDT signature at %X (%p) is invalid\n",
-				      acpi_gbl_RSDP->rsdt_physical_address,
-				      (void *)(acpi_native_uint) acpi_gbl_RSDP->
-				      rsdt_physical_address));
+		ACPI_ERROR((AE_INFO,
+			    "RSDT/XSDT signature at %X (%p) is invalid",
+			    acpi_gbl_RSDP->rsdt_physical_address,
+			    (void *)(acpi_native_uint) acpi_gbl_RSDP->
+			    rsdt_physical_address));
 
 		if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
-			ACPI_REPORT_ERROR(("Looking for RSDT\n"))
+			ACPI_ERROR((AE_INFO, "Looking for RSDT"));
 		} else {
-			ACPI_REPORT_ERROR(("Looking for XSDT\n"))
+			ACPI_ERROR((AE_INFO, "Looking for XSDT"));
 		}
 
 		ACPI_DUMP_BUFFER((char *)table_ptr, 48);
-
 		return (AE_BAD_SIGNATURE);
 	}
 
@@ -243,15 +243,13 @@
 	table_info.type = ACPI_TABLE_XSDT;
 	status = acpi_tb_get_table(&address, &table_info);
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Could not get the RSDT/XSDT, %s\n",
-				  acpi_format_exception(status)));
-
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not get the RSDT/XSDT"));
 		return_ACPI_STATUS(status);
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n",
+			  "RSDP located at %p, points to RSDT physical=%8.8X%8.8X\n",
 			  acpi_gbl_RSDP,
 			  ACPI_FORMAT_UINT64(address.pointer.value)));
 
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index 4b2fbb5..bc57159 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -94,9 +94,8 @@
 		     new_table_desc->pointer->length)
 		    &&
 		    (!ACPI_MEMCMP
-		     ((const char *)table_desc->pointer,
-		      (const char *)new_table_desc->pointer,
-		      (acpi_size) new_table_desc->pointer->length))) {
+		     (table_desc->pointer, new_table_desc->pointer,
+		      new_table_desc->pointer->length))) {
 			/* Match: this table is already installed */
 
 			ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
@@ -145,14 +144,13 @@
 {
 	acpi_name signature;
 
-	ACPI_FUNCTION_NAME("tb_validate_table_header");
+	ACPI_FUNCTION_ENTRY();
 
 	/* Verify that this is a valid address */
 
 	if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Cannot read table header at %p\n",
-				  table_header));
+		ACPI_ERROR((AE_INFO,
+			    "Cannot read table header at %p", table_header));
 
 		return (AE_BAD_ADDRESS);
 	}
@@ -161,12 +159,12 @@
 
 	ACPI_MOVE_32_TO_32(&signature, table_header->signature);
 	if (!acpi_ut_valid_acpi_name(signature)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Table signature at %p [%p] has invalid characters\n",
-				  table_header, &signature));
+		ACPI_ERROR((AE_INFO,
+			    "Table signature at %p [%p] has invalid characters",
+			    table_header, &signature));
 
-		ACPI_REPORT_WARNING(("Invalid table signature found: [%4.4s]\n",
-				     (char *)&signature));
+		ACPI_WARNING((AE_INFO, "Invalid table signature found: [%4.4s]",
+			      ACPI_CAST_PTR(char, &signature)));
 
 		ACPI_DUMP_BUFFER(table_header,
 				 sizeof(struct acpi_table_header));
@@ -176,11 +174,13 @@
 	/* Validate the table length */
 
 	if (table_header->length < sizeof(struct acpi_table_header)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Invalid length in table header %p name %4.4s\n",
-				  table_header, (char *)&signature));
+		ACPI_ERROR((AE_INFO,
+			    "Invalid length in table header %p name %4.4s",
+			    table_header, (char *)&signature));
 
-		ACPI_REPORT_WARNING(("Invalid table header length (0x%X) found\n", (u32) table_header->length));
+		ACPI_WARNING((AE_INFO,
+			      "Invalid table header length (0x%X) found",
+			      (u32) table_header->length));
 
 		ACPI_DUMP_BUFFER(table_header,
 				 sizeof(struct acpi_table_header));
@@ -219,7 +219,10 @@
 	/* Return the appropriate exception */
 
 	if (checksum) {
-		ACPI_REPORT_WARNING(("Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n", table_header->signature, (u32) table_header->checksum, (u32) checksum));
+		ACPI_WARNING((AE_INFO,
+			      "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)",
+			      table_header->signature,
+			      (u32) table_header->checksum, (u32) checksum));
 
 		status = AE_BAD_CHECKSUM;
 	}
@@ -241,16 +244,16 @@
 
 u8 acpi_tb_generate_checksum(void *buffer, u32 length)
 {
-	const u8 *limit;
-	const u8 *rover;
+	u8 *end_buffer;
+	u8 *rover;
 	u8 sum = 0;
 
 	if (buffer && length) {
 		/*  Buffer and Length are valid   */
 
-		limit = (u8 *) buffer + length;
+		end_buffer = ACPI_ADD_PTR(u8, buffer, length);
 
-		for (rover = buffer; rover < limit; rover++) {
+		for (rover = buffer; rover < end_buffer; rover++) {
 			sum = (u8) (sum + *rover);
 		}
 	}
@@ -292,8 +295,7 @@
 		}
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "table_id=%X does not exist\n",
-			  table_id));
+	ACPI_ERROR((AE_INFO, "table_id=%X does not exist", table_id));
 	return (AE_BAD_PARAMETER);
 }
 #endif
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 3f96a49..9fe53c9 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -75,8 +75,7 @@
 	status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING,
 					  &rsdp_address);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("acpi_load_tables: Could not get RSDP, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP"));
 		goto error_exit;
 	}
 
@@ -86,7 +85,7 @@
 
 	status = acpi_tb_verify_rsdp(&rsdp_address);
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("acpi_load_tables: RSDP Failed validation: %s\n", acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation"));
 		goto error_exit;
 	}
 
@@ -94,7 +93,7 @@
 
 	status = acpi_tb_get_table_rsdt();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("acpi_load_tables: Could not load RSDT: %s\n", acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT"));
 		goto error_exit;
 	}
 
@@ -102,7 +101,8 @@
 
 	status = acpi_tb_get_required_tables();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not get all required tables (DSDT/FADT/FACS)"));
 		goto error_exit;
 	}
 
@@ -112,16 +112,14 @@
 
 	status = acpi_ns_load_namespace();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("acpi_load_tables: Could not load namespace: %s\n", acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace"));
 		goto error_exit;
 	}
 
 	return_ACPI_STATUS(AE_OK);
 
       error_exit:
-	ACPI_REPORT_ERROR(("acpi_load_tables: Could not load tables: %s\n",
-			   acpi_format_exception(status)));
-
+	ACPI_EXCEPTION((AE_INFO, status, "Could not load tables"));
 	return_ACPI_STATUS(status);
 }
 
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index 3b8a7e0..a62db6a 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -251,7 +251,7 @@
 
 	acpi_tb_get_rsdt_address(&address);
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
+			  "RSDP located at %p, RSDT physical=%8.8X%8.8X\n",
 			  acpi_gbl_RSDP,
 			  ACPI_FORMAT_UINT64(address.pointer.value)));
 
@@ -396,9 +396,8 @@
 
 	status = acpi_tb_find_rsdp(&table_info, flags);
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "RSDP structure not found, %s Flags=%X\n",
-				  acpi_format_exception(status), flags));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"RSDP structure not found - Flags=%X", flags));
 
 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
 	}
@@ -503,10 +502,10 @@
 					    ACPI_EBDA_PTR_LENGTH,
 					    (void *)&table_ptr);
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Could not map memory at %8.8X for length %X\n",
-					  ACPI_EBDA_PTR_LOCATION,
-					  ACPI_EBDA_PTR_LENGTH));
+			ACPI_ERROR((AE_INFO,
+				    "Could not map memory at %8.8X for length %X",
+				    ACPI_EBDA_PTR_LOCATION,
+				    ACPI_EBDA_PTR_LENGTH));
 
 			return_ACPI_STATUS(status);
 		}
@@ -530,10 +529,10 @@
 						    ACPI_EBDA_WINDOW_SIZE,
 						    (void *)&table_ptr);
 			if (ACPI_FAILURE(status)) {
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Could not map memory at %8.8X for length %X\n",
-						  physical_address,
-						  ACPI_EBDA_WINDOW_SIZE));
+				ACPI_ERROR((AE_INFO,
+					    "Could not map memory at %8.8X for length %X",
+					    physical_address,
+					    ACPI_EBDA_WINDOW_SIZE));
 
 				return_ACPI_STATUS(status);
 			}
@@ -563,10 +562,10 @@
 					    (void *)&table_ptr);
 
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Could not map memory at %8.8X for length %X\n",
-					  ACPI_HI_RSDP_WINDOW_BASE,
-					  ACPI_HI_RSDP_WINDOW_SIZE));
+			ACPI_ERROR((AE_INFO,
+				    "Could not map memory at %8.8X for length %X",
+				    ACPI_HI_RSDP_WINDOW_BASE,
+				    ACPI_HI_RSDP_WINDOW_SIZE));
 
 			return_ACPI_STATUS(status);
 		}
@@ -635,7 +634,7 @@
 
 	/* A valid RSDP was not found */
 
-	ACPI_REPORT_ERROR(("No valid RSDP was found\n"));
+	ACPI_ERROR((AE_INFO, "No valid RSDP was found"));
 	return_ACPI_STATUS(AE_NOT_FOUND);
 }
 
diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile
index e87108b..88eff14 100644
--- a/drivers/acpi/utilities/Makefile
+++ b/drivers/acpi/utilities/Makefile
@@ -2,7 +2,8 @@
 # Makefile for all Linux ACPI interpreter subdirectories
 #
 
-obj-y := utalloc.o  utdebug.o   uteval.o    utinit.o  utmisc.o    utxface.o \
-	 utcopy.o   utdelete.o  utglobal.o  utmath.o  utobject.o utstate.o utmutex.o utobject.o utcache.o
+obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
+		utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
+		utstate.o utmutex.o utobject.o utcache.o utresrc.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 068450b..03b0044 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
 ACPI_MODULE_NAME("utalloc")
 
 /* Local prototypes */
-#ifdef	ACPI_DBG_TRACK_ALLOCATIONS
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
 static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation);
 
 static acpi_status
@@ -58,9 +58,7 @@
 static acpi_status
 acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
 			  u32 component, char *module, u32 line);
-#endif				/* ACPI_DBG_TRACK_ALLOCATIONS */
 
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
 static acpi_status
 acpi_ut_create_list(char *list_name,
 		    u16 object_size, struct acpi_memory_list **return_cache);
@@ -303,8 +301,8 @@
 	/* Check for an inadvertent size of zero bytes */
 
 	if (!size) {
-		_ACPI_REPORT_ERROR(module, line, component,
-				   ("ut_allocate: Attempt to allocate zero bytes\n"));
+		ACPI_ERROR((module, line,
+			    "ut_allocate: Attempt to allocate zero bytes, allocating 1 byte"));
 		size = 1;
 	}
 
@@ -312,9 +310,9 @@
 	if (!allocation) {
 		/* Report allocation error */
 
-		_ACPI_REPORT_ERROR(module, line, component,
-				   ("ut_allocate: Could not allocate size %X\n",
-				    (u32) size));
+		ACPI_ERROR((module, line,
+			    "ut_allocate: Could not allocate size %X",
+			    (u32) size));
 
 		return_PTR(NULL);
 	}
@@ -346,18 +344,17 @@
 	/* Check for an inadvertent size of zero bytes */
 
 	if (!size) {
-		_ACPI_REPORT_ERROR(module, line, component,
-				   ("ut_callocate: Attempt to allocate zero bytes\n"));
-		return_PTR(NULL);
+		ACPI_ERROR((module, line,
+			    "Attempt to allocate zero bytes, allocating 1 byte"));
+		size = 1;
 	}
 
 	allocation = acpi_os_allocate(size);
 	if (!allocation) {
 		/* Report allocation error */
 
-		_ACPI_REPORT_ERROR(module, line, component,
-				   ("ut_callocate: Could not allocate size %X\n",
-				    (u32) size));
+		ACPI_ERROR((module, line,
+			    "Could not allocate size %X", (u32) size));
 		return_PTR(NULL);
 	}
 
@@ -482,9 +479,8 @@
 	if (!allocation) {
 		/* Report allocation error */
 
-		_ACPI_REPORT_ERROR(module, line, component,
-				   ("ut_callocate: Could not allocate size %X\n",
-				    (u32) size));
+		ACPI_ERROR((module, line,
+			    "Could not allocate size %X", (u32) size));
 		return (NULL);
 	}
 
@@ -526,8 +522,7 @@
 	ACPI_FUNCTION_TRACE_PTR("ut_free", allocation);
 
 	if (NULL == allocation) {
-		_ACPI_REPORT_ERROR(module, line, component,
-				   ("acpi_ut_free: Attempt to delete a NULL address\n"));
+		ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
 
 		return_VOID;
 	}
@@ -542,14 +537,11 @@
 	status = acpi_ut_remove_allocation(debug_block,
 					   component, module, line);
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Could not free memory, %s\n",
-				  acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
 	}
 
 	acpi_os_free(debug_block);
-
 	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
-
 	return_VOID;
 }
 
@@ -626,10 +618,12 @@
 	 */
 	element = acpi_ut_find_allocation(allocation);
 	if (element) {
-		ACPI_REPORT_ERROR(("ut_track_allocation: Allocation already present in list! (%p)\n", allocation));
+		ACPI_ERROR((AE_INFO,
+			    "ut_track_allocation: Allocation already present in list! (%p)",
+			    allocation));
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Element %p Address %p\n",
-				  element, allocation));
+		ACPI_ERROR((AE_INFO, "Element %p Address %p",
+			    element, allocation));
 
 		goto unlock_and_exit;
 	}
@@ -689,8 +683,8 @@
 	if (NULL == mem_list->list_head) {
 		/* No allocations! */
 
-		_ACPI_REPORT_ERROR(module, line, component,
-				   ("ut_remove_allocation: Empty allocation list, nothing to free!\n"));
+		ACPI_ERROR((module, line,
+			    "Empty allocation list, nothing to free!"));
 
 		return_ACPI_STATUS(AE_OK);
 	}
@@ -865,12 +859,11 @@
 	/* Print summary */
 
 	if (!num_outstanding) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "No outstanding allocations.\n"));
+		ACPI_INFO((AE_INFO, "No outstanding allocations"));
 	} else {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "%d(%X) Outstanding allocations\n",
-				  num_outstanding, num_outstanding));
+		ACPI_ERROR((AE_INFO,
+			    "%d(%X) Outstanding allocations",
+			    num_outstanding, num_outstanding));
 	}
 
 	return_VOID;
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
index 93d4868..2177cb1 100644
--- a/drivers/acpi/utilities/utcache.c
+++ b/drivers/acpi/utilities/utcache.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 5442b32..df2d320 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -398,14 +398,17 @@
 		 * Build a simple object (no nested objects)
 		 */
 		status = acpi_ut_copy_isimple_to_esimple(internal_object,
-							 (union acpi_object *)
-							 ret_buffer->pointer,
-							 ((u8 *) ret_buffer->
-							  pointer +
-							  ACPI_ROUND_UP_TO_NATIVE_WORD
-							  (sizeof
-							   (union
-							    acpi_object))),
+							 ACPI_CAST_PTR(union
+								       acpi_object,
+								       ret_buffer->
+								       pointer),
+							 ACPI_ADD_PTR(u8,
+								      ret_buffer->
+								      pointer,
+								      ACPI_ROUND_UP_TO_NATIVE_WORD
+								      (sizeof
+								       (union
+									acpi_object))),
 							 &ret_buffer->length);
 		/*
 		 * build simple does not include the object size in the length
@@ -603,8 +606,8 @@
 		/*
 		 * Packages as external input to control methods are not supported,
 		 */
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Packages as parameters not implemented!\n"));
+		ACPI_ERROR((AE_INFO,
+			    "Packages as parameters not implemented!"));
 
 		return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
 	}
@@ -867,7 +870,7 @@
 							 count +
 							 1) * sizeof(void *));
 	if (!dest_obj->package.elements) {
-		ACPI_REPORT_ERROR(("aml_build_copy_internal_package_object: Package allocation failure\n"));
+		ACPI_ERROR((AE_INFO, "Package allocation failure"));
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index d80e926..35f3d58 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index 2bc878f..1db9695 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -363,8 +363,7 @@
 
 	default:
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown action (%X)\n",
-				  action));
+		ACPI_ERROR((AE_INFO, "Unknown action (%X)", action));
 		break;
 	}
 
@@ -374,9 +373,9 @@
 	 */
 	if (count > ACPI_MAX_REFERENCE_COUNT) {
 
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-				  "**** Warning **** Large Reference Count (%X) in object %p\n\n",
-				  count, object));
+		ACPI_WARNING((AE_INFO,
+			      "Large Reference Count (%X) in object %p",
+			      count, object));
 	}
 
 	return;
@@ -535,8 +534,8 @@
 
       error_exit:
 
-	ACPI_REPORT_ERROR(("Could not update object reference count, %s\n",
-			   acpi_format_exception(status)));
+	ACPI_EXCEPTION((AE_INFO, status,
+			"Could not update object reference count"));
 
 	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index 7b81d5e..106cc97 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/utilities/uteval.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -95,7 +95,9 @@
 
 	for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) {
 		if (!ACPI_STRCMP(string_desc->string.pointer,
-				 (char *)acpi_gbl_valid_osi_strings[i])) {
+				 ACPI_CAST_PTR(char,
+					       acpi_gbl_valid_osi_strings[i])))
+		{
 			/* This string is supported */
 
 			return_desc->integer.value = 0xFFFFFFFF;
@@ -152,8 +154,8 @@
 					  acpi_ut_get_node_name(prefix_node),
 					  path));
 		} else {
-			ACPI_REPORT_METHOD_ERROR("Method execution failed",
-						 prefix_node, path, status);
+			ACPI_ERROR_METHOD("Method execution failed",
+					  prefix_node, path, status);
 		}
 
 		return_ACPI_STATUS(status);
@@ -163,9 +165,8 @@
 
 	if (!info.return_object) {
 		if (expected_return_btypes) {
-			ACPI_REPORT_METHOD_ERROR("No object was returned from",
-						 prefix_node, path,
-						 AE_NOT_EXIST);
+			ACPI_ERROR_METHOD("No object was returned from",
+					  prefix_node, path, AE_NOT_EXIST);
 
 			return_ACPI_STATUS(AE_NOT_EXIST);
 		}
@@ -210,15 +211,14 @@
 	/* Is the return object one of the expected types? */
 
 	if (!(expected_return_btypes & return_btype)) {
-		ACPI_REPORT_METHOD_ERROR("Return object type is incorrect",
-					 prefix_node, path, AE_TYPE);
+		ACPI_ERROR_METHOD("Return object type is incorrect",
+				  prefix_node, path, AE_TYPE);
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Type returned from %s was incorrect: %s, expected Btypes: %X\n",
-				  path,
-				  acpi_ut_get_object_type_name(info.
-							       return_object),
-				  expected_return_btypes));
+		ACPI_ERROR((AE_INFO,
+			    "Type returned from %s was incorrect: %s, expected Btypes: %X",
+			    path,
+			    acpi_ut_get_object_type_name(info.return_object),
+			    expected_return_btypes));
 
 		/* On error exit, we must delete the return object */
 
@@ -592,7 +592,7 @@
 					  "_STA on %4.4s was not found, assuming device is present\n",
 					  acpi_ut_get_node_name(device_node)));
 
-			*flags = 0x0F;
+			*flags = ACPI_UINT32_MAX;
 			status = AE_OK;
 		}
 
@@ -637,17 +637,17 @@
 	for (i = 0; i < 4; i++) {
 		highest[i] = 0xFF;
 		status = acpi_ut_evaluate_object(device_node,
-						 (char *)
-						 acpi_gbl_highest_dstate_names
-						 [i], ACPI_BTYPE_INTEGER,
-						 &obj_desc);
+						 ACPI_CAST_PTR(char,
+							       acpi_gbl_highest_dstate_names
+							       [i]),
+						 ACPI_BTYPE_INTEGER, &obj_desc);
 		if (ACPI_FAILURE(status)) {
 			if (status != AE_NOT_FOUND) {
 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 						  "%s on Device %4.4s, %s\n",
-						  (char *)
-						  acpi_gbl_highest_dstate_names
-						  [i],
+						  ACPI_CAST_PTR(char,
+								acpi_gbl_highest_dstate_names
+								[i]),
 						  acpi_ut_get_node_name
 						  (device_node),
 						  acpi_format_exception
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index 399e64b..ffd1338 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -67,8 +67,11 @@
 	acpi_status sub_status;
 	const char *exception = NULL;
 
-	ACPI_FUNCTION_NAME("format_exception");
+	ACPI_FUNCTION_ENTRY();
 
+	/*
+	 * Status is composed of two parts, a "type" and an actual code
+	 */
 	sub_status = (status & ~AE_CODE_MASK);
 
 	switch (status & AE_CODE_MASK) {
@@ -118,13 +121,13 @@
 	if (!exception) {
 		/* Exception code was not recognized */
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unknown exception code: 0x%8.8X\n", status));
+		ACPI_ERROR((AE_INFO,
+			    "Unknown exception code: 0x%8.8X", status));
 
-		return ((const char *)"UNKNOWN_STATUS_CODE");
+		exception = "UNKNOWN_STATUS_CODE";
 	}
 
-	return ((const char *)exception);
+	return (ACPI_CAST_PTR(const char, exception));
 }
 
 /*******************************************************************************
@@ -217,23 +220,23 @@
  * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to
  *    perform a Notify() operation on it.
  */
-const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
-    { {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
-{"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
-{"_SB_", ACPI_TYPE_DEVICE, NULL},
-{"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
-{"_TZ_", ACPI_TYPE_THERMAL, NULL},
-{"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
-{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
-{"_GL_", ACPI_TYPE_MUTEX, (char *)1},
+const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = {
+	{"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
+	{"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
+	{"_SB_", ACPI_TYPE_DEVICE, NULL},
+	{"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
+	{"_TZ_", ACPI_TYPE_THERMAL, NULL},
+	{"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
+	{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
+	{"_GL_", ACPI_TYPE_MUTEX, (char *)1},
 
 #if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
-{"_OSI", ACPI_TYPE_METHOD, (char *)1},
+	{"_OSI", ACPI_TYPE_METHOD, (char *)1},
 #endif
 
 	/* Table terminator */
 
-{NULL, ACPI_TYPE_ANY, NULL}
+	{NULL, ACPI_TYPE_ANY, NULL}
 };
 
 /*
@@ -485,7 +488,7 @@
 		return ("invalid_space_id");
 	}
 
-	return ((char *)acpi_gbl_region_types[space_id]);
+	return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id]));
 }
 
 /*******************************************************************************
@@ -503,11 +506,13 @@
 /* Event type decoding */
 
 static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = {
+/*! [Begin] no source code translation (keep these strings as-is) */
 	"PM_Timer",
-	"global_lock",
-	"power_button",
-	"sleep_button",
-	"real_time_clock",
+	"GlobalLock",
+	"PowerButton",
+	"SleepButton",
+	"RealTimeClock",
+/*! [End] no source code translation !*/
 };
 
 char *acpi_ut_get_event_name(u32 event_id)
@@ -517,7 +522,7 @@
 		return ("invalid_event_iD");
 	}
 
-	return ((char *)acpi_gbl_event_types[event_id]);
+	return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id]));
 }
 
 /*******************************************************************************
@@ -545,12 +550,13 @@
 /* Printable names of the ACPI object types */
 
 static const char *acpi_gbl_ns_type_names[] = {
+/*! [Begin] no source code translation (keep these strings as-is) */
 	/* 00 */ "Untyped",
 	/* 01 */ "Integer",
 	/* 02 */ "String",
 	/* 03 */ "Buffer",
 	/* 04 */ "Package",
-	/* 05 */ "field_unit",
+	/* 05 */ "FieldUnit",
 	/* 06 */ "Device",
 	/* 07 */ "Event",
 	/* 08 */ "Method",
@@ -559,33 +565,34 @@
 	/* 11 */ "Power",
 	/* 12 */ "Processor",
 	/* 13 */ "Thermal",
-	/* 14 */ "buffer_field",
-	/* 15 */ "ddb_handle",
-	/* 16 */ "debug_object",
-	/* 17 */ "region_field",
-	/* 18 */ "bank_field",
-	/* 19 */ "index_field",
+	/* 14 */ "BufferField",
+	/* 15 */ "DdbHandle",
+	/* 16 */ "DebugObject",
+	/* 17 */ "RegionField",
+	/* 18 */ "BankField",
+	/* 19 */ "IndexField",
 	/* 20 */ "Reference",
 	/* 21 */ "Alias",
-	/* 22 */ "method_alias",
+	/* 22 */ "MethodAlias",
 	/* 23 */ "Notify",
-	/* 24 */ "addr_handler",
-	/* 25 */ "resource_desc",
-	/* 26 */ "resource_fld",
+	/* 24 */ "AddrHandler",
+	/* 25 */ "ResourceDesc",
+	/* 26 */ "ResourceFld",
 	/* 27 */ "Scope",
 	/* 28 */ "Extra",
 	/* 29 */ "Data",
 	/* 30 */ "Invalid"
+/*! [End] no source code translation !*/
 };
 
 char *acpi_ut_get_type_name(acpi_object_type type)
 {
 
 	if (type > ACPI_TYPE_INVALID) {
-		return ((char *)acpi_gbl_bad_type);
+		return (ACPI_CAST_PTR(char, acpi_gbl_bad_type));
 	}
 
-	return ((char *)acpi_gbl_ns_type_names[type]);
+	return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type]));
 }
 
 char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
@@ -634,7 +641,7 @@
 
 	/* Name must be a valid ACPI name */
 
-	if (!acpi_ut_valid_acpi_name(*(u32 *) node->name.ascii)) {
+	if (!acpi_ut_valid_acpi_name(node->name.integer)) {
 		return ("????");
 	}
 
@@ -658,15 +665,16 @@
 /* Printable names of object descriptor types */
 
 static const char *acpi_gbl_desc_type_names[] = {
+/*! [Begin] no source code translation (keep these ASL Keywords as-is) */
 	/* 00 */ "Invalid",
 	/* 01 */ "Cached",
 	/* 02 */ "State-Generic",
 	/* 03 */ "State-Update",
 	/* 04 */ "State-Package",
 	/* 05 */ "State-Control",
-	/* 06 */ "State-root_parse_scope",
-	/* 07 */ "State-parse_scope",
-	/* 08 */ "State-walk_scope",
+	/* 06 */ "State-RootParseScope",
+	/* 07 */ "State-ParseScope",
+	/* 08 */ "State-WalkScope",
 	/* 09 */ "State-Result",
 	/* 10 */ "State-Notify",
 	/* 11 */ "State-Thread",
@@ -674,6 +682,7 @@
 	/* 13 */ "Parser",
 	/* 14 */ "Operand",
 	/* 15 */ "Node"
+/*! [End] no source code translation !*/
 };
 
 char *acpi_ut_get_descriptor_name(void *object)
@@ -684,11 +693,12 @@
 	}
 
 	if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) {
-		return ((char *)acpi_gbl_bad_type);
+		return (ACPI_CAST_PTR(char, acpi_gbl_bad_type));
 	}
 
-	return ((char *)
-		acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE(object)]);
+	return (ACPI_CAST_PTR(char,
+			      acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE
+						       (object)]));
 
 }
 
@@ -787,6 +797,11 @@
 		acpi_gbl_mutex_info[i].use_count = 0;
 	}
 
+	for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) {
+		acpi_gbl_owner_id_mask[i] = 0;
+	}
+	acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000;	/* Last ID is never valid */
+
 	/* GPE support */
 
 	acpi_gbl_gpe_xrupt_list_head = NULL;
@@ -824,7 +839,11 @@
 	acpi_gbl_ns_lookup_count = 0;
 	acpi_gbl_ps_find_count = 0;
 	acpi_gbl_acpi_hardware_present = TRUE;
-	acpi_gbl_owner_id_mask = 0;
+	acpi_gbl_last_owner_id_index = 0;
+	acpi_gbl_next_owner_id_offset = 0;
+	acpi_gbl_trace_method_name = 0;
+	acpi_gbl_trace_dbg_level = 0;
+	acpi_gbl_trace_dbg_layer = 0;
 	acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
 	acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
 
@@ -836,7 +855,6 @@
 	/* Namespace */
 
 	acpi_gbl_root_node = NULL;
-
 	acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
 	acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED;
 	acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c
index 9dde82b..ba771b4 100644
--- a/drivers/acpi/utilities/utinit.c
+++ b/drivers/acpi/utilities/utinit.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -72,9 +72,9 @@
 acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset)
 {
 
-	ACPI_REPORT_WARNING(("Invalid FADT value %s=%X at offset %X FADT=%p\n",
-			     register_name, value, (u32) offset,
-			     acpi_gbl_FADT));
+	ACPI_WARNING((AE_INFO,
+		      "Invalid FADT value %s=%X at offset %X FADT=%p",
+		      register_name, value, (u32) offset, acpi_gbl_FADT));
 }
 
 /******************************************************************************
@@ -221,15 +221,14 @@
 	/* Just exit if subsystem is already shutdown */
 
 	if (acpi_gbl_shutdown) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "ACPI Subsystem is already terminated\n"));
+		ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated"));
 		return_VOID;
 	}
 
 	/* Subsystem appears active, go ahead and shut it down */
 
 	acpi_gbl_shutdown = TRUE;
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem...\n"));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
 
 	/* Close the acpi_event Handling */
 
diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c
index 68a0a6f..4a33604 100644
--- a/drivers/acpi/utilities/utmath.c
+++ b/drivers/acpi/utilities/utmath.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -82,7 +82,7 @@
 	/* Always check for a zero divisor */
 
 	if (divisor == 0) {
-		ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n"));
+		ACPI_ERROR((AE_INFO, "Divide by zero"));
 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
 	}
 
@@ -144,7 +144,7 @@
 	/* Always check for a zero divisor */
 
 	if (in_divisor == 0) {
-		ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n"));
+		ACPI_ERROR((AE_INFO, "Divide by zero"));
 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
 	}
 
@@ -266,7 +266,7 @@
 	/* Always check for a zero divisor */
 
 	if (divisor == 0) {
-		ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n"));
+		ACPI_ERROR((AE_INFO, "Divide by zero"));
 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
 	}
 
@@ -292,7 +292,7 @@
 	/* Always check for a zero divisor */
 
 	if (in_divisor == 0) {
-		ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n"));
+		ACPI_ERROR((AE_INFO, "Divide by zero"));
 		return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
 	}
 
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 2ce872d..7364f5f 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,8 @@
 acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
 {
 	acpi_native_uint i;
+	acpi_native_uint j;
+	acpi_native_uint k;
 	acpi_status status;
 
 	ACPI_FUNCTION_TRACE("ut_allocate_owner_id");
@@ -70,8 +72,8 @@
 	/* Guard against multiple allocations of ID to the same location */
 
 	if (*owner_id) {
-		ACPI_REPORT_ERROR(("Owner ID [%2.2X] already exists\n",
-				   *owner_id));
+		ACPI_ERROR((AE_INFO, "Owner ID [%2.2X] already exists",
+			    *owner_id));
 		return_ACPI_STATUS(AE_ALREADY_EXISTS);
 	}
 
@@ -82,31 +84,67 @@
 		return_ACPI_STATUS(status);
 	}
 
-	/* Find a free owner ID */
-
-	for (i = 0; i < 64; i++) {
-		if (!(acpi_gbl_owner_id_mask & (1ULL << i))) {
-			ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
-					  "Current owner_id mask: %16.16LX New ID: %2.2X\n",
-					  acpi_gbl_owner_id_mask,
-					  (unsigned int)(i + 1)));
-
-			acpi_gbl_owner_id_mask |= (1ULL << i);
-			*owner_id = (acpi_owner_id) (i + 1);
-			goto exit;
+	/*
+	 * Find a free owner ID, cycle through all possible IDs on repeated
+	 * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
+	 * to be scanned twice.
+	 */
+	for (i = 0, j = acpi_gbl_last_owner_id_index;
+	     i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) {
+		if (j >= ACPI_NUM_OWNERID_MASKS) {
+			j = 0;	/* Wraparound to start of mask array */
 		}
+
+		for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) {
+			if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) {
+				/* There are no free IDs in this mask */
+
+				break;
+			}
+
+			if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) {
+				/*
+				 * Found a free ID. The actual ID is the bit index plus one,
+				 * making zero an invalid Owner ID. Save this as the last ID
+				 * allocated and update the global ID mask.
+				 */
+				acpi_gbl_owner_id_mask[j] |= (1 << k);
+
+				acpi_gbl_last_owner_id_index = (u8) j;
+				acpi_gbl_next_owner_id_offset = (u8) (k + 1);
+
+				/*
+				 * Construct encoded ID from the index and bit position
+				 *
+				 * Note: Last [j].k (bit 255) is never used and is marked
+				 * permanently allocated (prevents +1 overflow)
+				 */
+				*owner_id =
+				    (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j));
+
+				ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
+						  "Allocated owner_id: %2.2X\n",
+						  (unsigned int)*owner_id));
+				goto exit;
+			}
+		}
+
+		acpi_gbl_next_owner_id_offset = 0;
 	}
 
 	/*
-	 * If we are here, all owner_ids have been allocated. This probably should
+	 * All owner_ids have been allocated. This typically should
 	 * not happen since the IDs are reused after deallocation. The IDs are
 	 * allocated upon table load (one per table) and method execution, and
 	 * they are released when a table is unloaded or a method completes
 	 * execution.
+	 *
+	 * If this error happens, there may be very deep nesting of invoked control
+	 * methods, or there may be a bug where the IDs are not released.
 	 */
-	*owner_id = 0;
 	status = AE_OWNER_ID_LIMIT;
-	ACPI_REPORT_ERROR(("Could not allocate new owner_id (64 max), AE_OWNER_ID_LIMIT\n"));
+	ACPI_ERROR((AE_INFO,
+		    "Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT"));
 
       exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
@@ -123,7 +161,7 @@
  *              control method or unloading a table. Either way, we would
  *              ignore any error anyway.
  *
- * DESCRIPTION: Release a table or method owner ID.  Valid IDs are 1 - 64
+ * DESCRIPTION: Release a table or method owner ID.  Valid IDs are 1 - 255
  *
  ******************************************************************************/
 
@@ -131,6 +169,8 @@
 {
 	acpi_owner_id owner_id = *owner_id_ptr;
 	acpi_status status;
+	acpi_native_uint index;
+	u32 bit;
 
 	ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id);
 
@@ -140,8 +180,8 @@
 
 	/* Zero is not a valid owner_iD */
 
-	if ((owner_id == 0) || (owner_id > 64)) {
-		ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id));
+	if (owner_id == 0) {
+		ACPI_ERROR((AE_INFO, "Invalid owner_id: %2.2X", owner_id));
 		return_VOID;
 	}
 
@@ -156,10 +196,19 @@
 
 	owner_id--;
 
+	/* Decode ID to index/offset pair */
+
+	index = ACPI_DIV_32(owner_id);
+	bit = 1 << ACPI_MOD_32(owner_id);
+
 	/* Free the owner ID only if it is valid */
 
-	if (acpi_gbl_owner_id_mask & (1ULL << owner_id)) {
-		acpi_gbl_owner_id_mask ^= (1ULL << owner_id);
+	if (acpi_gbl_owner_id_mask[index] & bit) {
+		acpi_gbl_owner_id_mask[index] ^= bit;
+	} else {
+		ACPI_ERROR((AE_INFO,
+			    "Release of non-allocated owner_id: %2.2X",
+			    owner_id + 1));
 	}
 
 	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
@@ -790,109 +839,97 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_get_resource_end_tag
+ * FUNCTION:    acpi_ut_error, acpi_ut_warning, acpi_ut_info
  *
- * PARAMETERS:  obj_desc        - The resource template buffer object
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Format              - Printf format string + additional args
  *
- * RETURN:      Pointer to the end tag
+ * RETURN:      None
  *
- * DESCRIPTION: Find the END_TAG resource descriptor in a resource template
+ * DESCRIPTION: Print message with module/line/version info
  *
  ******************************************************************************/
 
-u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc)
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_error(char *module_name, u32 line_number, char *format, ...)
 {
-	u8 buffer_byte;
-	u8 *buffer;
-	u8 *end_buffer;
+	va_list args;
 
-	buffer = obj_desc->buffer.pointer;
-	end_buffer = buffer + obj_desc->buffer.length;
+	acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
 
-	while (buffer < end_buffer) {
-		buffer_byte = *buffer;
-		if (buffer_byte & ACPI_RDESC_TYPE_MASK) {
-			/* Large Descriptor - Length is next 2 bytes */
+	va_start(args, format);
+	acpi_os_vprintf(format, args);
+	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+}
 
-			buffer += ((*(buffer + 1) | (*(buffer + 2) << 8)) + 3);
-		} else {
-			/* Small Descriptor.  End Tag will be found here */
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_exception(char *module_name,
+		  u32 line_number, acpi_status status, char *format, ...)
+{
+	va_list args;
 
-			if ((buffer_byte & ACPI_RDESC_SMALL_MASK) ==
-			    ACPI_RDESC_TYPE_END_TAG) {
-				/* Found the end tag descriptor, all done. */
+	acpi_os_printf("ACPI Exception (%s-%04d): %s, ", module_name,
+		       line_number, acpi_format_exception(status));
 
-				return (buffer);
-			}
+	va_start(args, format);
+	acpi_os_vprintf(format, args);
+	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+}
 
-			/* Length is in the header */
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
+{
+	va_list args;
 
-			buffer += ((buffer_byte & 0x07) + 1);
-		}
-	}
+	acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number);
 
-	/* End tag not found */
+	va_start(args, format);
+	acpi_os_vprintf(format, args);
+	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+}
 
-	return (NULL);
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_info(char *module_name, u32 line_number, char *format, ...)
+{
+	va_list args;
+
+	acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number);
+
+	va_start(args, format);
+	acpi_os_vprintf(format, args);
+	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
 }
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_report_error
+ * FUNCTION:    acpi_ut_report_error, Warning, Info
  *
  * PARAMETERS:  module_name         - Caller's module name (for error output)
  *              line_number         - Caller's line number (for error output)
- *              component_id        - Caller's component ID (for error output)
  *
  * RETURN:      None
  *
  * DESCRIPTION: Print error message
  *
+ * Note: Legacy only, should be removed when no longer used by drivers.
+ *
  ******************************************************************************/
 
-void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id)
+void acpi_ut_report_error(char *module_name, u32 line_number)
 {
 
-	acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
+	acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
 }
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_report_warning
- *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *              component_id        - Caller's component ID (for error output)
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print warning message
- *
- ******************************************************************************/
-
-void
-acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id)
+void acpi_ut_report_warning(char *module_name, u32 line_number)
 {
 
-	acpi_os_printf("%8s-%04d: *** Warning: ", module_name, line_number);
+	acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number);
 }
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_report_info
- *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *              component_id        - Caller's component ID (for error output)
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print information message
- *
- ******************************************************************************/
-
-void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id)
+void acpi_ut_report_info(char *module_name, u32 line_number)
 {
 
-	acpi_os_printf("%8s-%04d: *** Info: ", module_name, line_number);
+	acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number);
 }
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
index 90134c5..45a7244 100644
--- a/drivers/acpi/utilities/utmutex.c
+++ b/drivers/acpi/utilities/utmutex.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -214,23 +214,22 @@
 		 * the ACPI subsystem code.
 		 */
 		for (i = mutex_id; i < MAX_MUTEX; i++) {
-			if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
+			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
 				if (i == mutex_id) {
-					ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-							  "Mutex [%s] already acquired by this thread [%X]\n",
-							  acpi_ut_get_mutex_name
-							  (mutex_id),
-							  this_thread_id));
+					ACPI_ERROR((AE_INFO,
+						    "Mutex [%s] already acquired by this thread [%X]",
+						    acpi_ut_get_mutex_name
+						    (mutex_id),
+						    this_thread_id));
 
 					return (AE_ALREADY_ACQUIRED);
 				}
 
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
-						  this_thread_id,
-						  acpi_ut_get_mutex_name(i),
-						  acpi_ut_get_mutex_name
-						  (mutex_id)));
+				ACPI_ERROR((AE_INFO,
+					    "Invalid acquire order: Thread %X owns [%s], wants [%s]",
+					    this_thread_id,
+					    acpi_ut_get_mutex_name(i),
+					    acpi_ut_get_mutex_name(mutex_id)));
 
 				return (AE_ACQUIRE_DEADLOCK);
 			}
@@ -253,11 +252,9 @@
 		acpi_gbl_mutex_info[mutex_id].use_count++;
 		acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
 	} else {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Thread %X could not acquire Mutex [%s] %s\n",
-				  this_thread_id,
-				  acpi_ut_get_mutex_name(mutex_id),
-				  acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Thread %X could not acquire Mutex [%X]",
+				this_thread_id, mutex_id));
 	}
 
 	return (status);
@@ -295,9 +292,9 @@
 	 * Mutex must be acquired in order to release it!
 	 */
 	if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Mutex [%s] is not acquired, cannot release\n",
-				  acpi_ut_get_mutex_name(mutex_id)));
+		ACPI_ERROR((AE_INFO,
+			    "Mutex [%X] is not acquired, cannot release",
+			    mutex_id));
 
 		return (AE_NOT_ACQUIRED);
 	}
@@ -313,16 +310,15 @@
 		 * the ACPI subsystem code.
 		 */
 		for (i = mutex_id; i < MAX_MUTEX; i++) {
-			if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
+			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
 				if (i == mutex_id) {
 					continue;
 				}
 
-				ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-						  "Invalid release order: owns [%s], releasing [%s]\n",
-						  acpi_ut_get_mutex_name(i),
-						  acpi_ut_get_mutex_name
-						  (mutex_id)));
+				ACPI_ERROR((AE_INFO,
+					    "Invalid release order: owns [%s], releasing [%s]",
+					    acpi_ut_get_mutex_name(i),
+					    acpi_ut_get_mutex_name(mutex_id)));
 
 				return (AE_RELEASE_DEADLOCK);
 			}
@@ -338,11 +334,9 @@
 	    acpi_os_signal_semaphore(acpi_gbl_mutex_info[mutex_id].mutex, 1);
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Thread %X could not release Mutex [%s] %s\n",
-				  this_thread_id,
-				  acpi_ut_get_mutex_name(mutex_id),
-				  acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Thread %X could not release Mutex [%X]",
+				this_thread_id, mutex_id));
 	} else {
 		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
 				  "Thread %X released Mutex [%s]\n",
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index 3015e15..7ee2d1d 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -177,7 +177,8 @@
 
 		buffer = ACPI_MEM_CALLOCATE(buffer_size);
 		if (!buffer) {
-			ACPI_REPORT_ERROR(("create_buffer: could not allocate size %X\n", (u32) buffer_size));
+			ACPI_ERROR((AE_INFO, "Could not allocate size %X",
+				    (u32) buffer_size));
 			acpi_ut_remove_reference(buffer_desc);
 			return_PTR(NULL);
 		}
@@ -228,7 +229,8 @@
 	 */
 	string = ACPI_MEM_CALLOCATE(string_size + 1);
 	if (!string) {
-		ACPI_REPORT_ERROR(("create_string: could not allocate size %X\n", (u32) string_size));
+		ACPI_ERROR((AE_INFO, "Could not allocate size %X",
+			    (u32) string_size));
 		acpi_ut_remove_reference(string_desc);
 		return_PTR(NULL);
 	}
@@ -310,8 +312,8 @@
 
 	object = acpi_os_acquire_object(acpi_gbl_operand_cache);
 	if (!object) {
-		_ACPI_REPORT_ERROR(module_name, line_number, component_id,
-				   ("Could not allocate an object descriptor\n"));
+		ACPI_ERROR((module_name, line_number,
+			    "Could not allocate an object descriptor"));
 
 		return_PTR(NULL);
 	}
@@ -345,9 +347,9 @@
 	/* Object must be an union acpi_operand_object    */
 
 	if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "%p is not an ACPI Operand object [%s]\n",
-				  object, acpi_ut_get_descriptor_name(object)));
+		ACPI_ERROR((AE_INFO,
+			    "%p is not an ACPI Operand object [%s]", object,
+			    acpi_ut_get_descriptor_name(object)));
 		return_VOID;
 	}
 
@@ -449,10 +451,10 @@
 			 * Notably, Locals and Args are not supported, but this may be
 			 * required eventually.
 			 */
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-					  "Unsupported Reference opcode=%X in object %p\n",
-					  internal_object->reference.opcode,
-					  internal_object));
+			ACPI_ERROR((AE_INFO,
+				    "Unsupported Reference opcode=%X in object %p",
+				    internal_object->reference.opcode,
+				    internal_object));
 			status = AE_TYPE;
 			break;
 		}
@@ -460,10 +462,9 @@
 
 	default:
 
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Unsupported type=%X in object %p\n",
-				  ACPI_GET_OBJECT_TYPE(internal_object),
-				  internal_object));
+		ACPI_ERROR((AE_INFO, "Unsupported type=%X in object %p",
+			    ACPI_GET_OBJECT_TYPE(internal_object),
+			    internal_object));
 		status = AE_TYPE;
 		break;
 	}
diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c
new file mode 100644
index 0000000..1646131
--- /dev/null
+++ b/drivers/acpi/utilities/utresrc.c
@@ -0,0 +1,554 @@
+/*******************************************************************************
+ *
+ * Module Name: utresrc - Resource managment utilities
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2006, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include <acpi/amlresrc.h>
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utmisc")
+
+#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
+/*
+ * Strings used to decode resource descriptors.
+ * Used by both the disasssembler and the debugger resource dump routines
+ */
+const char *acpi_gbl_BMdecode[2] = {
+	"not_bus_master",
+	"bus_master"
+};
+
+const char *acpi_gbl_config_decode[4] = {
+	"0 - Good Configuration",
+	"1 - Acceptable Configuration",
+	"2 - Suboptimal Configuration",
+	"3 - ***Invalid Configuration***",
+};
+
+const char *acpi_gbl_consume_decode[2] = {
+	"resource_producer",
+	"resource_consumer"
+};
+
+const char *acpi_gbl_DECdecode[2] = {
+	"pos_decode",
+	"sub_decode"
+};
+
+const char *acpi_gbl_HEdecode[2] = {
+	"Level",
+	"Edge"
+};
+
+const char *acpi_gbl_io_decode[2] = {
+	"Decode10",
+	"Decode16"
+};
+
+const char *acpi_gbl_LLdecode[2] = {
+	"active_high",
+	"active_low"
+};
+
+const char *acpi_gbl_max_decode[2] = {
+	"max_not_fixed",
+	"max_fixed"
+};
+
+const char *acpi_gbl_MEMdecode[4] = {
+	"non_cacheable",
+	"Cacheable",
+	"write_combining",
+	"Prefetchable"
+};
+
+const char *acpi_gbl_min_decode[2] = {
+	"min_not_fixed",
+	"min_fixed"
+};
+
+const char *acpi_gbl_MTPdecode[4] = {
+	"address_range_memory",
+	"address_range_reserved",
+	"address_range_aCPI",
+	"address_range_nVS"
+};
+
+const char *acpi_gbl_RNGdecode[4] = {
+	"invalid_ranges",
+	"non_iSAonly_ranges",
+	"ISAonly_ranges",
+	"entire_range"
+};
+
+const char *acpi_gbl_RWdecode[2] = {
+	"read_only",
+	"read_write"
+};
+
+const char *acpi_gbl_SHRdecode[2] = {
+	"Exclusive",
+	"Shared"
+};
+
+const char *acpi_gbl_SIZdecode[4] = {
+	"Transfer8",
+	"Transfer8_16",
+	"Transfer16",
+	"invalid_size"
+};
+
+const char *acpi_gbl_TRSdecode[2] = {
+	"dense_translation",
+	"sparse_translation"
+};
+
+const char *acpi_gbl_TTPdecode[2] = {
+	"type_static",
+	"type_translation"
+};
+
+const char *acpi_gbl_TYPdecode[4] = {
+	"Compatibility",
+	"type_a",
+	"type_b",
+	"type_f"
+};
+
+#endif
+
+/*
+ * Base sizes of the raw AML resource descriptors, indexed by resource type.
+ * Zero indicates a reserved (and therefore invalid) resource type.
+ */
+const u8 acpi_gbl_resource_aml_sizes[] = {
+	/* Small descriptors */
+
+	0,
+	0,
+	0,
+	0,
+	ACPI_AML_SIZE_SMALL(struct aml_resource_irq),
+	ACPI_AML_SIZE_SMALL(struct aml_resource_dma),
+	ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent),
+	ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),
+	ACPI_AML_SIZE_SMALL(struct aml_resource_io),
+	ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io),
+	0,
+	0,
+	0,
+	0,
+	ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small),
+	ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag),
+
+	/* Large descriptors */
+
+	0,
+	ACPI_AML_SIZE_LARGE(struct aml_resource_memory24),
+	ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register),
+	0,
+	ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large),
+	ACPI_AML_SIZE_LARGE(struct aml_resource_memory32),
+	ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32),
+	ACPI_AML_SIZE_LARGE(struct aml_resource_address32),
+	ACPI_AML_SIZE_LARGE(struct aml_resource_address16),
+	ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),
+	ACPI_AML_SIZE_LARGE(struct aml_resource_address64),
+	ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64)
+};
+
+/*
+ * Resource types, used to validate the resource length field.
+ * The length of fixed-length types must match exactly, variable
+ * lengths must meet the minimum required length, etc.
+ * Zero indicates a reserved (and therefore invalid) resource type.
+ */
+static const u8 acpi_gbl_resource_types[] = {
+	/* Small descriptors */
+
+	0,
+	0,
+	0,
+	0,
+	ACPI_SMALL_VARIABLE_LENGTH,
+	ACPI_FIXED_LENGTH,
+	ACPI_SMALL_VARIABLE_LENGTH,
+	ACPI_FIXED_LENGTH,
+	ACPI_FIXED_LENGTH,
+	ACPI_FIXED_LENGTH,
+	0,
+	0,
+	0,
+	0,
+	ACPI_VARIABLE_LENGTH,
+	ACPI_FIXED_LENGTH,
+
+	/* Large descriptors */
+
+	0,
+	ACPI_FIXED_LENGTH,
+	ACPI_FIXED_LENGTH,
+	0,
+	ACPI_VARIABLE_LENGTH,
+	ACPI_FIXED_LENGTH,
+	ACPI_FIXED_LENGTH,
+	ACPI_VARIABLE_LENGTH,
+	ACPI_VARIABLE_LENGTH,
+	ACPI_VARIABLE_LENGTH,
+	ACPI_VARIABLE_LENGTH,
+	ACPI_FIXED_LENGTH
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_validate_resource
+ *
+ * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
+ *              return_index    - Where the resource index is returned. NULL
+ *                                if the index is not required.
+ *
+ * RETURN:      Status, and optionally the Index into the global resource tables
+ *
+ * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
+ *              Type and Resource Length. Returns an index into the global
+ *              resource information/dispatch tables for later use.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
+{
+	u8 resource_type;
+	u8 resource_index;
+	acpi_rs_length resource_length;
+	acpi_rs_length minimum_resource_length;
+
+	ACPI_FUNCTION_ENTRY();
+
+	/*
+	 * 1) Validate the resource_type field (Byte 0)
+	 */
+	resource_type = ACPI_GET8(aml);
+
+	/*
+	 * Byte 0 contains the descriptor name (Resource Type)
+	 * Examine the large/small bit in the resource header
+	 */
+	if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
+		/* Verify the large resource type (name) against the max */
+
+		if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
+			return (AE_AML_INVALID_RESOURCE_TYPE);
+		}
+
+		/*
+		 * Large Resource Type -- bits 6:0 contain the name
+		 * Translate range 0x80-0x8B to index range 0x10-0x1B
+		 */
+		resource_index = (u8) (resource_type - 0x70);
+	} else {
+		/*
+		 * Small Resource Type -- bits 6:3 contain the name
+		 * Shift range to index range 0x00-0x0F
+		 */
+		resource_index = (u8)
+		    ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
+	}
+
+	/* Check validity of the resource type, zero indicates name is invalid */
+
+	if (!acpi_gbl_resource_types[resource_index]) {
+		return (AE_AML_INVALID_RESOURCE_TYPE);
+	}
+
+	/*
+	 * 2) Validate the resource_length field. This ensures that the length
+	 *    is at least reasonable, and guarantees that it is non-zero.
+	 */
+	resource_length = acpi_ut_get_resource_length(aml);
+	minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
+
+	/* Validate based upon the type of resource - fixed length or variable */
+
+	switch (acpi_gbl_resource_types[resource_index]) {
+	case ACPI_FIXED_LENGTH:
+
+		/* Fixed length resource, length must match exactly */
+
+		if (resource_length != minimum_resource_length) {
+			return (AE_AML_BAD_RESOURCE_LENGTH);
+		}
+		break;
+
+	case ACPI_VARIABLE_LENGTH:
+
+		/* Variable length resource, length must be at least the minimum */
+
+		if (resource_length < minimum_resource_length) {
+			return (AE_AML_BAD_RESOURCE_LENGTH);
+		}
+		break;
+
+	case ACPI_SMALL_VARIABLE_LENGTH:
+
+		/* Small variable length resource, length can be (Min) or (Min-1) */
+
+		if ((resource_length > minimum_resource_length) ||
+		    (resource_length < (minimum_resource_length - 1))) {
+			return (AE_AML_BAD_RESOURCE_LENGTH);
+		}
+		break;
+
+	default:
+
+		/* Shouldn't happen (because of validation earlier), but be sure */
+
+		return (AE_AML_INVALID_RESOURCE_TYPE);
+	}
+
+	/* Optionally return the resource table index */
+
+	if (return_index) {
+		*return_index = resource_index;
+	}
+
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_resource_type
+ *
+ * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
+ *
+ * RETURN:      The Resource Type with no extraneous bits (except the
+ *              Large/Small descriptor bit -- this is left alone)
+ *
+ * DESCRIPTION: Extract the Resource Type/Name from the first byte of
+ *              a resource descriptor.
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_get_resource_type(void *aml)
+{
+	ACPI_FUNCTION_ENTRY();
+
+	/*
+	 * Byte 0 contains the descriptor name (Resource Type)
+	 * Examine the large/small bit in the resource header
+	 */
+	if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+		/* Large Resource Type -- bits 6:0 contain the name */
+
+		return (ACPI_GET8(aml));
+	} else {
+		/* Small Resource Type -- bits 6:3 contain the name */
+
+		return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
+	}
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_resource_length
+ *
+ * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
+ *
+ * RETURN:      Byte Length
+ *
+ * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
+ *              definition, this does not include the size of the descriptor
+ *              header or the length field itself.
+ *
+ ******************************************************************************/
+
+u16 acpi_ut_get_resource_length(void *aml)
+{
+	acpi_rs_length resource_length;
+
+	ACPI_FUNCTION_ENTRY();
+
+	/*
+	 * Byte 0 contains the descriptor name (Resource Type)
+	 * Examine the large/small bit in the resource header
+	 */
+	if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+		/* Large Resource type -- bytes 1-2 contain the 16-bit length */
+
+		ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
+
+	} else {
+		/* Small Resource type -- bits 2:0 of byte 0 contain the length */
+
+		resource_length = (u16) (ACPI_GET8(aml) &
+					 ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
+	}
+
+	return (resource_length);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_resource_header_length
+ *
+ * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
+ *
+ * RETURN:      Length of the AML header (depends on large/small descriptor)
+ *
+ * DESCRIPTION: Get the length of the header for this resource.
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_get_resource_header_length(void *aml)
+{
+	ACPI_FUNCTION_ENTRY();
+
+	/* Examine the large/small bit in the resource header */
+
+	if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+		return (sizeof(struct aml_resource_large_header));
+	} else {
+		return (sizeof(struct aml_resource_small_header));
+	}
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_descriptor_length
+ *
+ * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
+ *
+ * RETURN:      Byte length
+ *
+ * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
+ *              length of the descriptor header and the length field itself.
+ *              Used to walk descriptor lists.
+ *
+ ******************************************************************************/
+
+u32 acpi_ut_get_descriptor_length(void *aml)
+{
+	ACPI_FUNCTION_ENTRY();
+
+	/*
+	 * Get the Resource Length (does not include header length) and add
+	 * the header length (depends on if this is a small or large resource)
+	 */
+	return (acpi_ut_get_resource_length(aml) +
+		acpi_ut_get_resource_header_length(aml));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_resource_end_tag
+ *
+ * PARAMETERS:  obj_desc        - The resource template buffer object
+ *              end_tag         - Where the pointer to the end_tag is returned
+ *
+ * RETURN:      Status, pointer to the end tag
+ *
+ * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template
+ *              Note: allows a buffer length of zero.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc,
+			     u8 ** end_tag)
+{
+	acpi_status status;
+	u8 *aml;
+	u8 *end_aml;
+
+	ACPI_FUNCTION_TRACE("ut_get_resource_end_tag");
+
+	/* Get start and end pointers */
+
+	aml = obj_desc->buffer.pointer;
+	end_aml = aml + obj_desc->buffer.length;
+
+	/* Allow a buffer length of zero */
+
+	if (!obj_desc->buffer.length) {
+		*end_tag = aml;
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	/* Walk the resource template, one descriptor per iteration */
+
+	while (aml < end_aml) {
+		/* Validate the Resource Type and Resource Length */
+
+		status = acpi_ut_validate_resource(aml, NULL);
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+
+		/* end_tag resource indicates the end of the resource template */
+
+		if (acpi_ut_get_resource_type(aml) ==
+		    ACPI_RESOURCE_NAME_END_TAG) {
+			/*
+			 * There must be at least one more byte in the buffer for
+			 * the 2nd byte of the end_tag
+			 */
+			if ((aml + 1) >= end_aml) {
+				return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+			}
+
+			/* Return the pointer to the end_tag */
+
+			*end_tag = aml;
+			return_ACPI_STATUS(AE_OK);
+		}
+
+		/*
+		 * Point to the next resource descriptor in the AML buffer. The
+		 * descriptor length is guaranteed to be non-zero by resource
+		 * validation above.
+		 */
+		aml += acpi_ut_get_descriptor_length(aml);
+	}
+
+	/* Did not find an end_tag resource descriptor */
+
+	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+}
diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c
index c1cb275..4b134a7 100644
--- a/drivers/acpi/utilities/utstate.c
+++ b/drivers/acpi/utilities/utstate.c
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,7 @@
 acpi_ut_create_pkg_state_and_push(void *internal_object,
 				  void *external_object,
 				  u16 index,
-				  union acpi_generic_state ** state_list)
+				  union acpi_generic_state **state_list)
 {
 	union acpi_generic_state *state;
 
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index f06bd5e..308a960 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -75,8 +75,7 @@
 
 	status = acpi_os_initialize();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("OSD failed to initialize, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -88,8 +87,8 @@
 
 	status = acpi_ut_mutex_initialize();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Global mutex creation failure, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"During Global Mutex creation"));
 		return_ACPI_STATUS(status);
 	}
 
@@ -99,15 +98,14 @@
 	 */
 	status = acpi_ns_root_initialize();
 	if (ACPI_FAILURE(status)) {
-		ACPI_REPORT_ERROR(("Namespace initialization failure, %s\n",
-				   acpi_format_exception(status)));
+		ACPI_EXCEPTION((AE_INFO, status,
+				"During Namespace initialization"));
 		return_ACPI_STATUS(status);
 	}
 
 	/* If configured, initialize the AML debugger */
 
 	ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
-
 	return_ACPI_STATUS(status);
 }
 
@@ -154,8 +152,7 @@
 
 		status = acpi_enable();
 		if (ACPI_FAILURE(status)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-					  "acpi_enable failed.\n"));
+			ACPI_WARNING((AE_INFO, "acpi_enable failed"));
 			return_ACPI_STATUS(status);
 		}
 	}
@@ -178,10 +175,14 @@
 	/*
 	 * Initialize ACPI Event handling (Fixed and General Purpose)
 	 *
-	 * NOTE: We must have the hardware AND events initialized before we can
-	 * execute ANY control methods SAFELY.  Any control method can require
-	 * ACPI hardware support, so the hardware MUST be initialized before
-	 * execution!
+	 * Note1: We must have the hardware and events initialized before we can
+	 * execute any control methods safely. Any control method can require
+	 * ACPI hardware support, so the hardware must be fully initialized before
+	 * any method execution!
+	 *
+	 * Note2: Fixed events are initialized and enabled here. GPEs are
+	 * initialized, but cannot be enabled until after the hardware is
+	 * completely initialized (SCI and global_lock activated)
 	 */
 	if (!(flags & ACPI_NO_EVENT_INIT)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -193,8 +194,10 @@
 		}
 	}
 
-	/* Install the SCI handler and Global Lock handler */
-
+	/*
+	 * Install the SCI handler and Global Lock handler. This completes the
+	 * hardware initialization.
+	 */
 	if (!(flags & ACPI_NO_HANDLER_INIT)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 				  "[Init] Installing SCI/GL handlers\n"));
@@ -205,6 +208,24 @@
 		}
 	}
 
+	/*
+	 * Complete the GPE initialization for the GPE blocks defined in the FADT
+	 * (GPE block 0 and 1).
+	 *
+	 * Note1: This is where the _PRW methods are executed for the GPEs. These
+	 * methods can only be executed after the SCI and Global Lock handlers are
+	 * installed and initialized.
+	 *
+	 * Note2: Currently, there seems to be no need to run the _REG methods
+	 * before execution of the _PRW methods and enabling of the GPEs.
+	 */
+	if (!(flags & ACPI_NO_EVENT_INIT)) {
+		status = acpi_ev_install_fadt_gpes();
+		if (ACPI_FAILURE(status)) {
+			return (status);
+		}
+	}
+
 	return_ACPI_STATUS(status);
 }
 
@@ -230,9 +251,9 @@
 	/*
 	 * Run all _REG methods
 	 *
-	 * NOTE: Any objects accessed
-	 * by the _REG methods will be automatically initialized, even if they
-	 * contain executable AML (see call to acpi_ns_initialize_objects below).
+	 * Note: Any objects accessed by the _REG methods will be automatically
+	 * initialized, even if they contain executable AML (see the call to
+	 * acpi_ns_initialize_objects below).
 	 */
 	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -245,9 +266,9 @@
 	}
 
 	/*
-	 * Initialize the objects that remain uninitialized.  This
-	 * runs the executable AML that may be part of the declaration of these
-	 * objects: operation_regions, buffer_fields, Buffers, and Packages.
+	 * Initialize the objects that remain uninitialized. This runs the
+	 * executable AML that may be part of the declaration of these objects:
+	 * operation_regions, buffer_fields, Buffers, and Packages.
 	 */
 	if (!(flags & ACPI_NO_OBJECT_INIT)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -260,8 +281,8 @@
 	}
 
 	/*
-	 * Initialize all device objects in the namespace
-	 * This runs the _STA and _INI methods.
+	 * Initialize all device objects in the namespace. This runs the device
+	 * _STA and _INI methods.
 	 */
 	if (!(flags & ACPI_NO_DEVICE_INIT)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index d10668f..bd48875 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -920,8 +920,8 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 				  "Unable to create 'state' fs entry\n"));
 	else {
+		acpi_video_device_state_fops.write = acpi_video_device_write_state;
 		entry->proc_fops = &acpi_video_device_state_fops;
-		entry->proc_fops->write = acpi_video_device_write_state;
 		entry->data = acpi_driver_data(device);
 		entry->owner = THIS_MODULE;
 	}
@@ -934,8 +934,8 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 				  "Unable to create 'brightness' fs entry\n"));
 	else {
+		acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness;
 		entry->proc_fops = &acpi_video_device_brightness_fops;
-		entry->proc_fops->write = acpi_video_device_write_brightness;
 		entry->data = acpi_driver_data(device);
 		entry->owner = THIS_MODULE;
 	}
@@ -1239,8 +1239,8 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 				  "Unable to create 'POST' fs entry\n"));
 	else {
+		acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
 		entry->proc_fops = &acpi_video_bus_POST_fops;
-		entry->proc_fops->write = acpi_video_bus_write_POST;
 		entry->data = acpi_driver_data(device);
 		entry->owner = THIS_MODULE;
 	}
@@ -1253,8 +1253,8 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 				  "Unable to create 'DOS' fs entry\n"));
 	else {
+		acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
 		entry->proc_fops = &acpi_video_bus_DOS_fops;
-		entry->proc_fops->write = acpi_video_bus_write_DOS;
 		entry->data = acpi_driver_data(device);
 		entry->owner = THIS_MODULE;
 	}
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index f12898d..e99471d 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -8,6 +8,7 @@
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
+obj-$(CONFIG_SMP)	+= topology.o
 
 ifeq ($(CONFIG_DEBUG_DRIVER),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/base/base.h b/drivers/base/base.h
index e3b548d..5735b38 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -19,6 +19,10 @@
 extern void driver_detach(struct device_driver * drv);
 extern int driver_probe_device(struct device_driver *, struct device *);
 
+extern void sysdev_shutdown(void);
+extern int sysdev_suspend(pm_message_t state);
+extern int sysdev_resume(void);
+
 static inline struct class_device *to_class_dev(struct kobject *obj)
 {
 	return container_of(obj, struct class_device, kobj);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 29f6af5..c314156 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -133,6 +133,8 @@
 decl_subsys(bus, &ktype_bus, NULL);
 
 
+#ifdef CONFIG_HOTPLUG
+
 /* Manually detach a device from its associated driver. */
 static int driver_helper(struct device *dev, void *data)
 {
@@ -193,6 +195,7 @@
 }
 static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
 
+#endif
 
 static struct device * next_device(struct klist_iter * i)
 {
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index d1a0522..105a0d6 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -303,7 +303,7 @@
  */
 #ifdef CONFIG_ARCH_MEMORY_PROBE
 static ssize_t
-memory_probe_store(struct class *class, const char __user *buf, size_t count)
+memory_probe_store(struct class *class, const char *buf, size_t count)
 {
 	u64 phys_addr;
 	int ret;
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index 0a7aa07..317edbf 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -9,10 +9,9 @@
  */
 
 #include <linux/device.h>
+#include "../base.h"
 #include "power.h"
 
-extern int sysdev_resume(void);
-
 
 /**
  *	resume_device - Restore state for one device.
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index c2475f3..8826a5b 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -12,6 +12,7 @@
 #include <linux/device.h>
 #include <asm/semaphore.h>
 
+#include "../base.h"
 #include "power.h"
 
 #define to_dev(node) container_of(node, struct device, kobj.entry)
@@ -28,7 +29,6 @@
  * they only get one called once when interrupts are disabled.
  */
 
-extern int sysdev_shutdown(void);
 
 /**
  * device_shutdown - call ->shutdown() on each device to shutdown.
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 5050176..8660779 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -9,10 +9,9 @@
  */
 
 #include <linux/device.h>
+#include "../base.h"
 #include "power.h"
 
-extern int sysdev_suspend(pm_message_t state);
-
 /*
  * The entries in the dpm_active list are in a depth first order, simply
  * because children are guaranteed to be discovered after parents, and
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index f3a0c56..40d7242 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -27,22 +27,30 @@
 
 static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
 {
-	return sprintf(buf, "%u\n", dev->power.power_state.event);
+	if (dev->power.power_state.event)
+		return sprintf(buf, "2\n");
+	else
+		return sprintf(buf, "0\n");
 }
 
 static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
 {
 	pm_message_t state;
-	char * rest;
-	int error = 0;
+	int error = -EINVAL;
 
-	state.event = simple_strtoul(buf, &rest, 10);
-	if (*rest)
-		return -EINVAL;
-	if (state.event)
+	state.event = PM_EVENT_SUSPEND;
+	/* Older apps expected to write "3" here - confused with PCI D3 */
+	if ((n == 1) && !strcmp(buf, "3"))
 		error = dpm_runtime_suspend(dev, state);
-	else
+
+	if ((n == 1) && !strcmp(buf, "2"))
+		error = dpm_runtime_suspend(dev, state);
+
+	if ((n == 1) && !strcmp(buf, "0")) {
 		dpm_runtime_resume(dev);
+		error = 0;
+	}
+
 	return error ? error : n;
 }
 
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 66ed8f2..6fc23ab 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -21,8 +21,11 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/pm.h>
+#include <linux/device.h>
 #include <asm/semaphore.h>
 
+#include "base.h"
+
 extern struct subsystem devices_subsys;
 
 #define to_sysdev(k) container_of(k, struct sys_device, kobj)
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
new file mode 100644
index 0000000..915810f
--- /dev/null
+++ b/drivers/base/topology.c
@@ -0,0 +1,148 @@
+/*
+ * driver/base/topology.c - Populate sysfs with cpu topology information
+ *
+ * Written by: Zhang Yanmin, Intel Corporation
+ *
+ * Copyright (C) 2006, Intel Corp.
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/topology.h>
+
+#define define_one_ro(_name) 		\
+static SYSDEV_ATTR(_name, 0444, show_##_name, NULL)
+
+#define define_id_show_func(name)				\
+static ssize_t show_##name(struct sys_device *dev, char *buf)	\
+{								\
+	unsigned int cpu = dev->id;				\
+	return sprintf(buf, "%d\n", topology_##name(cpu));	\
+}
+
+#define define_siblings_show_func(name)					\
+static ssize_t show_##name(struct sys_device *dev, char *buf)		\
+{									\
+	ssize_t len = -1;						\
+	unsigned int cpu = dev->id;					\
+	len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu));	\
+	return (len + sprintf(buf + len, "\n"));			\
+}
+
+#ifdef	topology_physical_package_id
+define_id_show_func(physical_package_id);
+define_one_ro(physical_package_id);
+#define ref_physical_package_id_attr	&attr_physical_package_id.attr,
+#else
+#define ref_physical_package_id_attr
+#endif
+
+#ifdef topology_core_id
+define_id_show_func(core_id);
+define_one_ro(core_id);
+#define ref_core_id_attr		&attr_core_id.attr,
+#else
+#define ref_core_id_attr
+#endif
+
+#ifdef topology_thread_siblings
+define_siblings_show_func(thread_siblings);
+define_one_ro(thread_siblings);
+#define ref_thread_siblings_attr	&attr_thread_siblings.attr,
+#else
+#define ref_thread_siblings_attr
+#endif
+
+#ifdef topology_core_siblings
+define_siblings_show_func(core_siblings);
+define_one_ro(core_siblings);
+#define ref_core_siblings_attr		&attr_core_siblings.attr,
+#else
+#define ref_core_siblings_attr
+#endif
+
+static struct attribute *default_attrs[] = {
+	ref_physical_package_id_attr
+	ref_core_id_attr
+	ref_thread_siblings_attr
+	ref_core_siblings_attr
+	NULL
+};
+
+static struct attribute_group topology_attr_group = {
+	.attrs = default_attrs,
+	.name = "topology"
+};
+
+/* Add/Remove cpu_topology interface for CPU device */
+static int __cpuinit topology_add_dev(struct sys_device * sys_dev)
+{
+	sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
+	return 0;
+}
+
+static int __cpuinit topology_remove_dev(struct sys_device * sys_dev)
+{
+	sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
+	return 0;
+}
+
+static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
+		unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+	struct sys_device *sys_dev;
+
+	sys_dev = get_cpu_sysdev(cpu);
+	switch (action) {
+	case CPU_ONLINE:
+		topology_add_dev(sys_dev);
+		break;
+	case CPU_DEAD:
+		topology_remove_dev(sys_dev);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block topology_cpu_notifier =
+{
+	.notifier_call = topology_cpu_callback,
+};
+
+static int __cpuinit topology_sysfs_init(void)
+{
+	int i;
+
+	for_each_online_cpu(i) {
+		topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE,
+				(void *)(long)i);
+	}
+
+	register_cpu_notifier(&topology_cpu_notifier);
+
+	return 0;
+}
+
+device_initcall(topology_sysfs_init);
+
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 139cbba..8b13316 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -433,12 +433,12 @@
 	  This controls the maximum number of active concurrent packets. More
 	  concurrent packets can increase write performance, but also require
 	  more memory. Each concurrent packet will require approximately 64Kb
-	  of non-swappable kernel memory, memory which will be allocated at
-	  pktsetup time.
+	  of non-swappable kernel memory, memory which will be allocated when
+	  a disc is opened for writing.
 
 config CDROM_PKTCDVD_WCACHE
-	bool "Enable write caching"
-	depends on CDROM_PKTCDVD
+	bool "Enable write caching (EXPERIMENTAL)"
+	depends on CDROM_PKTCDVD && EXPERIMENTAL
 	help
 	  If enabled, write caching will be set for the CD-R/W device. For now
 	  this option is dangerous unless the CD-RW media is known good, as we
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 12d7b9b..0d65394 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2183,6 +2183,7 @@
 {
 	CommandList_struct *cmd = rq->completion_data;
 	ctlr_info_t *h = hba[cmd->ctlr];
+	unsigned long flags;
 	u64bit temp64;
 	int i, ddir;
 
@@ -2205,10 +2206,10 @@
 	printk("Done with %p\n", rq);
 #endif /* CCISS_DEBUG */ 
 
-	spin_lock_irq(&h->lock);
+	spin_lock_irqsave(&h->lock, flags);
 	end_that_request_last(rq, rq->errors);
 	cmd_free(h, cmd,1);
-	spin_unlock_irq(&h->lock);
+	spin_unlock_irqrestore(&h->lock, flags);
 }
 
 /* checks the status of the job and calls complete buffers to mark all 
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 93affee..4e7dbcc 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -43,8 +43,6 @@
  *
  *************************************************************************/
 
-#define VERSION_CODE	"v0.2.0a 2004-07-14 Jens Axboe (axboe@suse.de) and petero2@telia.com"
-
 #include <linux/pktcdvd.h>
 #include <linux/config.h>
 #include <linux/module.h>
@@ -131,7 +129,7 @@
 /*
  * Allocate a packet_data struct
  */
-static struct packet_data *pkt_alloc_packet_data(void)
+static struct packet_data *pkt_alloc_packet_data(int frames)
 {
 	int i;
 	struct packet_data *pkt;
@@ -140,11 +138,12 @@
 	if (!pkt)
 		goto no_pkt;
 
-	pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE);
+	pkt->frames = frames;
+	pkt->w_bio = pkt_bio_alloc(frames);
 	if (!pkt->w_bio)
 		goto no_bio;
 
-	for (i = 0; i < PAGES_PER_PACKET; i++) {
+	for (i = 0; i < frames / FRAMES_PER_PAGE; i++) {
 		pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO);
 		if (!pkt->pages[i])
 			goto no_page;
@@ -152,7 +151,7 @@
 
 	spin_lock_init(&pkt->lock);
 
-	for (i = 0; i < PACKET_MAX_SIZE; i++) {
+	for (i = 0; i < frames; i++) {
 		struct bio *bio = pkt_bio_alloc(1);
 		if (!bio)
 			goto no_rd_bio;
@@ -162,14 +161,14 @@
 	return pkt;
 
 no_rd_bio:
-	for (i = 0; i < PACKET_MAX_SIZE; i++) {
+	for (i = 0; i < frames; i++) {
 		struct bio *bio = pkt->r_bios[i];
 		if (bio)
 			bio_put(bio);
 	}
 
 no_page:
-	for (i = 0; i < PAGES_PER_PACKET; i++)
+	for (i = 0; i < frames / FRAMES_PER_PAGE; i++)
 		if (pkt->pages[i])
 			__free_page(pkt->pages[i]);
 	bio_put(pkt->w_bio);
@@ -186,12 +185,12 @@
 {
 	int i;
 
-	for (i = 0; i < PACKET_MAX_SIZE; i++) {
+	for (i = 0; i < pkt->frames; i++) {
 		struct bio *bio = pkt->r_bios[i];
 		if (bio)
 			bio_put(bio);
 	}
-	for (i = 0; i < PAGES_PER_PACKET; i++)
+	for (i = 0; i < pkt->frames / FRAMES_PER_PAGE; i++)
 		__free_page(pkt->pages[i]);
 	bio_put(pkt->w_bio);
 	kfree(pkt);
@@ -206,17 +205,17 @@
 	list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) {
 		pkt_free_packet_data(pkt);
 	}
+	INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
 }
 
 static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
 {
 	struct packet_data *pkt;
 
-	INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
-	INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
-	spin_lock_init(&pd->cdrw.active_list_lock);
+	BUG_ON(!list_empty(&pd->cdrw.pkt_free_list));
+
 	while (nr_packets > 0) {
-		pkt = pkt_alloc_packet_data();
+		pkt = pkt_alloc_packet_data(pd->settings.size >> 2);
 		if (!pkt) {
 			pkt_shrink_pktlist(pd);
 			return 0;
@@ -951,7 +950,7 @@
 
 	pd->current_sector = zone + pd->settings.size;
 	pkt->sector = zone;
-	pkt->frames = pd->settings.size >> 2;
+	BUG_ON(pkt->frames != pd->settings.size >> 2);
 	pkt->write_size = 0;
 
 	/*
@@ -1639,7 +1638,7 @@
 	pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2;
 	if (pd->settings.size == 0) {
 		printk("pktcdvd: detected zero packet size!\n");
-		pd->settings.size = 128;
+		return -ENXIO;
 	}
 	if (pd->settings.size > PACKET_MAX_SECTORS) {
 		printk("pktcdvd: packet size is too big\n");
@@ -1987,8 +1986,14 @@
 	if ((ret = pkt_set_segment_merging(pd, q)))
 		goto out_unclaim;
 
-	if (write)
+	if (write) {
+		if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
+			printk("pktcdvd: not enough memory for buffers\n");
+			ret = -ENOMEM;
+			goto out_unclaim;
+		}
 		printk("pktcdvd: %lukB available on disc\n", lba << 1);
+	}
 
 	return 0;
 
@@ -2014,6 +2019,8 @@
 	pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
 	bd_release(pd->bdev);
 	blkdev_put(pd->bdev);
+
+	pkt_shrink_pktlist(pd);
 }
 
 static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor)
@@ -2379,12 +2386,6 @@
 	/* This is safe, since we have a reference from open(). */
 	__module_get(THIS_MODULE);
 
-	if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
-		printk("pktcdvd: not enough memory for buffers\n");
-		ret = -ENOMEM;
-		goto out_mem;
-	}
-
 	pd->bdev = bdev;
 	set_blocksize(bdev, CD_FRAMESIZE);
 
@@ -2395,7 +2396,7 @@
 	if (IS_ERR(pd->cdrw.thread)) {
 		printk("pktcdvd: can't start kernel thread\n");
 		ret = -ENOMEM;
-		goto out_thread;
+		goto out_mem;
 	}
 
 	proc = create_proc_entry(pd->name, 0, pkt_proc);
@@ -2406,8 +2407,6 @@
 	DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
 	return 0;
 
-out_thread:
-	pkt_shrink_pktlist(pd);
 out_mem:
 	blkdev_put(bdev);
 	/* This is safe: open() is still holding a reference. */
@@ -2503,6 +2502,10 @@
 		goto out_mem;
 	pd->disk = disk;
 
+	INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
+	INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
+	spin_lock_init(&pd->cdrw.active_list_lock);
+
 	spin_lock_init(&pd->lock);
 	spin_lock_init(&pd->iosched.lock);
 	sprintf(pd->name, "pktcdvd%d", idx);
@@ -2567,8 +2570,6 @@
 
 	blkdev_put(pd->bdev);
 
-	pkt_shrink_pktlist(pd);
-
 	remove_proc_entry(pd->name, pkt_proc);
 	DPRINTK("pktcdvd: writer %s unmapped\n", pd->name);
 
@@ -2678,7 +2679,6 @@
 
 	pkt_proc = proc_mkdir("pktcdvd", proc_root_driver);
 
-	DPRINTK("pktcdvd: %s\n", VERSION_CODE);
 	return 0;
 
 out:
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index a05fe58..f04d864 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -14,7 +14,6 @@
  *  -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
  *  -- verify the 13 conditions and do bulk resets
  *  -- kill last_pipe and simply do two-state clearing on both pipes
- *  -- verify protocol (bulk) from USB descriptors (maybe...)
  *  -- highmem
  *  -- move top_sense and work_bcs into separate allocations (if they survive)
  *     for cache purists and esoteric architectures.
@@ -355,7 +354,7 @@
  * The USB device instance.
  */
 struct ub_dev {
-	spinlock_t lock;
+	spinlock_t *lock;
 	atomic_t poison;		/* The USB device is disconnected */
 	int openc;			/* protected by ub_lock! */
 					/* kref is too implicit for our taste */
@@ -420,11 +419,13 @@
 static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
     int stalled_pipe);
 static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
-static void ub_reset_enter(struct ub_dev *sc);
+static void ub_reset_enter(struct ub_dev *sc, int try);
 static void ub_reset_task(void *arg);
 static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
 static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_capacity *ret);
+static int ub_sync_reset(struct ub_dev *sc);
+static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe);
 static int ub_probe_lun(struct ub_dev *sc, int lnum);
 
 /*
@@ -452,6 +453,10 @@
 #define UB_MAX_HOSTS  26
 static char ub_hostv[UB_MAX_HOSTS];
 
+#define UB_QLOCK_NUM 5
+static spinlock_t ub_qlockv[UB_QLOCK_NUM];
+static int ub_qlock_next = 0;
+
 static DEFINE_SPINLOCK(ub_lock);	/* Locks globals and ->openc */
 
 /*
@@ -531,7 +536,7 @@
 		return 0;
 
 	cnt = 0;
-	spin_lock_irqsave(&sc->lock, flags);
+	spin_lock_irqsave(sc->lock, flags);
 
 	cnt += sprintf(page + cnt,
 	    "poison %d reset %d\n",
@@ -579,7 +584,7 @@
 		if (++nc == SCMD_TRACE_SZ) nc = 0;
 	}
 
-	spin_unlock_irqrestore(&sc->lock, flags);
+	spin_unlock_irqrestore(sc->lock, flags);
 	return cnt;
 }
 
@@ -627,6 +632,24 @@
 }
 
 /*
+ * This is necessitated by the fact that blk_cleanup_queue does not
+ * necesserily destroy the queue. Instead, it may merely decrease q->refcnt.
+ * Since our blk_init_queue() passes a spinlock common with ub_dev,
+ * we have life time issues when ub_cleanup frees ub_dev.
+ */
+static spinlock_t *ub_next_lock(void)
+{
+	unsigned long flags;
+	spinlock_t *ret;
+
+	spin_lock_irqsave(&ub_lock, flags);
+	ret = &ub_qlockv[ub_qlock_next];
+	ub_qlock_next = (ub_qlock_next + 1) % UB_QLOCK_NUM;
+	spin_unlock_irqrestore(&ub_lock, flags);
+	return ret;
+}
+
+/*
  * Downcount for deallocation. This rides on two assumptions:
  *  - once something is poisoned, its refcount cannot grow
  *  - opens cannot happen at this time (del_gendisk was done)
@@ -961,7 +984,7 @@
 	if (atomic_read(&sc->poison))
 		return -ENXIO;
 
-	ub_reset_enter(sc);
+	ub_reset_enter(sc, urq->current_try);
 
 	if (urq->current_try >= 3)
 		return -EIO;
@@ -997,8 +1020,6 @@
  * No exceptions.
  *
  * Host is assumed locked.
- *
- * XXX We only support Bulk for the moment.
  */
 static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 {
@@ -1083,9 +1104,10 @@
 	struct ub_dev *sc = (struct ub_dev *) arg;
 	unsigned long flags;
 
-	spin_lock_irqsave(&sc->lock, flags);
-	usb_unlink_urb(&sc->work_urb);
-	spin_unlock_irqrestore(&sc->lock, flags);
+	spin_lock_irqsave(sc->lock, flags);
+	if (!ub_is_completed(&sc->work_done))
+		usb_unlink_urb(&sc->work_urb);
+	spin_unlock_irqrestore(sc->lock, flags);
 }
 
 /*
@@ -1108,10 +1130,9 @@
 	struct ub_dev *sc = (struct ub_dev *) _dev;
 	unsigned long flags;
 
-	spin_lock_irqsave(&sc->lock, flags);
-	del_timer(&sc->work_timer);
+	spin_lock_irqsave(sc->lock, flags);
 	ub_scsi_dispatch(sc);
-	spin_unlock_irqrestore(&sc->lock, flags);
+	spin_unlock_irqrestore(sc->lock, flags);
 }
 
 static void ub_scsi_dispatch(struct ub_dev *sc)
@@ -1133,6 +1154,7 @@
 		} else {
 			if (!ub_is_completed(&sc->work_done))
 				break;
+			del_timer(&sc->work_timer);
 			ub_scsi_urb_compl(sc, cmd);
 		}
 	}
@@ -1680,16 +1702,18 @@
 
 /*
  * Reset management
+ * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing.
+ * XXX Make usb_sync_reset asynchronous.
  */
 
-static void ub_reset_enter(struct ub_dev *sc)
+static void ub_reset_enter(struct ub_dev *sc, int try)
 {
 
 	if (sc->reset) {
 		/* This happens often on multi-LUN devices. */
 		return;
 	}
-	sc->reset = 1;
+	sc->reset = try + 1;
 
 #if 0 /* Not needed because the disconnect waits for us. */
 	unsigned long flags;
@@ -1727,6 +1751,11 @@
 	if (atomic_read(&sc->poison)) {
 		printk(KERN_NOTICE "%s: Not resetting disconnected device\n",
 		    sc->name); /* P3 This floods. Remove soon. XXX */
+	} else if ((sc->reset & 1) == 0) {
+		ub_sync_reset(sc);
+		msleep(700);	/* usb-storage sleeps 6s (!) */
+		ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
+		ub_probe_clear_stall(sc, sc->send_bulk_pipe);
 	} else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
 		printk(KERN_NOTICE "%s: Not resetting multi-interface device\n",
 		    sc->name); /* P3 This floods. Remove soon. XXX */
@@ -1754,7 +1783,7 @@
 	 * queues of resets or anything. We do need a spinlock though,
 	 * to interact with block layer.
 	 */
-	spin_lock_irqsave(&sc->lock, flags);
+	spin_lock_irqsave(sc->lock, flags);
 	sc->reset = 0;
 	tasklet_schedule(&sc->tasklet);
 	list_for_each(p, &sc->luns) {
@@ -1762,7 +1791,7 @@
 		blk_start_queue(lun->disk->queue);
 	}
 	wake_up(&sc->reset_wait);
-	spin_unlock_irqrestore(&sc->lock, flags);
+	spin_unlock_irqrestore(sc->lock, flags);
 }
 
 /*
@@ -1990,11 +2019,11 @@
 	cmd->done = ub_probe_done;
 	cmd->back = &compl;
 
-	spin_lock_irqsave(&sc->lock, flags);
+	spin_lock_irqsave(sc->lock, flags);
 	cmd->tag = sc->tagcnt++;
 
 	rc = ub_submit_scsi(sc, cmd);
-	spin_unlock_irqrestore(&sc->lock, flags);
+	spin_unlock_irqrestore(sc->lock, flags);
 
 	if (rc != 0) {
 		printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */
@@ -2052,11 +2081,11 @@
 	cmd->done = ub_probe_done;
 	cmd->back = &compl;
 
-	spin_lock_irqsave(&sc->lock, flags);
+	spin_lock_irqsave(sc->lock, flags);
 	cmd->tag = sc->tagcnt++;
 
 	rc = ub_submit_scsi(sc, cmd);
-	spin_unlock_irqrestore(&sc->lock, flags);
+	spin_unlock_irqrestore(sc->lock, flags);
 
 	if (rc != 0) {
 		printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */
@@ -2118,6 +2147,52 @@
 }
 
 /*
+ * Reset with a Bulk reset.
+ */
+static int ub_sync_reset(struct ub_dev *sc)
+{
+	int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber;
+	struct usb_ctrlrequest *cr;
+	struct completion compl;
+	struct timer_list timer;
+	int rc;
+
+	init_completion(&compl);
+
+	cr = &sc->work_cr;
+	cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+	cr->bRequest = US_BULK_RESET_REQUEST;
+	cr->wValue = cpu_to_le16(0);
+	cr->wIndex = cpu_to_le16(ifnum);
+	cr->wLength = cpu_to_le16(0);
+
+	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
+	sc->work_urb.actual_length = 0;
+	sc->work_urb.error_count = 0;
+	sc->work_urb.status = 0;
+
+	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+		printk(KERN_WARNING
+		     "%s: Unable to submit a bulk reset (%d)\n", sc->name, rc);
+		return rc;
+	}
+
+	init_timer(&timer);
+	timer.function = ub_probe_timeout;
+	timer.data = (unsigned long) &compl;
+	timer.expires = jiffies + UB_CTRL_TIMEOUT;
+	add_timer(&timer);
+
+	wait_for_completion(&compl);
+
+	del_timer_sync(&timer);
+	usb_kill_urb(&sc->work_urb);
+
+	return sc->work_urb.status;
+}
+
+/*
  * Get number of LUNs by the way of Bulk GetMaxLUN command.
  */
 static int ub_sync_getmaxlun(struct ub_dev *sc)
@@ -2333,7 +2408,7 @@
 	if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
 		goto err_core;
 	memset(sc, 0, sizeof(struct ub_dev));
-	spin_lock_init(&sc->lock);
+	sc->lock = ub_next_lock();
 	INIT_LIST_HEAD(&sc->luns);
 	usb_init_urb(&sc->work_urb);
 	tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
@@ -2483,7 +2558,7 @@
 	disk->driverfs_dev = &sc->intf->dev;
 
 	rc = -ENOMEM;
-	if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL)
+	if ((q = blk_init_queue(ub_request_fn, sc->lock)) == NULL)
 		goto err_blkqinit;
 
 	disk->queue = q;
@@ -2554,7 +2629,7 @@
 	 * and the whole queue drains. So, we just use this code to
 	 * print warnings.
 	 */
-	spin_lock_irqsave(&sc->lock, flags);
+	spin_lock_irqsave(sc->lock, flags);
 	{
 		struct ub_scsi_cmd *cmd;
 		int cnt = 0;
@@ -2571,7 +2646,7 @@
 			    "%d was queued after shutdown\n", sc->name, cnt);
 		}
 	}
-	spin_unlock_irqrestore(&sc->lock, flags);
+	spin_unlock_irqrestore(sc->lock, flags);
 
 	/*
 	 * Unregister the upper layer.
@@ -2590,19 +2665,15 @@
 	}
 
 	/*
-	 * Taking a lock on a structure which is about to be freed
-	 * is very nonsensual. Here it is largely a way to do a debug freeze,
-	 * and a bracket which shows where the nonsensual code segment ends.
-	 *
 	 * Testing for -EINPROGRESS is always a bug, so we are bending
 	 * the rules a little.
 	 */
-	spin_lock_irqsave(&sc->lock, flags);
+	spin_lock_irqsave(sc->lock, flags);
 	if (sc->work_urb.status == -EINPROGRESS) {	/* janitors: ignore */
 		printk(KERN_WARNING "%s: "
 		    "URB is active after disconnect\n", sc->name);
 	}
-	spin_unlock_irqrestore(&sc->lock, flags);
+	spin_unlock_irqrestore(sc->lock, flags);
 
 	/*
 	 * There is virtually no chance that other CPU runs times so long
@@ -2636,6 +2707,10 @@
 static int __init ub_init(void)
 {
 	int rc;
+	int i;
+
+	for (i = 0; i < UB_QLOCK_NUM; i++)
+		spin_lock_init(&ub_qlockv[i]);
 
 	if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
 		goto err_regblkdev;
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index a3614e6..4ada126 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -882,7 +882,7 @@
 	       card->card_number, dev->bus->number, dev->devfn);
 
 	if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) &&
-	    !pci_set_dma_mask(dev, 0xffffffffLL)) {
+	    pci_set_dma_mask(dev, 0xffffffffLL)) {
 		printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards);
 		return  -ENOMEM;
 	}
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index e522d19..7e21b1f 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -474,18 +474,6 @@
 /* ======================== Card services HCI interaction ======================== */
 
 
-static struct device *bt3c_device(void)
-{
-	static struct device dev = {
-		.bus_id = "pcmcia",
-	};
-	kobject_set_name(&dev.kobj, "bt3c");
-	kobject_init(&dev.kobj);
-
-	return &dev;
-}
-
-
 static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int count)
 {
 	char *ptr = (char *) firmware;
@@ -574,6 +562,7 @@
 {
 	const struct firmware *firmware;
 	struct hci_dev *hdev;
+	client_handle_t handle;
 	int err;
 
 	spin_lock_init(&(info->lock));
@@ -605,8 +594,10 @@
 
 	hdev->owner = THIS_MODULE;
 
+	handle = info->link.handle;
+
 	/* Load firmware */
-	err = request_firmware(&firmware, "BT3CPCC.bin", bt3c_device());
+	err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle));
 	if (err < 0) {
 		BT_ERR("Firmware request failed");
 		goto error;
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 193446e..e276172 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -42,8 +42,6 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
-#include <asm/bug.h>
-
 #include <asm/vio.h>
 #include <asm/scatterlist.h>
 #include <asm/iseries/hv_types.h>
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 4135d8c..05ba410 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -222,7 +222,7 @@
 
 config SYNCLINK_GT
 	tristate "SyncLink GT/AC support"
-	depends on SERIAL_NONSTANDARD
+	depends on SERIAL_NONSTANDARD && PCI
 	help
 	  Support for SyncLink GT and SyncLink AC families of
 	  synchronous and asynchronous serial adapters
@@ -992,7 +992,7 @@
 
 config HANGCHECK_TIMER
 	tristate "Hangcheck timer"
-	depends on X86 || IA64 || PPC64 || S390
+	depends on X86 || IA64 || PPC64
 	help
 	  The hangcheck-timer module detects when the system has gone
 	  out to lunch past a certain margin.  It can reboot the system
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 810679d..9964c50 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -600,6 +600,26 @@
 	agp_put_bridge(bridge);
 }
 
+#ifdef CONFIG_PM
+
+static int agp_amd64_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+static int agp_amd64_resume(struct pci_dev *pdev)
+{
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	return amd_8151_configure();
+}
+
+#endif /* CONFIG_PM */
+
 static struct pci_device_id agp_amd64_pci_table[] = {
 	{
 	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
@@ -718,6 +738,10 @@
 	.id_table	= agp_amd64_pci_table,
 	.probe		= agp_amd64_probe,
 	.remove		= agp_amd64_remove,
+#ifdef CONFIG_PM
+	.suspend	= agp_amd64_suspend,
+	.resume		= agp_amd64_resume,
+#endif
 };
 
 
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 53372a8..5b74c36 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -244,6 +244,22 @@
 }
 
 
+#ifdef CONFIG_PM
+static int agp_ati_resume(struct pci_dev *dev)
+{
+	pci_restore_state(dev);
+
+	return ati_configure();
+}
+
+static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state)
+{
+	pci_save_state(dev);
+
+	return 0;
+}
+#endif
+
 /*
  *Since we don't need contigious memory we just try
  * to get the gatt table once
@@ -525,6 +541,10 @@
 	.id_table	= agp_ati_pci_table,
 	.probe		= agp_ati_probe,
 	.remove		= agp_ati_remove,
+#ifdef CONFIG_PM
+	.resume		= agp_ati_resume,
+	.suspend	= agp_ati_suspend,
+#endif
 };
 
 static int __init agp_ati_init(void)
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 17f520c..97eeb23 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -592,7 +592,7 @@
 	struct agp_file_private *priv = file->private_data;
 	struct agp_kern_info kerninfo;
 
-	down(&(agp_fe.agp_mutex));
+	mutex_lock(&(agp_fe.agp_mutex));
 
 	if (agp_fe.backend_acquired != TRUE)
 		goto out_eperm;
@@ -627,7 +627,7 @@
 					    size, vma->vm_page_prot)) {
 			goto out_again;
 		}
-		up(&(agp_fe.agp_mutex));
+		mutex_unlock(&(agp_fe.agp_mutex));
 		return 0;
 	}
 
@@ -643,20 +643,20 @@
 					    size, vma->vm_page_prot)) {
 			goto out_again;
 		}
-		up(&(agp_fe.agp_mutex));
+		mutex_unlock(&(agp_fe.agp_mutex));
 		return 0;
 	}
 
 out_eperm:
-	up(&(agp_fe.agp_mutex));
+	mutex_unlock(&(agp_fe.agp_mutex));
 	return -EPERM;
 
 out_inval:
-	up(&(agp_fe.agp_mutex));
+	mutex_unlock(&(agp_fe.agp_mutex));
 	return -EINVAL;
 
 out_again:
-	up(&(agp_fe.agp_mutex));
+	mutex_unlock(&(agp_fe.agp_mutex));
 	return -EAGAIN;
 }
 
@@ -664,7 +664,7 @@
 {
 	struct agp_file_private *priv = file->private_data;
 
-	down(&(agp_fe.agp_mutex));
+	mutex_lock(&(agp_fe.agp_mutex));
 
 	DBG("priv=%p", priv);
 
@@ -687,7 +687,7 @@
 	agp_remove_file_private(priv);
 	kfree(priv);
 	file->private_data = NULL;
-	up(&(agp_fe.agp_mutex));
+	mutex_unlock(&(agp_fe.agp_mutex));
 	return 0;
 }
 
@@ -698,7 +698,7 @@
 	struct agp_client *client;
 	int rc = -ENXIO;
 
-	down(&(agp_fe.agp_mutex));
+	mutex_lock(&(agp_fe.agp_mutex));
 
 	if (minor != AGPGART_MINOR)
 		goto err_out;
@@ -723,13 +723,13 @@
 	file->private_data = (void *) priv;
 	agp_insert_file_private(priv);
 	DBG("private=%p, client=%p", priv, client);
-	up(&(agp_fe.agp_mutex));
+	mutex_unlock(&(agp_fe.agp_mutex));
 	return 0;
 
 err_out_nomem:
 	rc = -ENOMEM;
 err_out:
-	up(&(agp_fe.agp_mutex));
+	mutex_unlock(&(agp_fe.agp_mutex));
 	return rc;
 }
 
@@ -985,7 +985,7 @@
 	int ret_val = -ENOTTY;
 
 	DBG("priv=%p, cmd=%x", curr_priv, cmd);
-	down(&(agp_fe.agp_mutex));
+	mutex_lock(&(agp_fe.agp_mutex));
 
 	if ((agp_fe.current_controller == NULL) &&
 	    (cmd != AGPIOC_ACQUIRE)) {
@@ -1055,7 +1055,7 @@
 
 ioctl_out:
 	DBG("ioctl returns %d\n", ret_val);
-	up(&(agp_fe.agp_mutex));
+	mutex_unlock(&(agp_fe.agp_mutex));
 	return ret_val;
 }
 
@@ -1081,7 +1081,7 @@
 int agp_frontend_initialize(void)
 {
 	memset(&agp_fe, 0, sizeof(struct agp_front_data));
-	sema_init(&(agp_fe.agp_mutex), 1);
+	mutex_init(&(agp_fe.agp_mutex));
 
 	if (misc_register(&agp_miscdev)) {
 		printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index e7bed50..631531f 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -422,7 +422,8 @@
 			/* Check it's really I915G */
 			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
 			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB)
 				gtt_entries = MB(48) - KB(size);
 			else
 				gtt_entries = 0;
@@ -431,7 +432,8 @@
 			/* Check it's really I915G */
 			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
 			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB)
 				gtt_entries = MB(64) - KB(size);
 			else
 				gtt_entries = 0;
@@ -1681,6 +1683,14 @@
 		}
 		name = "945G";
 		break;
+	case PCI_DEVICE_ID_INTEL_82945GM_HB:
+		if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG)) {
+			bridge->driver = &intel_915_driver;
+		} else {
+			bridge->driver = &intel_845_driver;
+		}
+		name = "945GM";
+		break;
 	case PCI_DEVICE_ID_INTEL_7505_0:
 		bridge->driver = &intel_7505_driver;
 		name = "E7505";
@@ -1821,6 +1831,7 @@
 	ID(PCI_DEVICE_ID_INTEL_82915G_HB),
 	ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
 	ID(PCI_DEVICE_ID_INTEL_82945G_HB),
+	ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
 	{ }
 };
 
diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c
index 4008324..7c14a09 100644
--- a/drivers/char/agp/isoch.c
+++ b/drivers/char/agp/isoch.c
@@ -218,10 +218,8 @@
 			master[cdev].rq *= (1 << (master[cdev].y - 1));
 
 		tot_rq += master[cdev].rq;
-
-		if (cdev == ndevs-1)
-			master[cdev].n += rem;
 	}
+	master[ndevs-1].n += rem;
 
 	/* Figure the number of isochronous and asynchronous RQ slots the
 	 * target is providing. */
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 39c61a7..cc7acf8 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1233,7 +1233,7 @@
                             }
                              info->idle_stats.recv_idle = jiffies;
                         }
-                        schedule_delayed_work(&tty->buf.work, 1);
+			tty_schedule_flip(tty);
                     }
                     /* end of service */
                     cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
@@ -1606,7 +1606,7 @@
 	    }
 #endif
 	    info->idle_stats.recv_idle = jiffies;
-	    schedule_delayed_work(&tty->buf.work, 1);
+	    tty_schedule_flip(tty);
 	}
 	/* Update rx_get */
 	cy_writel(&buf_ctrl->rx_get, new_rx_get);
@@ -1809,7 +1809,7 @@
 	if(delta_count)
 	    cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
 	if(special_count)
-	    schedule_delayed_work(&tty->buf.work, 1);
+	    tty_schedule_flip(tty);
     }
 }
 
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index 5485382..bd7be09 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -59,17 +59,16 @@
 	int i;
 	DRM_DEBUG("%s\n", __FUNCTION__);
 
-	address = __get_free_pages(GFP_KERNEL, ATI_PCIGART_TABLE_ORDER);
+	address = __get_free_pages(GFP_KERNEL | __GFP_COMP,
+				   ATI_PCIGART_TABLE_ORDER);
 	if (address == 0UL) {
-		return 0;
+		return NULL;
 	}
 
 	page = virt_to_page(address);
 
-	for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
-		get_page(page);
+	for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++)
 		SetPageReserved(page);
-	}
 
 	DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
 	return (void *)address;
@@ -83,10 +82,8 @@
 
 	page = virt_to_page((unsigned long)address);
 
-	for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
-		__put_page(page);
+	for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++)
 		ClearPageReserved(page);
-	}
 
 	free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER);
 }
@@ -127,7 +124,7 @@
 	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN
 	    && gart_info->addr) {
 		drm_ati_free_pcigart_table(gart_info->addr);
-		gart_info->addr = 0;
+		gart_info->addr = NULL;
 	}
 
 	return 1;
@@ -168,7 +165,7 @@
 		if (bus_address == 0) {
 			DRM_ERROR("unable to map PCIGART pages!\n");
 			drm_ati_free_pcigart_table(address);
-			address = 0;
+			address = NULL;
 			goto done;
 		}
 	} else {
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 54b561e..107df9f 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -57,6 +57,7 @@
 #include <linux/smp_lock.h>	/* For (un)lock_kernel */
 #include <linux/mm.h>
 #include <linux/cdev.h>
+#include <linux/mutex.h>
 #if defined(__alpha__) || defined(__powerpc__)
 #include <asm/pgtable.h>	/* For pte_wrprotect */
 #endif
@@ -623,7 +624,7 @@
 	/** \name Locks */
 	/*@{ */
 	spinlock_t count_lock;		/**< For inuse, drm_device::open_count, drm_device::buf_use */
-	struct semaphore struct_sem;	/**< For others */
+	struct mutex struct_mutex;	/**< For others */
 	/*@} */
 
 	/** \name Usage Counters */
@@ -658,7 +659,7 @@
 	/*@{ */
 	drm_ctx_list_t *ctxlist;	/**< Linked list of context handles */
 	int ctx_count;			/**< Number of context handles */
-	struct semaphore ctxlist_sem;	/**< For ctxlist */
+	struct mutex ctxlist_mutex;	/**< For ctxlist */
 
 	drm_map_t **context_sareas;	    /**< per-context SAREA's */
 	int max_context;
@@ -979,7 +980,7 @@
 extern unsigned int drm_debug;
 extern unsigned int drm_cards_limit;
 extern drm_head_t **drm_heads;
-extern struct drm_sysfs_class *drm_class;
+extern struct class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
 
 				/* Proc support (drm_proc.h) */
@@ -1010,11 +1011,9 @@
 extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
 
 			       /* sysfs support (drm_sysfs.c) */
-struct drm_sysfs_class;
-extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner,
-						char *name);
-extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);
-extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
+extern struct class *drm_sysfs_create(struct module *owner, char *name);
+extern void drm_sysfs_destroy(struct class *cs);
+extern struct class_device *drm_sysfs_device_add(struct class *cs,
 						 drm_head_t *head);
 extern void drm_sysfs_device_remove(struct class_device *class_dev);
 
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index a47b502..2a37586 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -56,7 +56,7 @@
  * \param magic magic number.
  *
  * Searches in drm_device::magiclist within all files with the same hash key
- * the one with matching magic number, while holding the drm_device::struct_sem
+ * the one with matching magic number, while holding the drm_device::struct_mutex
  * lock.
  */
 static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
@@ -65,14 +65,14 @@
 	drm_magic_entry_t *pt;
 	int hash = drm_hash_magic(magic);
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
 		if (pt->magic == magic) {
 			retval = pt->priv;
 			break;
 		}
 	}
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 	return retval;
 }
 
@@ -85,7 +85,7 @@
  *
  * Creates a drm_magic_entry structure and appends to the linked list
  * associated the magic number hash key in drm_device::magiclist, while holding
- * the drm_device::struct_sem lock.
+ * the drm_device::struct_mutex lock.
  */
 static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
 			 drm_magic_t magic)
@@ -104,7 +104,7 @@
 	entry->priv = priv;
 	entry->next = NULL;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	if (dev->magiclist[hash].tail) {
 		dev->magiclist[hash].tail->next = entry;
 		dev->magiclist[hash].tail = entry;
@@ -112,7 +112,7 @@
 		dev->magiclist[hash].head = entry;
 		dev->magiclist[hash].tail = entry;
 	}
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
 }
@@ -124,7 +124,7 @@
  * \param magic magic number.
  *
  * Searches and unlinks the entry in drm_device::magiclist with the magic
- * number hash key, while holding the drm_device::struct_sem lock.
+ * number hash key, while holding the drm_device::struct_mutex lock.
  */
 static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
 {
@@ -135,7 +135,7 @@
 	DRM_DEBUG("%d\n", magic);
 	hash = drm_hash_magic(magic);
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
 		if (pt->magic == magic) {
 			if (dev->magiclist[hash].head == pt) {
@@ -147,11 +147,11 @@
 			if (prev) {
 				prev->next = pt->next;
 			}
-			up(&dev->struct_sem);
+			mutex_unlock(&dev->struct_mutex);
 			return 0;
 		}
 	}
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
 
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 1db12dc..e2637b4 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -255,14 +255,14 @@
 	memset(list, 0, sizeof(*list));
 	list->map = map;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	list_add(&list->head, &dev->maplist->head);
 	/* Assign a 32-bit handle */
-	/* We do it here so that dev->struct_sem protects the increment */
+	/* We do it here so that dev->struct_mutex protects the increment */
 	list->user_token = HandleID(map->type == _DRM_SHM
 				    ? (unsigned long)map->handle
 				    : map->offset, dev);
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	*maplist = list;
 	return 0;
@@ -392,9 +392,9 @@
 {
 	int ret;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	ret = drm_rmmap_locked(dev, map);
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	return ret;
 }
@@ -423,7 +423,7 @@
 		return -EFAULT;
 	}
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	list_for_each(list, &dev->maplist->head) {
 		drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
 
@@ -439,7 +439,7 @@
 	 * find anything.
 	 */
 	if (list == (&dev->maplist->head)) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 
@@ -448,13 +448,13 @@
 
 	/* Register and framebuffer maps are permanent */
 	if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return 0;
 	}
 
 	ret = drm_rmmap_locked(dev, map);
 
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	return ret;
 }
@@ -566,16 +566,16 @@
 	atomic_inc(&dev->buf_alloc);
 	spin_unlock(&dev->count_lock);
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	entry = &dma->bufs[order];
 	if (entry->buf_count) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;	/* May only call once for each order */
 	}
 
 	if (count < 0 || count > 4096) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -EINVAL;
 	}
@@ -583,7 +583,7 @@
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
 				   DRM_MEM_BUFS);
 	if (!entry->buflist) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -616,7 +616,7 @@
 			/* Set count correctly so we free the proper amount. */
 			entry->buf_count = count;
 			drm_cleanup_buf_error(dev, entry);
-			up(&dev->struct_sem);
+			mutex_unlock(&dev->struct_mutex);
 			atomic_dec(&dev->buf_alloc);
 			return -ENOMEM;
 		}
@@ -638,7 +638,7 @@
 	if (!temp_buflist) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -656,7 +656,7 @@
 	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
 	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
 
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	request->count = entry->buf_count;
 	request->size = size;
@@ -722,16 +722,16 @@
 	atomic_inc(&dev->buf_alloc);
 	spin_unlock(&dev->count_lock);
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	entry = &dma->bufs[order];
 	if (entry->buf_count) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;	/* May only call once for each order */
 	}
 
 	if (count < 0 || count > 4096) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -EINVAL;
 	}
@@ -739,7 +739,7 @@
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
 				   DRM_MEM_BUFS);
 	if (!entry->buflist) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -750,7 +750,7 @@
 	if (!entry->seglist) {
 		drm_free(entry->buflist,
 			 count * sizeof(*entry->buflist), DRM_MEM_BUFS);
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -766,7 +766,7 @@
 			 count * sizeof(*entry->buflist), DRM_MEM_BUFS);
 		drm_free(entry->seglist,
 			 count * sizeof(*entry->seglist), DRM_MEM_SEGS);
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -790,7 +790,7 @@
 			drm_free(temp_pagelist,
 				 (dma->page_count + (count << page_order))
 				 * sizeof(*dma->pagelist), DRM_MEM_PAGES);
-			up(&dev->struct_sem);
+			mutex_unlock(&dev->struct_mutex);
 			atomic_dec(&dev->buf_alloc);
 			return -ENOMEM;
 		}
@@ -831,7 +831,7 @@
 					  (count << page_order))
 					 * sizeof(*dma->pagelist),
 					 DRM_MEM_PAGES);
-				up(&dev->struct_sem);
+				mutex_unlock(&dev->struct_mutex);
 				atomic_dec(&dev->buf_alloc);
 				return -ENOMEM;
 			}
@@ -853,7 +853,7 @@
 		drm_free(temp_pagelist,
 			 (dma->page_count + (count << page_order))
 			 * sizeof(*dma->pagelist), DRM_MEM_PAGES);
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -878,7 +878,7 @@
 	dma->page_count += entry->seg_count << page_order;
 	dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
 
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	request->count = entry->buf_count;
 	request->size = size;
@@ -948,16 +948,16 @@
 	atomic_inc(&dev->buf_alloc);
 	spin_unlock(&dev->count_lock);
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	entry = &dma->bufs[order];
 	if (entry->buf_count) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;	/* May only call once for each order */
 	}
 
 	if (count < 0 || count > 4096) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -EINVAL;
 	}
@@ -965,7 +965,7 @@
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
 				   DRM_MEM_BUFS);
 	if (!entry->buflist) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -999,7 +999,7 @@
 			/* Set count correctly so we free the proper amount. */
 			entry->buf_count = count;
 			drm_cleanup_buf_error(dev, entry);
-			up(&dev->struct_sem);
+			mutex_unlock(&dev->struct_mutex);
 			atomic_dec(&dev->buf_alloc);
 			return -ENOMEM;
 		}
@@ -1022,7 +1022,7 @@
 	if (!temp_buflist) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -1040,7 +1040,7 @@
 	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
 	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
 
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	request->count = entry->buf_count;
 	request->size = size;
@@ -1110,16 +1110,16 @@
 	atomic_inc(&dev->buf_alloc);
 	spin_unlock(&dev->count_lock);
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	entry = &dma->bufs[order];
 	if (entry->buf_count) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;	/* May only call once for each order */
 	}
 
 	if (count < 0 || count > 4096) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -EINVAL;
 	}
@@ -1127,7 +1127,7 @@
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
 				   DRM_MEM_BUFS);
 	if (!entry->buflist) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -1160,7 +1160,7 @@
 			/* Set count correctly so we free the proper amount. */
 			entry->buf_count = count;
 			drm_cleanup_buf_error(dev, entry);
-			up(&dev->struct_sem);
+			mutex_unlock(&dev->struct_mutex);
 			atomic_dec(&dev->buf_alloc);
 			return -ENOMEM;
 		}
@@ -1182,7 +1182,7 @@
 	if (!temp_buflist) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
 	}
@@ -1200,7 +1200,7 @@
 	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
 	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
 
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	request->count = entry->buf_count;
 	request->size = size;
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index f842545..83094c7 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -53,7 +53,7 @@
  * \param ctx_handle context handle.
  *
  * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::context_sareas, while holding the drm_device::struct_sem
+ * in drm_device::context_sareas, while holding the drm_device::struct_mutex
  * lock.
  */
 void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
@@ -64,10 +64,10 @@
 		goto failed;
 
 	if (ctx_handle < DRM_MAX_CTXBITMAP) {
-		down(&dev->struct_sem);
+		mutex_lock(&dev->struct_mutex);
 		clear_bit(ctx_handle, dev->ctx_bitmap);
 		dev->context_sareas[ctx_handle] = NULL;
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return;
 	}
       failed:
@@ -83,7 +83,7 @@
  *
  * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
  * drm_device::context_sareas to accommodate the new entry while holding the
- * drm_device::struct_sem lock.
+ * drm_device::struct_mutex lock.
  */
 static int drm_ctxbitmap_next(drm_device_t * dev)
 {
@@ -92,7 +92,7 @@
 	if (!dev->ctx_bitmap)
 		return -1;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
 	if (bit < DRM_MAX_CTXBITMAP) {
 		set_bit(bit, dev->ctx_bitmap);
@@ -113,7 +113,7 @@
 							 DRM_MEM_MAPS);
 				if (!ctx_sareas) {
 					clear_bit(bit, dev->ctx_bitmap);
-					up(&dev->struct_sem);
+					mutex_unlock(&dev->struct_mutex);
 					return -1;
 				}
 				dev->context_sareas = ctx_sareas;
@@ -126,16 +126,16 @@
 					      DRM_MEM_MAPS);
 				if (!dev->context_sareas) {
 					clear_bit(bit, dev->ctx_bitmap);
-					up(&dev->struct_sem);
+					mutex_unlock(&dev->struct_mutex);
 					return -1;
 				}
 				dev->context_sareas[bit] = NULL;
 			}
 		}
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return bit;
 	}
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 	return -1;
 }
 
@@ -145,24 +145,24 @@
  * \param dev DRM device.
  *
  * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_sem lock.
+ * the drm_device::struct_mutex lock.
  */
 int drm_ctxbitmap_init(drm_device_t * dev)
 {
 	int i;
 	int temp;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
 						     DRM_MEM_CTXBITMAP);
 	if (dev->ctx_bitmap == NULL) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return -ENOMEM;
 	}
 	memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
 	dev->context_sareas = NULL;
 	dev->max_context = -1;
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
 		temp = drm_ctxbitmap_next(dev);
@@ -178,17 +178,17 @@
  * \param dev DRM device.
  *
  * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_sem lock.
+ * the drm_device::struct_mutex lock.
  */
 void drm_ctxbitmap_cleanup(drm_device_t * dev)
 {
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	if (dev->context_sareas)
 		drm_free(dev->context_sareas,
 			 sizeof(*dev->context_sareas) *
 			 dev->max_context, DRM_MEM_MAPS);
 	drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP);
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 }
 
 /*@}*/
@@ -222,15 +222,15 @@
 	if (copy_from_user(&request, argp, sizeof(request)))
 		return -EFAULT;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	if (dev->max_context < 0
 	    || request.ctx_id >= (unsigned)dev->max_context) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 
 	map = dev->context_sareas[request.ctx_id];
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	request.handle = NULL;
 	list_for_each_entry(_entry, &dev->maplist->head, head) {
@@ -274,7 +274,7 @@
 			   (drm_ctx_priv_map_t __user *) arg, sizeof(request)))
 		return -EFAULT;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	list_for_each(list, &dev->maplist->head) {
 		r_list = list_entry(list, drm_map_list_t, head);
 		if (r_list->map
@@ -282,7 +282,7 @@
 			goto found;
 	}
       bad:
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 	return -EINVAL;
 
       found:
@@ -294,7 +294,7 @@
 	if (request.ctx_id >= (unsigned)dev->max_context)
 		goto bad;
 	dev->context_sareas[request.ctx_id] = map;
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 	return 0;
 }
 
@@ -448,10 +448,10 @@
 	ctx_entry->handle = ctx.handle;
 	ctx_entry->tag = priv;
 
-	down(&dev->ctxlist_sem);
+	mutex_lock(&dev->ctxlist_mutex);
 	list_add(&ctx_entry->head, &dev->ctxlist->head);
 	++dev->ctx_count;
-	up(&dev->ctxlist_sem);
+	mutex_unlock(&dev->ctxlist_mutex);
 
 	if (copy_to_user(argp, &ctx, sizeof(ctx)))
 		return -EFAULT;
@@ -574,7 +574,7 @@
 		drm_ctxbitmap_free(dev, ctx.handle);
 	}
 
-	down(&dev->ctxlist_sem);
+	mutex_lock(&dev->ctxlist_mutex);
 	if (!list_empty(&dev->ctxlist->head)) {
 		drm_ctx_list_t *pos, *n;
 
@@ -586,7 +586,7 @@
 			}
 		}
 	}
-	up(&dev->ctxlist_sem);
+	mutex_unlock(&dev->ctxlist_mutex);
 
 	return 0;
 }
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index c4fa5a2..dc6bbe8 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -151,7 +151,7 @@
 	if (dev->irq_enabled)
 		drm_irq_uninstall(dev);
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	del_timer(&dev->timer);
 
 	/* Clear pid list */
@@ -231,7 +231,7 @@
 		dev->lock.filp = NULL;
 		wake_up_interruptible(&dev->lock.lock_queue);
 	}
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	DRM_DEBUG("lastclose completed\n");
 	return 0;
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 403f44a..641f763 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -262,7 +262,7 @@
 			goto out_free;
 	}
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	if (!dev->file_last) {
 		priv->next = NULL;
 		priv->prev = NULL;
@@ -276,7 +276,7 @@
 		dev->file_last->next = priv;
 		dev->file_last = priv;
 	}
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 #ifdef __alpha__
 	/*
@@ -413,7 +413,7 @@
 
 	drm_fasync(-1, filp, 0);
 
-	down(&dev->ctxlist_sem);
+	mutex_lock(&dev->ctxlist_mutex);
 	if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
 		drm_ctx_list_t *pos, *n;
 
@@ -432,9 +432,9 @@
 			}
 		}
 	}
-	up(&dev->ctxlist_sem);
+	mutex_unlock(&dev->ctxlist_mutex);
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	if (priv->remove_auth_on_close == 1) {
 		drm_file_t *temp = dev->file_first;
 		while (temp) {
@@ -452,7 +452,7 @@
 	} else {
 		dev->file_last = priv->prev;
 	}
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	if (dev->driver->postclose)
 		dev->driver->postclose(dev, priv);
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index bcd4e60..555f323 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -194,9 +194,9 @@
 		return -EFAULT;
 	idx = map.offset;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	if (idx < 0) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 
@@ -209,7 +209,7 @@
 		i++;
 	}
 	if (!r_list || !r_list->map) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 
@@ -219,7 +219,7 @@
 	map.flags = r_list->map->flags;
 	map.handle = (void *)(unsigned long)r_list->user_token;
 	map.mtrr = r_list->map->mtrr;
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	if (copy_to_user(argp, &map, sizeof(map)))
 		return -EFAULT;
@@ -253,11 +253,11 @@
 	if (copy_from_user(&client, argp, sizeof(client)))
 		return -EFAULT;
 	idx = client.idx;
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ;
 
 	if (!pt) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 	client.auth = pt->authenticated;
@@ -265,7 +265,7 @@
 	client.uid = pt->uid;
 	client.magic = pt->magic;
 	client.iocs = pt->ioctl_count;
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	if (copy_to_user(argp, &client, sizeof(client)))
 		return -EFAULT;
@@ -292,7 +292,7 @@
 
 	memset(&stats, 0, sizeof(stats));
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 
 	for (i = 0; i < dev->counters; i++) {
 		if (dev->types[i] == _DRM_STAT_LOCK)
@@ -305,7 +305,7 @@
 
 	stats.count = dev->counters;
 
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats)))
 		return -EFAULT;
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index b0d4b23..611a117 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -98,20 +98,20 @@
 	if (dev->irq == 0)
 		return -EINVAL;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 
 	/* Driver must have been initialized */
 	if (!dev->dev_private) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 
 	if (dev->irq_enabled) {
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return -EBUSY;
 	}
 	dev->irq_enabled = 1;
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq);
 
@@ -135,9 +135,9 @@
 	ret = request_irq(dev->irq, dev->driver->irq_handler,
 			  sh_flags, dev->devname, dev);
 	if (ret < 0) {
-		down(&dev->struct_sem);
+		mutex_lock(&dev->struct_mutex);
 		dev->irq_enabled = 0;
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 		return ret;
 	}
 
@@ -161,10 +161,10 @@
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	irq_enabled = dev->irq_enabled;
 	dev->irq_enabled = 0;
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 
 	if (!irq_enabled)
 		return -EINVAL;
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 5b1d3a0..2c17e88 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -3,6 +3,7 @@
    Please contact dri-devel@lists.sf.net to add new cards to this list
 */
 #define radeon_PCI_IDS \
+	{0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\
 	{0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \
 	{0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \
 	{0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
@@ -84,7 +85,6 @@
 	{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
 	{0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-	{0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
 	{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
@@ -242,5 +242,6 @@
 	{0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0, 0, 0}
 
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 6f943e3..362a270 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -258,7 +258,7 @@
 }
 
 /**
- * Simply calls _vm_info() while holding the drm_device::struct_sem lock.
+ * Simply calls _vm_info() while holding the drm_device::struct_mutex lock.
  */
 static int drm_vm_info(char *buf, char **start, off_t offset, int request,
 		       int *eof, void *data)
@@ -266,9 +266,9 @@
 	drm_device_t *dev = (drm_device_t *) data;
 	int ret;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	ret = drm__vm_info(buf, start, offset, request, eof, data);
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
 
@@ -331,7 +331,7 @@
 }
 
 /**
- * Simply calls _queues_info() while holding the drm_device::struct_sem lock.
+ * Simply calls _queues_info() while holding the drm_device::struct_mutex lock.
  */
 static int drm_queues_info(char *buf, char **start, off_t offset, int request,
 			   int *eof, void *data)
@@ -339,9 +339,9 @@
 	drm_device_t *dev = (drm_device_t *) data;
 	int ret;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	ret = drm__queues_info(buf, start, offset, request, eof, data);
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
 
@@ -403,7 +403,7 @@
 }
 
 /**
- * Simply calls _bufs_info() while holding the drm_device::struct_sem lock.
+ * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock.
  */
 static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
 			 int *eof, void *data)
@@ -411,9 +411,9 @@
 	drm_device_t *dev = (drm_device_t *) data;
 	int ret;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	ret = drm__bufs_info(buf, start, offset, request, eof, data);
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
 
@@ -459,7 +459,7 @@
 }
 
 /**
- * Simply calls _clients_info() while holding the drm_device::struct_sem lock.
+ * Simply calls _clients_info() while holding the drm_device::struct_mutex lock.
  */
 static int drm_clients_info(char *buf, char **start, off_t offset,
 			    int request, int *eof, void *data)
@@ -467,9 +467,9 @@
 	drm_device_t *dev = (drm_device_t *) data;
 	int ret;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	ret = drm__clients_info(buf, start, offset, request, eof, data);
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
 
@@ -540,9 +540,9 @@
 	drm_device_t *dev = (drm_device_t *) data;
 	int ret;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	ret = drm__vma_info(buf, start, offset, request, eof, data);
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
 #endif
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 42d7663..68073e1 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -50,7 +50,7 @@
 module_param_named(debug, drm_debug, int, 0600);
 
 drm_head_t **drm_heads;
-struct drm_sysfs_class *drm_class;
+struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 
 static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
@@ -61,8 +61,8 @@
 
 	spin_lock_init(&dev->count_lock);
 	init_timer(&dev->timer);
-	sema_init(&dev->struct_sem, 1);
-	sema_init(&dev->ctxlist_sem, 1);
+	mutex_init(&dev->struct_mutex);
+	mutex_init(&dev->ctxlist_mutex);
 
 	dev->pdev = pdev;
 
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 68e43dd..0b9f98a 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -1,3 +1,4 @@
+
 /*
  * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
  *               extra sysfs attribute from DRM. Normal drm_sysfs_class
@@ -19,36 +20,6 @@
 #include "drm_core.h"
 #include "drmP.h"
 
-struct drm_sysfs_class {
-	struct class_device_attribute attr;
-	struct class class;
-};
-#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)
-
-struct simple_dev {
-	dev_t dev;
-	struct class_device class_dev;
-};
-#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
-
-static void release_simple_dev(struct class_device *class_dev)
-{
-	struct simple_dev *s_dev = to_simple_dev(class_dev);
-	kfree(s_dev);
-}
-
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
-	struct simple_dev *s_dev = to_simple_dev(class_dev);
-	return print_dev_t(buf, s_dev->dev);
-}
-
-static void drm_sysfs_class_release(struct class *class)
-{
-	struct drm_sysfs_class *cs = to_drm_sysfs_class(class);
-	kfree(cs);
-}
-
 /* Display the version of drm_core. This doesn't work right in current design */
 static ssize_t version_show(struct class *dev, char *buf)
 {
@@ -69,38 +40,16 @@
  * Note, the pointer created here is to be destroyed when finished by making a
  * call to drm_sysfs_destroy().
  */
-struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
+struct class *drm_sysfs_create(struct module *owner, char *name)
 {
-	struct drm_sysfs_class *cs;
-	int retval;
+	struct class *class;
 
-	cs = kmalloc(sizeof(*cs), GFP_KERNEL);
-	if (!cs) {
-		retval = -ENOMEM;
-		goto error;
-	}
-	memset(cs, 0x00, sizeof(*cs));
+	class = class_create(owner, name);
+	if (!class)
+		return class;
 
-	cs->class.name = name;
-	cs->class.class_release = drm_sysfs_class_release;
-	cs->class.release = release_simple_dev;
-
-	cs->attr.attr.name = "dev";
-	cs->attr.attr.mode = S_IRUGO;
-	cs->attr.attr.owner = owner;
-	cs->attr.show = show_dev;
-	cs->attr.store = NULL;
-
-	retval = class_register(&cs->class);
-	if (retval)
-		goto error;
-	class_create_file(&cs->class, &class_attr_version);
-
-	return cs;
-
-      error:
-	kfree(cs);
-	return ERR_PTR(retval);
+	class_create_file(class, &class_attr_version);
+	return class;
 }
 
 /**
@@ -110,12 +59,13 @@
  * Note, the pointer to be destroyed must have been created with a call to
  * drm_sysfs_create().
  */
-void drm_sysfs_destroy(struct drm_sysfs_class *cs)
+void drm_sysfs_destroy(struct class *class)
 {
-	if ((cs == NULL) || (IS_ERR(cs)))
+	if ((class == NULL) || (IS_ERR(class)))
 		return;
 
-	class_unregister(&cs->class);
+	class_remove_file(class, &class_attr_version);
+	class_destroy(class);
 }
 
 static ssize_t show_dri(struct class_device *class_device, char *buf)
@@ -132,7 +82,7 @@
 
 /**
  * drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @cs: pointer to the struct drm_sysfs_class that this device should be registered to.
+ * @cs: pointer to the struct class that this device should be registered to.
  * @dev: the dev_t for the device to be added.
  * @device: a pointer to a struct device that is assiociated with this class device.
  * @fmt: string for the class device's name
@@ -141,46 +91,26 @@
  * class.  A "dev" file will be created, showing the dev_t for the device.  The
  * pointer to the struct class_device will be returned from the call.  Any further
  * sysfs files that might be required can be created using this pointer.
- * Note: the struct drm_sysfs_class passed to this function must have previously been
+ * Note: the struct class passed to this function must have previously been
  * created with a call to drm_sysfs_create().
  */
-struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
-					  drm_head_t *head)
+struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head)
 {
-	struct simple_dev *s_dev = NULL;
-	int i, retval;
+	struct class_device *class_dev;
+	int i;
 
-	if ((cs == NULL) || (IS_ERR(cs))) {
-		retval = -ENODEV;
-		goto error;
-	}
+	class_dev = class_device_create(cs, NULL,
+					MKDEV(DRM_MAJOR, head->minor),
+					&(head->dev->pdev)->dev,
+					"card%d", head->minor);
+	if (!class_dev)
+		return NULL;
 
-	s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
-	if (!s_dev) {
-		retval = -ENOMEM;
-		goto error;
-	}
-	memset(s_dev, 0x00, sizeof(*s_dev));
-
-	s_dev->dev = MKDEV(DRM_MAJOR, head->minor);
-	s_dev->class_dev.dev = &(head->dev->pdev)->dev;
-	s_dev->class_dev.class = &cs->class;
-
-	snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor);
-	retval = class_device_register(&s_dev->class_dev);
-	if (retval)
-		goto error;
-
-	class_device_create_file(&s_dev->class_dev, &cs->attr);
-	class_set_devdata(&s_dev->class_dev, head);
+	class_set_devdata(class_dev, head);
 
 	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
-		class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]);
-	return &s_dev->class_dev;
-
-error:
-	kfree(s_dev);
-	return ERR_PTR(retval);
+		class_device_create_file(class_dev, &class_device_attrs[i]);
+	return class_dev;
 }
 
 /**
@@ -192,10 +122,9 @@
  */
 void drm_sysfs_device_remove(struct class_device *class_dev)
 {
-	struct simple_dev *s_dev = to_simple_dev(class_dev);
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
-		class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]);
-	class_device_unregister(&s_dev->class_dev);
+		class_device_remove_file(class_dev, &class_device_attrs[i]);
+	class_device_unregister(class_dev);
 }
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index 3f73aa7..0291cd6 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -188,7 +188,7 @@
 
 	map = vma->vm_private_data;
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
 		next = pt->next;
 		if (pt->vma->vm_private_data == map)
@@ -248,7 +248,7 @@
 			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 		}
 	}
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 }
 
 /**
@@ -404,12 +404,12 @@
 
 	vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
 	if (vma_entry) {
-		down(&dev->struct_sem);
+		mutex_lock(&dev->struct_mutex);
 		vma_entry->vma = vma;
 		vma_entry->next = dev->vmalist;
 		vma_entry->pid = current->pid;
 		dev->vmalist = vma_entry;
-		up(&dev->struct_sem);
+		mutex_unlock(&dev->struct_mutex);
 	}
 }
 
@@ -431,7 +431,7 @@
 		  vma->vm_start, vma->vm_end - vma->vm_start);
 	atomic_dec(&dev->vma_count);
 
-	down(&dev->struct_sem);
+	mutex_lock(&dev->struct_mutex);
 	for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
 		if (pt->vma == vma) {
 			if (prev) {
@@ -443,7 +443,7 @@
 			break;
 		}
 	}
-	up(&dev->struct_sem);
+	mutex_unlock(&dev->struct_mutex);
 }
 
 /**
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index cc1b890..ae0aa6d 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -958,7 +958,7 @@
 }
 
 /* Must be called with the lock held */
-void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
 {
 	drm_device_dma_t *dma = dev->dma;
 	int i;
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index a18b80d..e8cf3ff 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -113,8 +113,6 @@
 } drm_i810_private_t;
 
 				/* i810_dma.c */
-extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp);
-
 extern int i810_driver_dma_quiescent(drm_device_t * dev);
 extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
 					       struct file *filp);
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 4fea32a..163f2cb 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -1239,7 +1239,7 @@
 }
 
 /* Must be called with the lock held */
-void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
 {
 	drm_device_dma_t *dma = dev->dma;
 	int i;
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index bf9075b..85bc5be 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -123,9 +123,6 @@
 extern drm_ioctl_desc_t i830_ioctls[];
 extern int i830_max_ioctl;
 
-/* i830_dma.c */
-extern void i830_reclaim_buffers(drm_device_t * dev, struct file *filp);
-
 /* i830_irq.c */
 extern int i830_irq_emit(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg);
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 9140703..1ff4c7c 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -344,18 +344,20 @@
 	int i;
 	RING_LOCALS;
 
+	if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
+		return DRM_ERR(EINVAL);
+
+	BEGIN_LP_RING(((dwords+1)&~1));
+
 	for (i = 0; i < dwords;) {
 		int cmd, sz;
 
 		if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
 			return DRM_ERR(EINVAL);
 
-/* 		printk("%d/%d ", i, dwords); */
-
 		if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
 			return DRM_ERR(EINVAL);
 
-		BEGIN_LP_RING(sz);
 		OUT_RING(cmd);
 
 		while (++i, --sz) {
@@ -365,9 +367,13 @@
 			}
 			OUT_RING(cmd);
 		}
-		ADVANCE_LP_RING();
 	}
 
+	if (dwords & 1)
+		OUT_RING(0);
+
+	ADVANCE_LP_RING();
+
 	return 0;
 }
 
@@ -401,6 +407,21 @@
 	return 0;
 }
 
+static void i915_emit_breadcrumb(drm_device_t *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+
+	BEGIN_LP_RING(4);
+	OUT_RING(CMD_STORE_DWORD_IDX);
+	OUT_RING(20);
+	OUT_RING(dev_priv->counter);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+}
+
 static int i915_dispatch_cmdbuffer(drm_device_t * dev,
 				   drm_i915_cmdbuffer_t * cmd)
 {
@@ -429,6 +450,7 @@
 			return ret;
 	}
 
+	i915_emit_breadcrumb(dev);
 	return 0;
 }
 
@@ -475,12 +497,7 @@
 
 	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
 
-	BEGIN_LP_RING(4);
-	OUT_RING(CMD_STORE_DWORD_IDX);
-	OUT_RING(20);
-	OUT_RING(dev_priv->counter);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
+	i915_emit_breadcrumb(dev);
 
 	return 0;
 }
@@ -657,7 +674,7 @@
 		value = READ_BREADCRUMB(dev_priv);
 		break;
 	default:
-		DRM_ERROR("Unkown parameter %d\n", param.param);
+		DRM_ERROR("Unknown parameter %d\n", param.param);
 		return DRM_ERR(EINVAL);
 	}
 
@@ -742,7 +759,8 @@
 	[DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},
 	[DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
 	[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-	[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}
+	[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 77412dd..4cb3da5 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -74,6 +74,30 @@
 	int pf_active;
 	int pf_current_page;	/* which buffer is being displayed? */
 	int perf_boxes;		/* performance boxes to be displayed */
+	int width, height;      /* screen size in pixels */
+
+	drm_handle_t front_handle;
+	int front_offset;
+	int front_size;
+
+	drm_handle_t back_handle;
+	int back_offset;
+	int back_size;
+
+	drm_handle_t depth_handle;
+	int depth_offset;
+	int depth_size;
+
+	drm_handle_t tex_handle;
+	int tex_offset;
+	int tex_size;
+	int log_tex_granularity;
+	int pitch;
+	int rotation;           /* 0, 90, 180 or 270 */
+	int rotated_offset;
+	int rotated_size;
+	int rotated_pitch;
+	int virtualX, virtualY;
 } drm_i915_sarea_t;
 
 /* Flags for perf_boxes
@@ -99,6 +123,7 @@
 #define DRM_I915_FREE		0x09
 #define DRM_I915_INIT_HEAP	0x0a
 #define DRM_I915_CMDBUFFER	0x0b
+#define DRM_I915_DESTROY_HEAP	0x0c
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -112,6 +137,7 @@
 #define DRM_IOCTL_I915_FREE             DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
 #define DRM_IOCTL_I915_INIT_HEAP        DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
 #define DRM_IOCTL_I915_CMDBUFFER	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
+#define DRM_IOCTL_I915_DESTROY_HEAP	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -191,4 +217,11 @@
 	int start;
 } drm_i915_mem_init_heap_t;
 
+/* Allow memory manager to be torn down and re-initialized (eg on
+ * rotate):
+ */
+typedef struct drm_i915_mem_destroy_heap {
+	int region;
+} drm_i915_mem_destroy_heap_t;
+
 #endif				/* _I915_DRM_H_ */
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index c6c71b4..7a65666 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -37,16 +37,17 @@
 
 #define DRIVER_NAME		"i915"
 #define DRIVER_DESC		"Intel Graphics"
-#define DRIVER_DATE		"20051209"
+#define DRIVER_DATE		"20060119"
 
 /* Interface history:
  *
  * 1.1: Original.
  * 1.2: Add Power Management
  * 1.3: Add vblank support
+ * 1.4: Fix cmdbuffer path, add heap destroy
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		3
+#define DRIVER_MINOR		4
 #define DRIVER_PATCHLEVEL	0
 
 typedef struct _drm_i915_ring_buffer {
@@ -123,6 +124,7 @@
 extern int i915_mem_alloc(DRM_IOCTL_ARGS);
 extern int i915_mem_free(DRM_IOCTL_ARGS);
 extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
+extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS);
 extern void i915_mem_takedown(struct mem_block **heap);
 extern void i915_mem_release(drm_device_t * dev,
 			     DRMFILE filp, struct mem_block *heap);
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index ba87ff1..52c6732 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -365,3 +365,34 @@
 
 	return init_heap(heap, initheap.start, initheap.size);
 }
+
+int i915_mem_destroy_heap( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_mem_destroy_heap_t destroyheap;
+	struct mem_block **heap;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( destroyheap, (drm_i915_mem_destroy_heap_t *)data,
+				  sizeof(destroyheap) );
+
+	heap = get_heap( dev_priv, destroyheap.region );
+	if (!heap) {
+		DRM_ERROR("get_heap failed");
+		return DRM_ERR(EFAULT);
+	}
+	
+	if (!*heap) {
+		DRM_ERROR("heap not initialized?");
+		return DRM_ERR(EFAULT);
+	}
+
+	i915_mem_takedown( heap );
+	return 0;
+}
+
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 915665c..9bb8ae0 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1640,7 +1640,7 @@
 		if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
 		{
 			drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
-			dev_priv->gart_info.addr = 0;
+			dev_priv->gart_info.addr = NULL;
 		}
 	}
 	/* only clear to the start of flags */
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
index 0d426de..59c7520 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -32,6 +32,8 @@
 #define SAVAGE_EVENT_USEC_TIMEOUT	5000000	/* 5s */
 #define SAVAGE_FREELIST_DEBUG		0
 
+static int savage_do_cleanup_bci(drm_device_t *dev);
+
 static int
 savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
 {
@@ -895,7 +897,7 @@
 	return 0;
 }
 
-int savage_do_cleanup_bci(drm_device_t * dev)
+static int savage_do_cleanup_bci(drm_device_t * dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
index dd46cb8..8f04b3d 100644
--- a/drivers/char/drm/savage_drv.h
+++ b/drivers/char/drm/savage_drv.h
@@ -212,7 +212,6 @@
 extern int savage_driver_firstopen(drm_device_t *dev);
 extern void savage_driver_lastclose(drm_device_t *dev);
 extern int savage_driver_unload(drm_device_t *dev);
-extern int savage_do_cleanup_bci(drm_device_t * dev);
 extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp);
 
 /* state functions */
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index 593c0b8..a691ae7 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -222,7 +222,7 @@
 	return 0;
 }
 
-int via_dma_init(DRM_IOCTL_ARGS)
+static int via_dma_init(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -321,7 +321,7 @@
 	return 0;
 }
 
-int via_flush_ioctl(DRM_IOCTL_ARGS)
+static int via_flush_ioctl(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
 
@@ -330,7 +330,7 @@
 	return via_driver_dma_quiescent(dev);
 }
 
-int via_cmdbuffer(DRM_IOCTL_ARGS)
+static int via_cmdbuffer(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
 	drm_via_cmdbuffer_t cmdbuf;
@@ -375,7 +375,7 @@
 	return ret;
 }
 
-int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
+static int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
 	drm_via_cmdbuffer_t cmdbuf;
@@ -665,7 +665,7 @@
  * User interface to the space and lag functions.
  */
 
-int via_cmdbuf_size(DRM_IOCTL_ARGS)
+static int via_cmdbuf_size(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
 	drm_via_cmdbuf_size_t d_siz;
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index 9d5e027..b7f1745 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -108,7 +108,7 @@
 	int num_desc = 0;
 	int cur_line;
 	dma_addr_t next = 0 | VIA_DMA_DPR_EC;
-	drm_via_descriptor_t *desc_ptr = 0;
+	drm_via_descriptor_t *desc_ptr = NULL;
 
 	if (mode == 1) 
 		desc_ptr = vsg->desc_pages[cur_descriptor_page];
@@ -167,7 +167,7 @@
  */
 
 
-void
+static void
 via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) 
 {
 	struct page *page;
@@ -581,7 +581,7 @@
 	int ret = 0;
 	
 	vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-	vsg->bounce_buffer = 0;
+	vsg->bounce_buffer = NULL;
 
 	vsg->state = dr_via_sg_init;
 
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index aad4f99..52bcc7b 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -110,11 +110,6 @@
 extern int via_agp_init(DRM_IOCTL_ARGS);
 extern int via_map_init(DRM_IOCTL_ARGS);
 extern int via_decoder_futex(DRM_IOCTL_ARGS);
-extern int via_dma_init(DRM_IOCTL_ARGS);
-extern int via_cmdbuffer(DRM_IOCTL_ARGS);
-extern int via_flush_ioctl(DRM_IOCTL_ARGS);
-extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
-extern int via_cmdbuf_size(DRM_IOCTL_ARGS);
 extern int via_wait_irq(DRM_IOCTL_ARGS);
 extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
 extern int via_dma_blit( DRM_IOCTL_ARGS );
@@ -139,8 +134,6 @@
 extern void via_init_futex(drm_via_private_t * dev_priv);
 extern void via_cleanup_futex(drm_via_private_t * dev_priv);
 extern void via_release_futex(drm_via_private_t * dev_priv, int context);
-extern int via_driver_irq_wait(drm_device_t * dev, unsigned int irq,
-			       int force_sequence, unsigned int *sequence);
 
 extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
 extern void via_init_dmablit(drm_device_t *dev);
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index 56d7e3d..6152415 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -190,7 +190,7 @@
 	return ret;
 }
 
-int
+static int
 via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
 		    unsigned int *sequence)
 {
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 3f3ac03..57539d8 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -359,7 +359,7 @@
 		}
 	}
 
-	schedule_delayed_work(&tty->buf.work, 1);
+	tty_schedule_flip(tty);
 
 	info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
 	release_pio_buffer(pio_buf);
@@ -426,7 +426,7 @@
 			}
 			tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag);
 		}
-		schedule_delayed_work(&tty->buf.work, 1);
+		tty_schedule_flip(tty);
 	}
 
 	if (dma_bytes != num_bytes) {
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 40a67c8..ac62641 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -117,12 +117,9 @@
 __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
 #endif /* not MODULE */
 
-#if defined(CONFIG_X86)
+#if defined(CONFIG_X86) || defined(CONFIG_S390)
 # define HAVE_MONOTONIC
 # define TIMER_FREQ 1000000000ULL
-#elif defined(CONFIG_S390)
-/* FA240000 is 1 Second in the IBM time universe (Page 4-38 Principles of Op for zSeries */
-# define TIMER_FREQ 0xFA240000ULL
 #elif defined(CONFIG_IA64)
 # define TIMER_FREQ ((unsigned long long)local_cpu_data->itc_freq)
 #elif defined(CONFIG_PPC64)
@@ -134,12 +131,7 @@
 #else
 static inline unsigned long long monotonic_clock(void)
 {
-# ifdef __s390__
-	/* returns the TOD.  see 4-38 Principles of Op of zSeries */
-	return get_clock();
-# else
 	return get_cycles();
-# endif  /* __s390__ */
 }
 #endif  /* HAVE_MONOTONIC */
 
@@ -188,8 +180,6 @@
 	       VERSION_STR, hangcheck_tick, hangcheck_margin);
 #if defined (HAVE_MONOTONIC)
 	printk("Hangcheck: Using monotonic_clock().\n");
-#elif defined(__s390__)
-	printk("Hangcheck: Using TOD.\n");
 #else
 	printk("Hangcheck: Using get_cycles().\n");
 #endif  /* HAVE_MONOTONIC */
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 3808d95..66a2fee 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -927,9 +927,9 @@
 	if (ACPI_SUCCESS(status)) {
 		unsigned long size;
 
-		size = addr.max_address_range - addr.min_address_range + 1;
-		hdp->hd_phys_address = addr.min_address_range;
-		hdp->hd_address = ioremap(addr.min_address_range, size);
+		size = addr.maximum - addr.minimum + 1;
+		hdp->hd_phys_address = addr.minimum;
+		hdp->hd_address = ioremap(addr.minimum, size);
 
 		if (hpet_is_known(hdp)) {
 			printk(KERN_DEBUG "%s: 0x%lx is busy\n",
@@ -937,15 +937,15 @@
 			iounmap(hdp->hd_address);
 			return -EBUSY;
 		}
-	} else if (res->id == ACPI_RSTYPE_FIXED_MEM32) {
-		struct acpi_resource_fixed_mem32 *fixmem32;
+	} else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
+		struct acpi_resource_fixed_memory32 *fixmem32;
 
 		fixmem32 = &res->data.fixed_memory32;
 		if (!fixmem32)
 			return -EINVAL;
 
-		hdp->hd_phys_address = fixmem32->range_base_address;
-		hdp->hd_address = ioremap(fixmem32->range_base_address,
+		hdp->hd_phys_address = fixmem32->address;
+		hdp->hd_address = ioremap(fixmem32->address,
 						HPET_RANGE_SIZE);
 
 		if (hpet_is_known(hdp)) {
@@ -954,20 +954,20 @@
 			iounmap(hdp->hd_address);
 			return -EBUSY;
 		}
-	} else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
-		struct acpi_resource_ext_irq *irqp;
+	} else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
+		struct acpi_resource_extended_irq *irqp;
 		int i;
 
 		irqp = &res->data.extended_irq;
 
-		if (irqp->number_of_interrupts > 0) {
-			hdp->hd_nirqs = irqp->number_of_interrupts;
+		if (irqp->interrupt_count > 0) {
+			hdp->hd_nirqs = irqp->interrupt_count;
 
 			for (i = 0; i < hdp->hd_nirqs; i++) {
 				int rc =
 				    acpi_register_gsi(irqp->interrupts[i],
-						      irqp->edge_level,
-						      irqp->active_high_low);
+						      irqp->triggering,
+						      irqp->polarity);
 				if (rc < 0)
 					return AE_ERROR;
 				hdp->hd_irq[i] = rc;
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c
index cb8f419..e7af647 100644
--- a/drivers/char/ip2/i2cmd.c
+++ b/drivers/char/ip2/i2cmd.c
@@ -139,7 +139,6 @@
 //static UCHAR ct86[]={ 2, BTH,     0x56,0                   }; // RCV_ENABLE
 static UCHAR ct87[] = { 1, BYP,     0x57                     }; // HW_TEST
 //static UCHAR ct88[]={ 3, BTH,     0x58,0,0                 }; // RCV_THRESHOLD
-static UCHAR ct89[]={ 1, BYP,     0x59                     }; // DSS_NOW
 //static UCHAR ct90[]={ 3, BYP,     0x5A,0,0                 }; // Set SILO
 //static UCHAR ct91[]={ 2, BYP,     0x5B,0                   }; // timed break
 
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index 56e93a5..48fcfba 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -2906,65 +2906,16 @@
 		rc = -EINVAL;
 		break;
 	case 3:	    // Trace device
-		if ( cmd == 1 ) {
-			rc = put_user(iiSendPendingMail, pIndex++ );
-			rc = put_user(i2InitChannels, pIndex++ );
-			rc = put_user(i2QueueNeeds, pIndex++ );
-			rc = put_user(i2QueueCommands, pIndex++ );
-			rc = put_user(i2GetStatus, pIndex++ );
-			rc = put_user(i2Input, pIndex++ );
-			rc = put_user(i2InputFlush, pIndex++ );
-			rc = put_user(i2Output, pIndex++ );
-			rc = put_user(i2FlushOutput, pIndex++ );
-			rc = put_user(i2DrainWakeup, pIndex++ );
-			rc = put_user(i2DrainOutput, pIndex++ );
-			rc = put_user(i2OutputFree, pIndex++ );
-			rc = put_user(i2StripFifo, pIndex++ );
-			rc = put_user(i2StuffFifoBypass, pIndex++ );
-			rc = put_user(i2StuffFifoFlow, pIndex++ );
-			rc = put_user(i2StuffFifoInline, pIndex++ );
-			rc = put_user(i2ServiceBoard, pIndex++ );
-			rc = put_user(serviceOutgoingFifo, pIndex++ );
-			// rc = put_user(ip2_init, pIndex++ );
-			rc = put_user(ip2_init_board, pIndex++ );
-			rc = put_user(find_eisa_board, pIndex++ );
-			rc = put_user(set_irq, pIndex++ );
-			rc = put_user(ip2_interrupt, pIndex++ );
-			rc = put_user(ip2_poll, pIndex++ );
-			rc = put_user(service_all_boards, pIndex++ );
-			rc = put_user(do_input, pIndex++ );
-			rc = put_user(do_status, pIndex++ );
-#ifndef IP2DEBUG_OPEN
-			rc = put_user(0, pIndex++ );
-#else
-			rc = put_user(open_sanity_check, pIndex++ );
-#endif
-			rc = put_user(ip2_open, pIndex++ );
-			rc = put_user(ip2_close, pIndex++ );
-			rc = put_user(ip2_hangup, pIndex++ );
-			rc = put_user(ip2_write, pIndex++ );
-			rc = put_user(ip2_putchar, pIndex++ );
-			rc = put_user(ip2_flush_chars, pIndex++ );
-			rc = put_user(ip2_write_room, pIndex++ );
-			rc = put_user(ip2_chars_in_buf, pIndex++ );
-			rc = put_user(ip2_flush_buffer, pIndex++ );
-
-			//rc = put_user(ip2_wait_until_sent, pIndex++ );
-			rc = put_user(0, pIndex++ );
-
-			rc = put_user(ip2_throttle, pIndex++ );
-			rc = put_user(ip2_unthrottle, pIndex++ );
-			rc = put_user(ip2_ioctl, pIndex++ );
-			rc = put_user(0, pIndex++ );
-			rc = put_user(get_serial_info, pIndex++ );
-			rc = put_user(set_serial_info, pIndex++ );
-			rc = put_user(ip2_set_termios, pIndex++ );
-			rc = put_user(ip2_set_line_discipline, pIndex++ );
-			rc = put_user(set_params, pIndex++ );
-		} else {
+		/*
+		 * akpm: This used to write a whole bunch of function addresses
+		 * to userspace, which generated lots of put_user() warnings.
+		 * I killed it all.  Just return "success" and don't do
+		 * anything.
+		 */
+		if (cmd == 1)
+			rc = 0;
+		else
 			rc = -EINVAL;
-		}
-
 		break;
 
 	default:
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 0097f06..d745004 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -481,7 +481,7 @@
 	}
 
 	if ((addr->channel == IPMI_BMC_CHANNEL)
-	    || (addr->channel >= IPMI_NUM_CHANNELS)
+	    || (addr->channel >= IPMI_MAX_CHANNELS)
 	    || (addr->channel < 0))
 		return -EINVAL;
 
@@ -1321,7 +1321,7 @@
 		unsigned char         ipmb_seq;
 		long                  seqid;
 
-		if (addr->channel >= IPMI_NUM_CHANNELS) {
+		if (addr->channel >= IPMI_MAX_CHANNELS) {
 			spin_lock_irqsave(&intf->counter_lock, flags);
 			intf->sent_invalid_commands++;
 			spin_unlock_irqrestore(&intf->counter_lock, flags);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index c67ef3e..e59b638 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1270,36 +1270,36 @@
 	return 0;
 }
 
-static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset)
+static unsigned char intf_mem_inb(struct si_sm_io *io, unsigned int offset)
 {
 	return readb((io->addr)+(offset * io->regspacing));
 }
 
-static void mem_outb(struct si_sm_io *io, unsigned int offset,
+static void intf_mem_outb(struct si_sm_io *io, unsigned int offset,
 		     unsigned char b)
 {
 	writeb(b, (io->addr)+(offset * io->regspacing));
 }
 
-static unsigned char mem_inw(struct si_sm_io *io, unsigned int offset)
+static unsigned char intf_mem_inw(struct si_sm_io *io, unsigned int offset)
 {
 	return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift)
 		&& 0xff;
 }
 
-static void mem_outw(struct si_sm_io *io, unsigned int offset,
+static void intf_mem_outw(struct si_sm_io *io, unsigned int offset,
 		     unsigned char b)
 {
 	writeb(b << io->regshift, (io->addr)+(offset * io->regspacing));
 }
 
-static unsigned char mem_inl(struct si_sm_io *io, unsigned int offset)
+static unsigned char intf_mem_inl(struct si_sm_io *io, unsigned int offset)
 {
 	return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift)
 		&& 0xff;
 }
 
-static void mem_outl(struct si_sm_io *io, unsigned int offset,
+static void intf_mem_outl(struct si_sm_io *io, unsigned int offset,
 		     unsigned char b)
 {
 	writel(b << io->regshift, (io->addr)+(offset * io->regspacing));
@@ -1349,16 +1349,16 @@
 	   upon the register size. */
 	switch (info->io.regsize) {
 	case 1:
-		info->io.inputb = mem_inb;
-		info->io.outputb = mem_outb;
+		info->io.inputb = intf_mem_inb;
+		info->io.outputb = intf_mem_outb;
 		break;
 	case 2:
-		info->io.inputb = mem_inw;
-		info->io.outputb = mem_outw;
+		info->io.inputb = intf_mem_inw;
+		info->io.outputb = intf_mem_outw;
 		break;
 	case 4:
-		info->io.inputb = mem_inl;
-		info->io.outputb = mem_outl;
+		info->io.inputb = intf_mem_inl;
+		info->io.outputb = intf_mem_outl;
 		break;
 #ifdef readq
 	case 8:
@@ -1580,11 +1580,6 @@
 	if (! is_new_interface(-1, addr_space, spmi->addr.address))
 		return -ENODEV;
 
-	if (! spmi->addr.register_bit_width) {
-		acpi_failure = 1;
-		return -ENODEV;
-	}
-
 	/* Figure out the interface type. */
 	switch (spmi->InterfaceType)
 	{
@@ -1634,9 +1629,6 @@
 		regspacings[intf_num] = spmi->addr.register_bit_width / 8;
 		info->io.regspacing = spmi->addr.register_bit_width / 8;
 	} else {
-		/* Some broken systems get this wrong and set the value
-		 * to zero.  Assume it is the default spacing.  If that
-		 * is wrong, too bad, the vendor should fix the tables. */
 		regspacings[intf_num] = DEFAULT_REGSPACING;
 		info->io.regspacing = DEFAULT_REGSPACING;
 	}
diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h
index 217ff09..89bd94e 100644
--- a/drivers/char/rio/cirrus.h
+++ b/drivers/char/rio/cirrus.h
@@ -40,148 +40,6 @@
 #endif
 #define _cirrus_h 1
 
-#ifdef RTA
-#define	TO_UART	RX
-#define TO_DRIVER TX
-#endif
-
-#ifdef HOST
-#define	TO_UART	TX
-#define TO_DRIVER RX
-#endif
-#ifdef RTA
-/* Miscellaneous defines for CIRRUS addresses and related logic for
-   interrupts etc.
-*/
-#define	MAP(a)		((short *)(cirrus_base + (a)))
-#define outp(a,b)	(*MAP (a) =(b))
-#define inp(a)		((*MAP (a)) & 0xff)
-#define	CIRRUS_FIRST	(short*)0x7300
-#define	CIRRUS_SECOND	(short*)0x7200
-#define	CIRRUS_THIRD	(short*)0x7100
-#define	CIRRUS_FOURTH	(short*)0x7000
-#define	PORTS_ON_CIRRUS	4
-#define	CIRRUS_FIFO_SIZE	12
-#define	SPACE		0x20
-#define	TAB		0x09
-#define	LINE_FEED	0x0a
-#define	CARRIAGE_RETURN	0x0d
-#define	BACKSPACE	0x08
-#define	SPACES_IN_TABS	8
-#define	SEND_ESCAPE	0x00
-#define START_BREAK	0x81
-#define	TIMER_TICK	0x82
-#define STOP_BREAK	0x83
-#define BASE(a) ((a) < 4 ? (short*)CIRRUS_FIRST : ((a) < 8 ? (short *)CIRRUS_SECOND : ((a) < 12 ? (short*)CIRRUS_THIRD : (short *)CIRRUS_FOURTH)))
-#define txack1	((short *)0x7104)
-#define rxack1	((short *)0x7102)
-#define mdack1  ((short *)0x7106)
-#define txack2  ((short *)0x7006)
-#define rxack2	((short *)0x7004)
-#define mdack2  ((short *)0x7100)
-#define int_latch       ((short *) 0x7800)
-#define int_status      ((short *) 0x7c00)
-#define tx1_pending     0x20
-#define rx1_pending     0x10
-#define md1_pending     0x40
-#define tx2_pending     0x02
-#define rx2_pending     0x01
-#define md2_pending     0x40
-#define module1_bits	0x07
-#define module1_modern	0x08
-#define module2_bits	0x70
-#define module2_modern	0x80
-#define module_blank	0xf
-#define rs232_d25	0x0
-#define	rs232_rj45	0x1
-#define rs422_d25	0x3
-#define parallel	0x5
-
-#define	CLK0	0x00
-#define CLK1	0x01
-#define CLK2	0x02
-#define CLK3	0x03
-#define CLK4	0x04
-
-#define CIRRUS_REVC    0x42
-#define CIRRUS_REVE    0x44
-
-#define	TURNON	1
-#define TURNOFF 0
-
-/* The list of CIRRUS registers. 
-   NB. These registers are relative values on 8 bit boundaries whereas
-   on the RTA's the CIRRUS registers are on word boundaries. Use pointer
-   arithmetic (short *) to obtain the real addresses required */
-#define ccr	0x05		/* Channel Command Register     */
-#define ier	0x06		/* Interrupt Enable Register    */
-#define cor1	0x08		/* Channel Option Register 1    */
-#define cor2	0x09		/* Channel Option Register 2    */
-#define cor3	0x0a		/* Channel Option Register 3    */
-#define cor4	0x1e		/* Channel Option Register 4    */
-#define	cor5	0x1f		/* Channel Option Register 5    */
-
-#define ccsr	0x0b		/* Channel Control Status Register */
-#define rdcr	0x0e		/* Receive Data Count Register  */
-#define tdcr	0x12		/* Transmit Data Count Register */
-#define mcor1	0x15		/* Modem Change Option Register 1 */
-#define mcor2	0x16		/* Modem Change Option Regsiter 2 */
-
-#define livr	0x18		/* Local Interrupt Vector Register */
-#define schr1	0x1a		/* Special Character Register 1 */
-#define schr2	0x1b		/* Special Character Register 2 */
-#define schr3	0x1c		/* Special Character Register 3 */
-#define schr4	0x1d		/* Special Character Register 4 */
-
-#define rtr	0x20		/* Receive Timer Register */
-#define rtpr	0x21		/* Receive Timeout Period Register */
-#define lnc	0x24		/* Lnext character */
-
-#define rivr	0x43		/* Receive Interrupt Vector Register    */
-#define tivr	0x42		/* Transmit Interrupt Vector Register   */
-#define mivr	0x41		/* Modem Interrupt Vector Register      */
-#define gfrcr	0x40		/* Global Firmware Revision code Reg    */
-#define ricr	0x44		/* Receive Interrupting Channel Reg     */
-#define ticr	0x45		/* Transmit Interrupting Channel Reg    */
-#define micr	0x46		/* Modem Interrupting Channel Register  */
-
-#define gcr	0x4b		/* Global configuration register */
-#define misr    0x4c		/* Modem interrupt status register */
-
-#define rbusr	0x59
-#define tbusr	0x5a
-#define mbusr	0x5b
-
-#define eoir	0x60		/* End Of Interrupt Register */
-#define rdsr	0x62		/* Receive Data / Status Register */
-#define tdr	0x63		/* Transmit Data Register */
-#define svrr	0x67		/* Service Request Register */
-
-#define car	0x68		/* Channel Access Register */
-#define mir	0x69		/* Modem Interrupt Register */
-#define tir	0x6a		/* Transmit Interrupt Register */
-#define rir	0x6b		/* Receive Interrupt Register */
-#define msvr1	0x6c		/* Modem Signal Value Register 1 */
-#define msvr2	0x6d		/* Modem Signal Value Register 2 */
-#define psvr	0x6f		/* Printer Signal Value Register */
-
-#define tbpr	0x72		/* Transmit Baud Rate Period Register */
-#define tcor	0x76		/* Transmit Clock Option Register */
-
-#define rbpr	0x78		/* Receive Baud Rate Period Register */
-#define rber	0x7a		/* Receive Baud Rate Extension Register */
-#define rcor	0x7c		/* Receive Clock Option Register */
-#define ppr	0x7e		/* Prescalar Period Register    */
-
-/* Misc registers used for forcing the 1400 out of its reset woes */
-#define airl	0x6d
-#define airm	0x6e
-#define airh	0x6f
-#define btcr	0x66
-#define mtcr	0x6c
-#define tber	0x74
-
-#endif				/* #ifdef RTA */
 
 
 /* Bit fields for particular registers */
diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h
index 5b600c3..d55c2f6 100644
--- a/drivers/char/rio/defaults.h
+++ b/drivers/char/rio/defaults.h
@@ -45,13 +45,6 @@
 #define MILLISECOND           (int) (1000/64)	/* 15.625 low ticks */
 #define SECOND                (int) 15625	/* Low priority ticks */
 
-#ifdef RTA
-#define RX_LIMIT       (ushort) 3
-#endif
-#ifdef HOST
-#define RX_LIMIT       (ushort) 1
-#endif
-
 #define LINK_TIMEOUT          (int) (POLL_PERIOD / 2)
 
 
diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h
index bfba5b0..48d68ca 100644
--- a/drivers/char/rio/link.h
+++ b/drivers/char/rio/link.h
@@ -102,30 +102,14 @@
 /*
 ** LED stuff
 */
-#if defined(RTA)
-#define LED_OFF            ((ushort) 0)	/* LED off */
-#define LED_RED            ((ushort) 1)	/* LED Red */
-#define LED_GREEN          ((ushort) 2)	/* LED Green */
-#define LED_ORANGE         ((ushort) 4)	/* LED Orange */
-#define LED_1TO8_OPEN      ((ushort) 1)	/* Port 1->8 LED on */
-#define LED_9TO16_OPEN     ((ushort) 2)	/* Port 9->16 LED on */
-#define LED_SET_COLOUR(colour)	(link->led = (colour))
-#define LED_OR_COLOUR(colour)	(link->led |= (colour))
-#define LED_TIMEOUT(time)    (link->led_timeout = RioTimePlus(RioTime(),(time)))
-#else
 #define LED_SET_COLOUR(colour)
 #define LED_OR_COLOUR(colour)
 #define LED_TIMEOUT(time)
-#endif				/* RTA */
 
 struct LPB {
 	WORD link_number;	/* Link Number */
 	Channel_ptr in_ch;	/* Link In Channel */
 	Channel_ptr out_ch;	/* Link Out Channel */
-#ifdef RTA
-	uchar stat_led;		/* Port open leds */
-	uchar led;		/* True, light led! */
-#endif
 	BYTE attached_serial[4];	/* Attached serial number */
 	BYTE attached_host_serial[4];
 	/* Serial number of Host who
@@ -144,30 +128,12 @@
 	WORD WaitNoBoot;	/* Secs to hold off booting */
 	PKT_ptr add_packet_list;	/* Add packets to here */
 	PKT_ptr remove_packet_list;	/* Send packets from here */
-#ifdef RTA
-#ifdef DCIRRUS
-#define    QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1)
-#else
-#define    QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1)
-#endif
-	PKT_ptr_ptr rd_add;	/* Add a new Packet here */
-	Q_BUF_ptr rd_add_qb;	/* Pointer to the add Q buf */
-	PKT_ptr_ptr rd_add_st_qbb;	/* Pointer to start of the Q's buf */
-	PKT_ptr_ptr rd_add_end_qbb;	/* Pointer to the end of the Q's buf */
-	PKT_ptr_ptr rd_remove;	/* Remove a Packet here */
-	Q_BUF_ptr rd_remove_qb;	/* Pointer to the remove Q buf */
-	PKT_ptr_ptr rd_remove_st_qbb;	/* Pointer to the start of the Q buf */
-	PKT_ptr_ptr rd_remove_end_qbb;	/* Pointer to the end of the Q buf */
-	ushort pkts_in_q;	/* Packets in queue */
-#endif
 
 	Channel_ptr lrt_fail_chan;	/* Lrt's failure channel */
 	Channel_ptr ltt_fail_chan;	/* Ltt's failure channel */
 
-#if defined (HOST) || defined (INKERNEL)
 	/* RUP structure for HOST to driver communications */
 	struct RUP rup;
-#endif
 	struct RUP link_rup;	/* RUP for the link (POLL,
 				   topology etc.) */
 	WORD attached_link;	/* Number of attached link */
diff --git a/drivers/char/rio/list.h b/drivers/char/rio/list.h
index 36aad4c..79b8531 100644
--- a/drivers/char/rio/list.h
+++ b/drivers/char/rio/list.h
@@ -44,8 +44,6 @@
 
 #define PKT_IN_USE    0x1
 
-#ifdef INKERNEL
-
 #define ZERO_PTR (ushort) 0x8000
 #define	CaD	PortP->Caddr
 
@@ -54,143 +52,5 @@
 ** to by the TxAdd pointer has PKT_IN_USE clear in its address.
 */
 
-#ifndef linux
-#if defined( MIPS ) && !defined( MIPSEISA )
-/* May the shoes of the Devil dance on your grave for creating this */
-#define   can_add_transmit(PacketP,PortP) \
-          (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \
-          & (PKT_IN_USE<<2)))
-
-#elif  defined(MIPSEISA) || defined(nx6000) || \
-       defined(drs6000)  || defined(UWsparc)
-
-#define   can_add_transmit(PacketP,PortP) \
-          (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \
-	  & PKT_IN_USE))
-
-#else
-#define   can_add_transmit(PacketP,PortP) \
-          (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,*PortP->TxAdd)) \
-	  & PKT_IN_USE))
-#endif
-
-/*
-** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
-** and then move the TxAdd pointer along one position to point to the next
-** packet pointer. You must wrap the pointer from the end back to the start.
-*/
-#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
-#   define add_transmit(PortP)  \
-	WINDW(PortP->TxAdd,RINDW(PortP->TxAdd) | PKT_IN_USE);\
-	if (PortP->TxAdd == PortP->TxEnd)\
-	    PortP->TxAdd = PortP->TxStart;\
-	else\
-	    PortP->TxAdd++;\
-	WWORD(PortP->PhbP->tx_add , RIO_OFF(CaD,PortP->TxAdd));
-#elif defined(AIX)
-#   define add_transmit(PortP)  \
-	{\
-	    register ushort *TxAddP = (ushort *)RIO_PTR(Cad,PortP->TxAddO);\
-	    WINDW( TxAddP, RINDW( TxAddP ) | PKT_IN_USE );\
-	    if (PortP->TxAddO == PortP->TxEndO )\
-		PortP->TxAddO = PortP->TxStartO;\
-	    else\
-		PortP->TxAddO += sizeof(ushort);\
-	    WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->tx_add , PortP->TxAddO );\
-	}
-#else
-#   define add_transmit(PortP)  \
-	*PortP->TxAdd |= PKT_IN_USE;\
-	if (PortP->TxAdd == PortP->TxEnd)\
-	    PortP->TxAdd = PortP->TxStart;\
-	else\
-	    PortP->TxAdd++;\
-	PortP->PhbP->tx_add = RIO_OFF(CaD,PortP->TxAdd);
-#endif
-
-/*
-** can_remove_receive( PacketP, PortP ) returns non-zero if PKT_IN_USE is set
-** for the next packet on the queue. It will also set PacketP to point to the
-** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
-** then can_remove_receive() returns 0.
-*/
-#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
-#   define can_remove_receive(PacketP,PortP) \
-	((RINDW(PortP->RxRemove) & PKT_IN_USE) ? \
-	(PacketP=(struct PKT *)RIO_PTR(CaD,(RINDW(PortP->RxRemove) & ~PKT_IN_USE))):0)
-#elif defined(AIX)
-#   define can_remove_receive(PacketP,PortP) \
-	((RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & PKT_IN_USE) ? \
-	(PacketP=(struct PKT *)RIO_PTR(Cad,RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & ~PKT_IN_USE)):0)
-#else
-#   define can_remove_receive(PacketP,PortP) \
-	((*PortP->RxRemove & PKT_IN_USE) ? \
-	(PacketP=(struct PKT *)RIO_PTR(CaD,(*PortP->RxRemove & ~PKT_IN_USE))):0)
-#endif
-
-
-/*
-** Will God see it within his heart to forgive us for this thing that
-** we have created? To remove a packet from the receive queue you clear
-** its PKT_IN_USE bit, and then bump the pointers. Once the pointers
-** get to the end, they must be wrapped back to the start.
-*/
-#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
-#   define remove_receive(PortP) \
-	WINDW(PortP->RxRemove, (RINDW(PortP->RxRemove) & ~PKT_IN_USE));\
-	if (PortP->RxRemove == PortP->RxEnd)\
-	    PortP->RxRemove = PortP->RxStart;\
-	else\
-	    PortP->RxRemove++;\
-	WWORD(PortP->PhbP->rx_remove , RIO_OFF(CaD,PortP->RxRemove));
-#elif defined(AIX)
-#   define remove_receive(PortP) \
-    {\
-        register ushort *RxRemoveP = (ushort *)RIO_PTR(Cad,PortP->RxRemoveO);\
-        WINDW( RxRemoveP, RINDW( RxRemoveP ) & ~PKT_IN_USE );\
-        if (PortP->RxRemoveO == PortP->RxEndO)\
-            PortP->RxRemoveO = PortP->RxStartO;\
-        else\
-            PortP->RxRemoveO += sizeof(ushort);\
-        WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->rx_remove, PortP->RxRemoveO );\
-    }
-#else
-#   define remove_receive(PortP) \
-	*PortP->RxRemove &= ~PKT_IN_USE;\
-	if (PortP->RxRemove == PortP->RxEnd)\
-	    PortP->RxRemove = PortP->RxStart;\
-	else\
-	    PortP->RxRemove++;\
-	PortP->PhbP->rx_remove = RIO_OFF(CaD,PortP->RxRemove);
-#endif
-#endif
-
-
-#else				/* !IN_KERNEL */
-
-#define ZERO_PTR NULL
-
-
-#ifdef HOST
-/* #define can_remove_transmit(pkt,phb) ((((char*)pkt = (*(char**)(phb->tx_remove))-1) || 1)) && (*phb->u3.s2.tx_remove_ptr & PKT_IN_USE))   */
-#define remove_transmit(phb) *phb->u3.s2.tx_remove_ptr &= ~(ushort)PKT_IN_USE;\
-                             if (phb->tx_remove == phb->tx_end)\
-                                phb->tx_remove = phb->tx_start;\
-                             else\
-                                phb->tx_remove++;
-#define can_add_receive(phb) !(*phb->u4.s2.rx_add_ptr & PKT_IN_USE)
-#define add_receive(pkt,phb) *phb->rx_add = pkt;\
-                             *phb->u4.s2.rx_add_ptr |= PKT_IN_USE;\
-                             if (phb->rx_add == phb->rx_end)\
-                                phb->rx_add = phb->rx_start;\
-                             else\
-                                phb->rx_add++;
-#endif
-#endif
-
-#ifdef RTA
-#define splx(oldspl)    if ((oldspl) == 0) spl0()
-#endif
-
 #endif				/* ifndef _list.h */
 /*********** end of file ***********/
diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h
index fe4e005..e24acc1 100644
--- a/drivers/char/rio/parmmap.h
+++ b/drivers/char/rio/parmmap.h
@@ -78,14 +78,9 @@
 	WORD idle_count;	/* Idle time counter */
 	WORD busy_count;	/* Busy counter */
 	WORD idle_control;	/* Control Idle Process */
-#if defined(HOST) || defined(INKERNEL)
 	WORD tx_intr;		/* TX interrupt pending */
 	WORD rx_intr;		/* RX interrupt pending */
 	WORD rup_intr;		/* RUP interrupt pending */
-#endif
-#if defined(RTA)
-	WORD dying_count;	/* Count of processes dead */
-#endif
 };
 
 #endif
diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h
index 3baebf8..2663ca0 100644
--- a/drivers/char/rio/phb.h
+++ b/drivers/char/rio/phb.h
@@ -44,17 +44,6 @@
 #endif
 
 
- /*************************************************
-  * Set the LIMIT values.
-  ************************************************/
-#ifdef RTA
-#define RX_LIMIT       (ushort) 3
-#endif
-#ifdef HOST
-#define RX_LIMIT       (ushort) 1
-#endif
-
-
 /*************************************************
  * Handshake asserted. Deasserted by the LTT(s)
  ************************************************/
@@ -69,11 +58,7 @@
 /*************************************************
  * Maximum number of PHB's
  ************************************************/
-#if defined (HOST) || defined (INKERNEL)
 #define MAX_PHB               ((ushort) 128)	/* range 0-127 */
-#else
-#define MAX_PHB               ((ushort) 8)	/* range 0-7 */
-#endif
 
 /*************************************************
  * Defines for the mode fields
@@ -139,141 +124,23 @@
  * the start. The pointer tx_add points to a SPACE to put a Packet.
  * The pointer tx_remove points to the next Packet to remove
  *************************************************************************/
-#ifndef INKERNEL
-#define src_unit     u2.s2.unit
-#define src_port     u2.s2.port
-#define dest_unit    u1.s1.unit
-#define dest_port    u1.s1.port
-#endif
-#ifdef HOST
-#define tx_start     u3.s1.tx_start_ptr_ptr
-#define tx_add       u3.s1.tx_add_ptr_ptr
-#define tx_end       u3.s1.tx_end_ptr_ptr
-#define tx_remove    u3.s1.tx_remove_ptr_ptr
-#define rx_start     u4.s1.rx_start_ptr_ptr
-#define rx_add       u4.s1.rx_add_ptr_ptr
-#define rx_end       u4.s1.rx_end_ptr_ptr
-#define rx_remove    u4.s1.rx_remove_ptr_ptr
-#endif
 typedef struct PHB PHB;
 struct PHB {
-#ifdef RTA
-	ushort port;
-#endif
-#ifdef INKERNEL
 	WORD source;
-#else
-	union {
-		ushort source;	/* Complete source */
-		struct {
-			unsigned char unit;	/* Source unit */
-			unsigned char port;	/* Source port */
-		} s2;
-	} u2;
-#endif
 	WORD handshake;
 	WORD status;
 	NUMBER timeout;		/* Maximum of 1.9 seconds */
 	WORD link;		/* Send down this link */
-#ifdef INKERNEL
 	WORD destination;
-#else
-	union {
-		ushort destination;	/* Complete destination */
-		struct {
-			unsigned char unit;	/* Destination unit */
-			unsigned char port;	/* Destination port */
-		} s1;
-	} u1;
-#endif
-#ifdef RTA
-	ushort tx_pkts_added;
-	ushort tx_pkts_removed;
-	Q_BUF_ptr tx_q_start;	/* Start of the Q list chain */
-	short num_tx_q_bufs;	/* Number of Q buffers in the chain */
-	PKT_ptr_ptr tx_add;	/* Add a new Packet here */
-	Q_BUF_ptr tx_add_qb;	/* Pointer to the add Q buf */
-	PKT_ptr_ptr tx_add_st_qbb;	/* Pointer to start of the Q's buf */
-	PKT_ptr_ptr tx_add_end_qbb;	/* Pointer to the end of the Q's buf */
-	PKT_ptr_ptr tx_remove;	/* Remove a Packet here */
-	Q_BUF_ptr tx_remove_qb;	/* Pointer to the remove Q buf */
-	PKT_ptr_ptr tx_remove_st_qbb;	/* Pointer to the start of the Q buf */
-	PKT_ptr_ptr tx_remove_end_qbb;	/* Pointer to the end of the Q buf */
-#endif
-#ifdef INKERNEL
 	PKT_ptr_ptr tx_start;
 	PKT_ptr_ptr tx_end;
 	PKT_ptr_ptr tx_add;
 	PKT_ptr_ptr tx_remove;
-#endif
-#ifdef HOST
-	union {
-		struct {
-			PKT_ptr_ptr tx_start_ptr_ptr;
-			PKT_ptr_ptr tx_end_ptr_ptr;
-			PKT_ptr_ptr tx_add_ptr_ptr;
-			PKT_ptr_ptr tx_remove_ptr_ptr;
-		} s1;
-		struct {
-			ushort *tx_start_ptr;
-			ushort *tx_end_ptr;
-			ushort *tx_add_ptr;
-			ushort *tx_remove_ptr;
-		} s2;
-	} u3;
-#endif
 
-#ifdef  RTA
-	ushort rx_pkts_added;
-	ushort rx_pkts_removed;
-	Q_BUF_ptr rx_q_start;	/* Start of the Q list chain */
-	short num_rx_q_bufs;	/* Number of Q buffers in the chain */
-	PKT_ptr_ptr rx_add;	/* Add a new Packet here */
-	Q_BUF_ptr rx_add_qb;	/* Pointer to the add Q buf */
-	PKT_ptr_ptr rx_add_st_qbb;	/* Pointer to start of the Q's buf */
-	PKT_ptr_ptr rx_add_end_qbb;	/* Pointer to the end of the Q's buf */
-	PKT_ptr_ptr rx_remove;	/* Remove a Packet here */
-	Q_BUF_ptr rx_remove_qb;	/* Pointer to the remove Q buf */
-	PKT_ptr_ptr rx_remove_st_qbb;	/* Pointer to the start of the Q buf */
-	PKT_ptr_ptr rx_remove_end_qbb;	/* Pointer to the end of the Q buf */
-#endif
-#ifdef INKERNEL
 	PKT_ptr_ptr rx_start;
 	PKT_ptr_ptr rx_end;
 	PKT_ptr_ptr rx_add;
 	PKT_ptr_ptr rx_remove;
-#endif
-#ifdef HOST
-	union {
-		struct {
-			PKT_ptr_ptr rx_start_ptr_ptr;
-			PKT_ptr_ptr rx_end_ptr_ptr;
-			PKT_ptr_ptr rx_add_ptr_ptr;
-			PKT_ptr_ptr rx_remove_ptr_ptr;
-		} s1;
-		struct {
-			ushort *rx_start_ptr;
-			ushort *rx_end_ptr;
-			ushort *rx_add_ptr;
-			ushort *rx_remove_ptr;
-		} s2;
-	} u4;
-#endif
-
-#ifdef RTA			/* some fields for the remotes */
-	ushort flush_count;	/* Count of write flushes */
-	ushort txmode;		/* Modes for tx */
-	ushort rxmode;		/* Modes for rx */
-	ushort portmode;	/* Generic modes */
-	ushort column;		/* TAB3 column count */
-	ushort tx_subscript;	/* (TX) Subscript into data field */
-	ushort rx_subscript;	/* (RX) Subscript into data field */
-	PKT_ptr rx_incomplete;	/* Hold an incomplete packet here */
-	ushort modem_bits;	/* Modem bits to mask */
-	ushort lastModem;	/* Modem control lines. */
-	ushort addr;		/* Address for sub commands */
-	ushort MonitorTstate;	/* TRUE if monitoring tstop */
-#endif
 
 };
 
diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h
index 882fd42..7011e52 100644
--- a/drivers/char/rio/pkt.h
+++ b/drivers/char/rio/pkt.h
@@ -70,39 +70,12 @@
 #define CONTROL_DATA_WNDW  (DATA_WNDW << 8)
 
 struct PKT {
-#ifdef INKERNEL
 	BYTE dest_unit;		/* Destination Unit Id */
 	BYTE dest_port;		/* Destination POrt */
 	BYTE src_unit;		/* Source Unit Id */
 	BYTE src_port;		/* Source POrt */
-#else
-	union {
-		ushort destination;	/* Complete destination */
-		struct {
-			unsigned char unit;	/* Destination unit */
-			unsigned char port;	/* Destination port */
-		} s1;
-	} u1;
-	union {
-		ushort source;	/* Complete source */
-		struct {
-			unsigned char unit;	/* Source unit */
-			unsigned char port;	/* Source port */
-		} s2;
-	} u2;
-#endif
-#ifdef INKERNEL
 	BYTE len;
 	BYTE control;
-#else
-	union {
-		ushort control;
-		struct {
-			unsigned char len;
-			unsigned char control;
-		} s3;
-	} u3;
-#endif
 	BYTE data[PKT_MAX_DATA_LEN];
 	/* Actual data :-) */
 	WORD csum;		/* C-SUM */
diff --git a/drivers/char/rio/qbuf.h b/drivers/char/rio/qbuf.h
index acd9e8e..391ffc3 100644
--- a/drivers/char/rio/qbuf.h
+++ b/drivers/char/rio/qbuf.h
@@ -46,11 +46,7 @@
 
 
 
-#ifdef HOST
-#define PKTS_PER_BUFFER    1
-#else
 #define PKTS_PER_BUFFER    (220 / PKT_LENGTH)
-#endif
 
 typedef struct Q_BUF Q_BUF;
 struct Q_BUF {
diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h
index 9b67e24..46084d5 100644
--- a/drivers/char/rio/riotypes.h
+++ b/drivers/char/rio/riotypes.h
@@ -43,9 +43,6 @@
 #endif
 #endif
 
-#ifdef INKERNEL
-
-#if !defined(MIPSAT)
 typedef unsigned short NUMBER_ptr;
 typedef unsigned short WORD_ptr;
 typedef unsigned short BYTE_ptr;
@@ -65,69 +62,6 @@
 typedef unsigned short short_ptr;
 typedef unsigned short u_short_ptr;
 typedef unsigned short ushort_ptr;
-#else
-/* MIPSAT types */
-typedef char RIO_POINTER[8];
-typedef RIO_POINTER NUMBER_ptr;
-typedef RIO_POINTER WORD_ptr;
-typedef RIO_POINTER BYTE_ptr;
-typedef RIO_POINTER char_ptr;
-typedef RIO_POINTER Channel_ptr;
-typedef RIO_POINTER FREE_LIST_ptr_ptr;
-typedef RIO_POINTER FREE_LIST_ptr;
-typedef RIO_POINTER LPB_ptr;
-typedef RIO_POINTER Process_ptr;
-typedef RIO_POINTER PHB_ptr;
-typedef RIO_POINTER PKT_ptr;
-typedef RIO_POINTER PKT_ptr_ptr;
-typedef RIO_POINTER Q_BUF_ptr;
-typedef RIO_POINTER Q_BUF_ptr_ptr;
-typedef RIO_POINTER ROUTE_STR_ptr;
-typedef RIO_POINTER RUP_ptr;
-typedef RIO_POINTER short_ptr;
-typedef RIO_POINTER u_short_ptr;
-typedef RIO_POINTER ushort_ptr;
-#endif
-
-#else				/* not INKERNEL */
-typedef unsigned char BYTE;
-typedef unsigned short WORD;
-typedef unsigned long DWORD;
-typedef short NUMBER;
-typedef short *NUMBER_ptr;
-typedef unsigned short *WORD_ptr;
-typedef unsigned char *BYTE_ptr;
-typedef unsigned char uchar;
-typedef unsigned short ushort;
-typedef unsigned int uint;
-typedef unsigned long ulong;
-typedef unsigned char u_char;
-typedef unsigned short u_short;
-typedef unsigned int u_int;
-typedef unsigned long u_long;
-typedef unsigned short ERROR;
-typedef unsigned long ID;
-typedef char *char_ptr;
-typedef Channel *Channel_ptr;
-typedef struct FREE_LIST *FREE_LIST_ptr;
-typedef struct FREE_LIST **FREE_LIST_ptr_ptr;
-typedef struct LPB *LPB_ptr;
-typedef struct Process *Process_ptr;
-typedef struct PHB *PHB_ptr;
-typedef struct PKT *PKT_ptr;
-typedef struct PKT **PKT_ptr_ptr;
-typedef struct Q_BUF *Q_BUF_ptr;
-typedef struct Q_BUF **Q_BUF_ptr_ptr;
-typedef struct ROUTE_STR *ROUTE_STR_ptr;
-typedef struct RUP *RUP_ptr;
-typedef short *short_ptr;
-typedef u_short *u_short_ptr;
-typedef ushort *ushort_ptr;
-typedef struct PKT PKT;
-typedef struct LPB LPB;
-typedef struct RUP RUP;
-#endif
-
 
 #endif				/* __riotypes__ */
 
diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h
index 8d44fec..f74f67c 100644
--- a/drivers/char/rio/rup.h
+++ b/drivers/char/rio/rup.h
@@ -43,12 +43,7 @@
 #endif
 #endif
 
-#if defined( HOST ) || defined( INKERNEL )
 #define MAX_RUP          ((short) 16)
-#endif
-#ifdef RTA
-#define MAX_RUP          ((short) 1)
-#endif
 
 #define PKTS_PER_RUP     ((short) 2)	/* They are always used in pairs */
 
diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h
index 3149405..6f754e1 100644
--- a/drivers/char/rio/sam.h
+++ b/drivers/char/rio/sam.h
@@ -43,10 +43,6 @@
 #endif
 
 
-#if !defined( HOST ) && !defined( INKERNEL )
-#define RTA 1
-#endif
-
 #define NUM_FREE_LIST_UNITS     500
 
 #ifndef FALSE
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 0949dce..7edc6a4 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -433,7 +433,7 @@
 		count += ToRecv;
 	}
 	/*  Push the data up to the tty layer */
-	ld->receive_buf(tty, cbuf, fbuf, count);
+	ld->receive_buf(tty, chead, fhead, count);
 done:
 	tty_ldisc_deref(ld);
 }
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 80a5b84..fee68cc 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -103,6 +103,7 @@
 
 #include <linux/serial.h>
 #include <linux/generic_serial.h>
+#include <linux/tty_flip.h>
 
 #include "ser_a2232.h"
 #include "ser_a2232fw.h"
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 64bf89c..c2490e2 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -931,7 +931,7 @@
 	case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break;
 	case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break;
 	default:
-		printk (KERN_INFO "sx: Invalid wordsize: %d\n", CFLAG & CSIZE);
+		printk (KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
 		break;
 	}
 
@@ -958,7 +958,7 @@
 	} else {
 		set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
 	}
-	sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ", 
+	sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
 	            port->gs.tty->termios->c_iflag, 
 	            I_OTHER(port->gs.tty));
 
@@ -973,7 +973,7 @@
 	} else {
 		clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
 	}
-	sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", 
+	sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
 	            port->gs.tty->termios->c_oflag, 
 	            O_OTHER(port->gs.tty));
 	/* port->c_dcd = sx_get_CD (port); */
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 07c9be6..a85a60a 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -2630,7 +2630,7 @@
 static int set_interface(struct slgt_info *info, int if_mode)
 {
  	unsigned long flags;
-	unsigned char val;
+	unsigned short val;
 
 	DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode));
 	spin_lock_irqsave(&info->lock,flags);
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 41a94bc..eb2eb3e 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -250,12 +250,17 @@
 {
 	unsigned int minor = iminor(inode) - TIPAR_MINOR;
 
-	if (minor > tp_count - 1)
+	if (tp_count == 0 || minor > tp_count - 1)
 		return -ENXIO;
 
 	if (test_and_set_bit(minor, &opened))
 		return -EBUSY;
 
+	if (!table[minor].dev) {
+		printk(KERN_ERR "%s: NULL device for minor %u\n",
+				__FUNCTION__, minor);
+		return -ENXIO;
+	}
 	parport_claim_or_block(table[minor].dev);
 	init_ti_parallel(minor);
 	parport_release(table[minor].dev);
@@ -510,16 +515,20 @@
 		err = PTR_ERR(tipar_class);
 		goto out_chrdev;
 	}
-	if (parport_register_driver(&tipar_driver)) {
+	if (parport_register_driver(&tipar_driver) || tp_count == 0) {
 		printk(KERN_ERR "tipar: unable to register with parport\n");
 		err = -EIO;
-		goto out;
+		goto out_class;
 	}
 
 	err = 0;
 	goto out;
 
+out_class:
+	class_destroy(tipar_class);
+
 out_chrdev:
+	devfs_remove("ticables/par");
 	unregister_chrdev(TIPAR_MAJOR, "tipar");
 out:
 	return err;	
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index bc56df8a..4c27218 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -34,7 +34,6 @@
 #include <linux/kernel.h>	/* printk() */
 #include <linux/fs.h>		/* everything... */
 #include <linux/errno.h>	/* error codes */
-#include <linux/delay.h>	/* udelay */
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
@@ -156,6 +155,8 @@
 documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4.
 alarms				:
 current_ref			:
+received_ref_clk3a		:
+received_ref_clk3b		:
 enable_clk3a_output		:
 enable_clk3b_output		:
 enable_clka0_output		:
@@ -165,7 +166,7 @@
 filter_select			:
 hardware_switching		:
 hardware_switching_mode		:
-interrupt_switch		:
+telclock_version		:
 mode_select			:
 refalign			:
 reset				:
@@ -173,7 +174,6 @@
 select_amcb2_transmit_clock	:
 select_redundant_clock		:
 select_ref_frequency		:
-test_mode			:
 
 All sysfs interfaces are integers in hex format, i.e echo 99 > refalign
 has the same effect as echo 0x99 > refalign.
@@ -226,7 +226,7 @@
 	return 0;
 }
 
-ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
+static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
 		loff_t *f_pos)
 {
 	if (count < sizeof(struct tlclk_alarms))
@@ -242,7 +242,7 @@
 	return  sizeof(struct tlclk_alarms);
 }
 
-ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
+static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
 	    loff_t *f_pos)
 {
 	return 0;
@@ -278,21 +278,21 @@
 static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
 
 
-static ssize_t show_interrupt_switch(struct device *d,
+static ssize_t show_telclock_version(struct device *d,
 		struct device_attribute *attr, char *buf)
 {
 	unsigned long ret_val;
 	unsigned long flags;
 
 	spin_lock_irqsave(&event_lock, flags);
-	ret_val = inb(TLCLK_REG6);
+	ret_val = inb(TLCLK_REG5);
 	spin_unlock_irqrestore(&event_lock, flags);
 
 	return sprintf(buf, "0x%lX\n", ret_val);
 }
 
-static DEVICE_ATTR(interrupt_switch, S_IRUGO,
-		show_interrupt_switch, NULL);
+static DEVICE_ATTR(telclock_version, S_IRUGO,
+		show_telclock_version, NULL);
 
 static ssize_t show_alarms(struct device *d,
 		struct device_attribute *attr,  char *buf)
@@ -309,6 +309,50 @@
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static ssize_t store_received_ref_clk3a(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, ": tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG1, 0xef, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL,
+		store_received_ref_clk3a);
+
+
+static ssize_t store_received_ref_clk3b(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, ": tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG1, 0xef, val << 1);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL,
+		store_received_ref_clk3b);
+
+
 static ssize_t store_enable_clk3b_output(struct device *d,
 		 struct device_attribute *attr, const char *buf, size_t count)
 {
@@ -436,26 +480,6 @@
 static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL,
 		store_enable_clka0_output);
 
-static ssize_t store_test_mode(struct device *d,
-		struct device_attribute *attr,  const char *buf, size_t count)
-{
-	unsigned long flags;
-	unsigned long tmp;
-	unsigned char val;
-
-	sscanf(buf, "%lX", &tmp);
-	dev_dbg(d, "tmp = 0x%lX\n", tmp);
-
-	val = (unsigned char)tmp;
-	spin_lock_irqsave(&event_lock, flags);
-	SET_PORT_BITS(TLCLK_REG4, 0xfd, 2);
-	spin_unlock_irqrestore(&event_lock, flags);
-
-	return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(test_mode, S_IWUGO, NULL, store_test_mode);
-
 static ssize_t store_select_amcb2_transmit_clock(struct device *d,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
@@ -475,7 +499,7 @@
 			SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
 			switch (val) {
 			case CLK_8_592MHz:
-				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
 				break;
 			case CLK_11_184MHz:
 				SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
@@ -484,7 +508,7 @@
 				SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
 				break;
 			case CLK_44_736MHz:
-				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
 				break;
 			}
 		} else
@@ -653,9 +677,7 @@
 	dev_dbg(d, "tmp = 0x%lX\n", tmp);
 	spin_lock_irqsave(&event_lock, flags);
 	SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
-	udelay(2);
 	SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
-	udelay(2);
 	SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
 	spin_unlock_irqrestore(&event_lock, flags);
 
@@ -706,15 +728,16 @@
 
 static struct attribute *tlclk_sysfs_entries[] = {
 	&dev_attr_current_ref.attr,
-	&dev_attr_interrupt_switch.attr,
+	&dev_attr_telclock_version.attr,
 	&dev_attr_alarms.attr,
+	&dev_attr_received_ref_clk3a.attr,
+	&dev_attr_received_ref_clk3b.attr,
 	&dev_attr_enable_clk3a_output.attr,
 	&dev_attr_enable_clk3b_output.attr,
 	&dev_attr_enable_clkb1_output.attr,
 	&dev_attr_enable_clka1_output.attr,
 	&dev_attr_enable_clkb0_output.attr,
 	&dev_attr_enable_clka0_output.attr,
-	&dev_attr_test_mode.attr,
 	&dev_attr_select_amcb1_transmit_clock.attr,
 	&dev_attr_select_amcb2_transmit_clock.attr,
 	&dev_attr_select_redundant_clock.attr,
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
index aedf7a8..537aa45 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_bios.c
@@ -191,7 +191,7 @@
 	const char *name = "";
 	char data[40] = "";
 	int i, n_len = 0, d_len = 0;
-	u32 event_id, event_data_size;
+	u32 event_id;
 
 	switch(event->event_type) {
 	case PREBOOT:
@@ -220,8 +220,7 @@
 		}
 		break;
 	case EVENT_TAG:
-		event_id = be32_to_cpu(event_entry);
-		event_data_size = be32_to_cpu(&event_entry[4]);
+		event_id = be32_to_cpu(*((u32 *)event_entry));
 
 		/* ToDo Row data -> Base64 */
 
@@ -376,7 +375,7 @@
 {
 	struct acpi_tcpa *buff;
 	acpi_status status;
-	void *virt;
+	struct acpi_table_header *virt;
 
 	if (log->bios_event_log != NULL) {
 		printk(KERN_ERR
@@ -413,7 +412,7 @@
 
 	log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
 
-	acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, &virt);
+	acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt);
 
 	memcpy(log->bios_event_log, virt, buff->log_max_len);
 
@@ -487,26 +486,35 @@
 	.release = tpm_bios_measurements_release,
 };
 
+static int is_bad(void *p)
+{
+	if (!p)
+		return 1;
+	if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
+		return 1;
+	return 0;
+}
+
 struct dentry **tpm_bios_log_setup(char *name)
 {
 	struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
 
 	tpm_dir = securityfs_create_dir(name, NULL);
-	if (!tpm_dir)
+	if (is_bad(tpm_dir))
 		goto out;
 
 	bin_file =
 	    securityfs_create_file("binary_bios_measurements",
 				   S_IRUSR | S_IRGRP, tpm_dir, NULL,
 				   &tpm_binary_bios_measurements_ops);
-	if (!bin_file)
+	if (is_bad(bin_file))
 		goto out_tpm;
 
 	ascii_file =
 	    securityfs_create_file("ascii_bios_measurements",
 				   S_IRUSR | S_IRGRP, tpm_dir, NULL,
 				   &tpm_ascii_bios_measurements_ops);
-	if (!ascii_file)
+	if (is_bad(ascii_file))
 		goto out_bin;
 
 	ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
@@ -538,3 +546,4 @@
 		securityfs_remove(lst[i]);
 }
 EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 8198dbb..ec75909 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -441,7 +441,7 @@
 
 		if ((ioh << 8 | iol) != tpm_inf.base) {
 			dev_err(&dev->dev,
-				"Could not set IO-ports to %04x\n",
+				"Could not set IO-ports to 0x%lx\n",
 				tpm_inf.base);
 			release_region(tpm_inf.base, TPM_INF_PORT_LEN);
 			return -EIO;
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index eb8b5be..a23816d 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -253,6 +253,7 @@
 
 static void tty_buffer_init(struct tty_struct *tty)
 {
+	spin_lock_init(&tty->buf.lock);
 	tty->buf.head = NULL;
 	tty->buf.tail = NULL;
 	tty->buf.free = NULL;
@@ -266,6 +267,9 @@
 	p->used = 0;
 	p->size = size;
 	p->next = NULL;
+	p->active = 0;
+	p->commit = 0;
+	p->read = 0;
 	p->char_buf_ptr = (char *)(p->data);
 	p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
 /* 	printk("Flip create %p\n", p); */
@@ -296,6 +300,8 @@
 			*tbh = t->next;
 			t->next = NULL;
 			t->used = 0;
+			t->commit = 0;
+			t->read = 0;
 			/* DEBUG ONLY */
 			memset(t->data, '*', size);
 /* 			printk("Flip recycle %p\n", t); */
@@ -312,25 +318,37 @@
 
 int tty_buffer_request_room(struct tty_struct *tty, size_t size)
 {
-	struct tty_buffer *b = tty->buf.tail, *n;
-	int left = 0;
+	struct tty_buffer *b, *n;
+	int left;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tty->buf.lock, flags);
 
 	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
 	   remove this conditional if its worth it. This would be invisible
 	   to the callers */
-	if(b != NULL)
+	if ((b = tty->buf.tail) != NULL) {
 		left = b->size - b->used;
-	if(left >= size)
-		return size;
-	/* This is the slow path - looking for new buffers to use */
-	n = tty_buffer_find(tty, size);
-	if(n == NULL)
-		return left;
-	if(b != NULL)
-		b->next = n;
-	else
-		tty->buf.head = n;
-	tty->buf.tail = n;
+		b->active = 1;
+	} else
+		left = 0;
+
+	if (left < size) {
+		/* This is the slow path - looking for new buffers to use */
+		if ((n = tty_buffer_find(tty, size)) != NULL) {
+			if (b != NULL) {
+				b->next = n;
+				b->active = 0;
+				b->commit = b->used;
+			} else
+				tty->buf.head = n;
+			tty->buf.tail = n;
+			n->active = 1;
+		} else
+			size = left;
+	}
+
+	spin_unlock_irqrestore(&tty->buf.lock, flags);
 	return size;
 }
 
@@ -396,10 +414,12 @@
 int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
 {
 	int space = tty_buffer_request_room(tty, size);
-	struct tty_buffer *tb = tty->buf.tail;
-	*chars = tb->char_buf_ptr + tb->used;
-	memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
-	tb->used += space;
+	if (likely(space)) {
+		struct tty_buffer *tb = tty->buf.tail;
+		*chars = tb->char_buf_ptr + tb->used;
+		memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+		tb->used += space;
+	}
 	return space;
 }
 
@@ -416,10 +436,12 @@
 int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
 {
 	int space = tty_buffer_request_room(tty, size);
-	struct tty_buffer *tb = tty->buf.tail;
-	*chars = tb->char_buf_ptr + tb->used;
-	*flags = tb->flag_buf_ptr + tb->used;
-	tb->used += space;
+	if (likely(space)) {
+		struct tty_buffer *tb = tty->buf.tail;
+		*chars = tb->char_buf_ptr + tb->used;
+		*flags = tb->flag_buf_ptr + tb->used;
+		tb->used += space;
+	}
 	return space;
 }
 
@@ -2735,6 +2757,9 @@
 	unsigned long 	flags;
 	struct tty_ldisc *disc;
 	struct tty_buffer *tbuf;
+	int count;
+	char *char_buf;
+	unsigned char *flag_buf;
 
 	disc = tty_ldisc_ref(tty);
 	if (disc == NULL)	/*  !TTY_LDISC */
@@ -2747,20 +2772,24 @@
 		schedule_delayed_work(&tty->buf.work, 1);
 		goto out;
 	}
-	spin_lock_irqsave(&tty->read_lock, flags);
+	spin_lock_irqsave(&tty->buf.lock, flags);
 	while((tbuf = tty->buf.head) != NULL) {
+		while ((count = tbuf->commit - tbuf->read) != 0) {
+			char_buf = tbuf->char_buf_ptr + tbuf->read;
+			flag_buf = tbuf->flag_buf_ptr + tbuf->read;
+			tbuf->read += count;
+			spin_unlock_irqrestore(&tty->buf.lock, flags);
+			disc->receive_buf(tty, char_buf, flag_buf, count);
+			spin_lock_irqsave(&tty->buf.lock, flags);
+		}
+		if (tbuf->active)
+			break;
 		tty->buf.head = tbuf->next;
 		if (tty->buf.head == NULL)
 			tty->buf.tail = NULL;
-		spin_unlock_irqrestore(&tty->read_lock, flags);
-		/* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */
-		disc->receive_buf(tty, tbuf->char_buf_ptr,
-				       tbuf->flag_buf_ptr,
-				       tbuf->used);
-		spin_lock_irqsave(&tty->read_lock, flags);
 		tty_buffer_free(tty, tbuf);
 	}
-	spin_unlock_irqrestore(&tty->read_lock, flags);
+	spin_unlock_irqrestore(&tty->buf.lock, flags);
 out:
 	tty_ldisc_deref(disc);
 }
@@ -2852,6 +2881,14 @@
 
 void tty_flip_buffer_push(struct tty_struct *tty)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&tty->buf.lock, flags);
+	if (tty->buf.tail != NULL) {
+		tty->buf.tail->active = 0;
+		tty->buf.tail->commit = tty->buf.tail->used;
+	}
+	spin_unlock_irqrestore(&tty->buf.lock, flags);
+
 	if (tty->low_latency)
 		flush_to_ldisc((void *) tty);
 	else
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index f1d9cb7..0900d1d 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -3213,6 +3213,7 @@
 
 void putconsxy(struct vc_data *vc, unsigned char *p)
 {
+	hide_cursor(vc);
 	gotoxy(vc, p[0], p[1]);
 	set_cursor(vc);
 }
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 37c9e13..8d6b249 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -49,29 +49,37 @@
  *	More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
  */
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/config.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/reboot.h>
+#include <linux/config.h>	/* For CONFIG_WATCHDOG_NOWAYOUT/... */
+#include <linux/module.h>	/* For module specific items */
+#include <linux/moduleparam.h>	/* For new moduleparam's */
+#include <linux/types.h>	/* For standard types (like size_t) */
+#include <linux/errno.h>	/* For the -ENODEV/... values */
+#include <linux/kernel.h>	/* For printk/panic/... */
+#include <linux/delay.h>	/* For mdelay function */
+#include <linux/timer.h>	/* For timer related operations */
+#include <linux/jiffies.h>	/* For jiffies stuff */
+#include <linux/miscdevice.h>	/* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>	/* For the watchdog specific items */
+#include <linux/notifier.h>	/* For notifier support */
+#include <linux/reboot.h>	/* For reboot_notifier stuff */
+#include <linux/init.h>		/* For __init/__exit/... */
+#include <linux/fs.h>		/* For file operations */
+#include <linux/ioport.h>	/* For io-port access */
+#include <linux/spinlock.h>	/* For spin_lock/spin_unlock/... */
 #include <linux/sched.h>	/* TASK_INTERRUPTIBLE, set_current_state() and friends */
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/slab.h>		/* For kmalloc */
 
-#define WD_VER                  "1.16 (06/12/2004)"
-#define PFX			"pcwd: "
+#include <asm/uaccess.h>	/* For copy_to_user/put_user/... */
+#include <asm/io.h>		/* For inb/outb/... */
+
+/* Module and version information */
+#define WATCHDOG_VERSION "1.16"
+#define WATCHDOG_DATE "03 Jan 2006"
+#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
+#define WATCHDOG_NAME "pcwd"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n"
+#define WD_VER WATCHDOG_VERSION " (" WATCHDOG_DATE ")"
 
 /*
  * It should be noted that PCWD_REVISION_B was removed because A and B
@@ -85,36 +93,38 @@
 
 /*
  * These are the defines that describe the control status bits for the
- * PC Watchdog card, revision A.
- */
+ * PCI-PC Watchdog card.
+*/
+/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
 #define WD_WDRST                0x01	/* Previously reset state */
 #define WD_T110                 0x02	/* Temperature overheat sense */
 #define WD_HRTBT                0x04	/* Heartbeat sense */
 #define WD_RLY2                 0x08	/* External relay triggered */
 #define WD_SRLY2                0x80	/* Software external relay triggered */
-
-/*
- * These are the defines that describe the control status bits for the
- * PC Watchdog card, revision C.
- */
+/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
 #define WD_REVC_WTRP            0x01	/* Watchdog Trip status */
 #define WD_REVC_HRBT            0x02	/* Watchdog Heartbeat */
 #define WD_REVC_TTRP            0x04	/* Temperature Trip status */
+/* Port 2 : Control Status #2 */
+#define WD_WDIS			0x10	/* Watchdog Disabled */
+#define WD_ENTP			0x20	/* Watchdog Enable Temperature Trip */
+#define WD_SSEL			0x40	/* Watchdog Switch Select (1:SW1 <-> 0:SW2) */
+#define WD_WCMD			0x80	/* Watchdog Command Mode */
 
 /* max. time we give an ISA watchdog card to process a command */
 /* 500ms for each 4 bit response (according to spec.) */
 #define ISA_COMMAND_TIMEOUT     1000
 
 /* Watchdog's internal commands */
-#define CMD_ISA_IDLE                    0x00
-#define CMD_ISA_VERSION_INTEGER         0x01
-#define CMD_ISA_VERSION_TENTH           0x02
-#define CMD_ISA_VERSION_HUNDRETH        0x03
-#define CMD_ISA_VERSION_MINOR           0x04
-#define CMD_ISA_SWITCH_SETTINGS         0x05
-#define CMD_ISA_DELAY_TIME_2SECS        0x0A
-#define CMD_ISA_DELAY_TIME_4SECS        0x0B
-#define CMD_ISA_DELAY_TIME_8SECS        0x0C
+#define CMD_ISA_IDLE			0x00
+#define CMD_ISA_VERSION_INTEGER		0x01
+#define CMD_ISA_VERSION_TENTH		0x02
+#define CMD_ISA_VERSION_HUNDRETH	0x03
+#define CMD_ISA_VERSION_MINOR		0x04
+#define CMD_ISA_SWITCH_SETTINGS		0x05
+#define CMD_ISA_DELAY_TIME_2SECS	0x0A
+#define CMD_ISA_DELAY_TIME_4SECS	0x0B
+#define CMD_ISA_DELAY_TIME_8SECS	0x0C
 
 /*
  * We are using an kernel timer to do the pinging of the watchdog
@@ -130,15 +140,17 @@
 /* internal variables */
 static atomic_t open_allowed = ATOMIC_INIT(1);
 static char expect_close;
-static struct timer_list timer;
-static unsigned long next_heartbeat;
 static int temp_panic;
-static int revision;			/* The card's revision */
-static int supports_temp;		/* Wether or not the card has a temperature device */
-static int command_mode;		/* Wether or not the card is in command mode */
-static int initial_status;		/* The card's boot status */
-static int current_readport;		/* The cards I/O address */
-static spinlock_t io_lock;
+static struct {				/* this is private data for each ISA-PC watchdog card */
+	int revision;			/* The card's revision */
+	int supports_temp;		/* Wether or not the card has a temperature device */
+	int command_mode;		/* Wether or not the card is in command mode */
+	int boot_status;		/* The card's boot status */
+	int io_addr;			/* The cards I/O address */
+	spinlock_t io_lock;		/* the lock for io operations */
+	struct timer_list timer;	/* The timer that pings the watchdog */
+	unsigned long next_heartbeat;	/* the next_heartbeat for the timer */
+} pcwd_private;
 
 /* module parameters */
 #define WATCHDOG_HEARTBEAT 60		/* 60 sec default heartbeat */
@@ -161,14 +173,14 @@
 	int port0, last_port0;	/* Double read for stabilising */
 
 	/* The WCMD bit must be 1 and the command is only 4 bits in size */
-	control_status = (cmd & 0x0F) | 0x80;
-	outb_p(control_status, current_readport + 2);
+	control_status = (cmd & 0x0F) | WD_WCMD;
+	outb_p(control_status, pcwd_private.io_addr + 2);
 	udelay(ISA_COMMAND_TIMEOUT);
 
-	port0 = inb_p(current_readport);
+	port0 = inb_p(pcwd_private.io_addr);
 	for (i = 0; i < 25; ++i) {
 		last_port0 = port0;
-		port0 = inb_p(current_readport);
+		port0 = inb_p(pcwd_private.io_addr);
 
 		if (port0 == last_port0)
 			break;	/* Data is stable */
@@ -184,7 +196,7 @@
 	int i, found=0, count=0;
 
 	/* Set the card into command mode */
-	spin_lock(&io_lock);
+	spin_lock(&pcwd_private.io_lock);
 	while ((!found) && (count < 3)) {
 		i = send_isa_command(CMD_ISA_IDLE);
 
@@ -192,15 +204,15 @@
 			found = 1;
 		else if (i == 0xF3) {
 			/* Card does not like what we've done to it */
-			outb_p(0x00, current_readport + 2);
+			outb_p(0x00, pcwd_private.io_addr + 2);
 			udelay(1200);	/* Spec says wait 1ms */
-			outb_p(0x00, current_readport + 2);
+			outb_p(0x00, pcwd_private.io_addr + 2);
 			udelay(ISA_COMMAND_TIMEOUT);
 		}
 		count++;
 	}
-	spin_unlock(&io_lock);
-	command_mode = found;
+	spin_unlock(&pcwd_private.io_lock);
+	pcwd_private.command_mode = found;
 
 	return(found);
 }
@@ -208,12 +220,95 @@
 static void unset_command_mode(void)
 {
 	/* Set the card into normal mode */
-	spin_lock(&io_lock);
-	outb_p(0x00, current_readport + 2);
+	spin_lock(&pcwd_private.io_lock);
+	outb_p(0x00, pcwd_private.io_addr + 2);
 	udelay(ISA_COMMAND_TIMEOUT);
-	spin_unlock(&io_lock);
+	spin_unlock(&pcwd_private.io_lock);
 
-	command_mode = 0;
+	pcwd_private.command_mode = 0;
+}
+
+static inline void pcwd_check_temperature_support(void)
+{
+	if (inb(pcwd_private.io_addr) != 0xF0)
+		pcwd_private.supports_temp = 1;
+}
+
+static inline char *get_firmware(void)
+{
+	int one, ten, hund, minor;
+	char *ret;
+
+	ret = kmalloc(6, GFP_KERNEL);
+	if(ret == NULL)
+		return NULL;
+
+	if (set_command_mode()) {
+		one = send_isa_command(CMD_ISA_VERSION_INTEGER);
+		ten = send_isa_command(CMD_ISA_VERSION_TENTH);
+		hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
+		minor = send_isa_command(CMD_ISA_VERSION_MINOR);
+		sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
+	}
+	else
+		sprintf(ret, "ERROR");
+
+	unset_command_mode();
+	return(ret);
+}
+
+static inline int pcwd_get_option_switches(void)
+{
+	int option_switches=0;
+
+	if (set_command_mode()) {
+		/* Get switch settings */
+		option_switches = send_isa_command(CMD_ISA_SWITCH_SETTINGS);
+	}
+
+	unset_command_mode();
+	return(option_switches);
+}
+
+static void pcwd_show_card_info(void)
+{
+	char *firmware;
+	int option_switches;
+
+	/* Get some extra info from the hardware (in command/debug/diag mode) */
+	if (pcwd_private.revision == PCWD_REVISION_A)
+		printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr);
+	else if (pcwd_private.revision == PCWD_REVISION_C) {
+		firmware = get_firmware();
+		printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
+			pcwd_private.io_addr, firmware);
+		kfree(firmware);
+		option_switches = pcwd_get_option_switches();
+		printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
+			option_switches,
+			((option_switches & 0x10) ? "ON" : "OFF"),
+			((option_switches & 0x08) ? "ON" : "OFF"));
+
+		/* Reprogram internal heartbeat to 2 seconds */
+		if (set_command_mode()) {
+			send_isa_command(CMD_ISA_DELAY_TIME_2SECS);
+			unset_command_mode();
+		}
+	}
+
+	if (pcwd_private.supports_temp)
+		printk(KERN_INFO PFX "Temperature Option Detected\n");
+
+	if (pcwd_private.boot_status & WDIOF_CARDRESET)
+		printk(KERN_INFO PFX "Previous reboot was caused by the card\n");
+
+	if (pcwd_private.boot_status & WDIOF_OVERHEAT) {
+		printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n");
+		printk(KERN_EMERG PFX "CPU Overheat\n");
+	}
+
+	if (pcwd_private.boot_status == 0)
+		printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
 }
 
 static void pcwd_timer_ping(unsigned long data)
@@ -222,25 +317,25 @@
 
 	/* If we got a heartbeat pulse within the WDT_INTERVAL
 	 * we agree to ping the WDT */
-	if(time_before(jiffies, next_heartbeat)) {
+	if(time_before(jiffies, pcwd_private.next_heartbeat)) {
 		/* Ping the watchdog */
-		spin_lock(&io_lock);
-		if (revision == PCWD_REVISION_A) {
+		spin_lock(&pcwd_private.io_lock);
+		if (pcwd_private.revision == PCWD_REVISION_A) {
 			/*  Rev A cards are reset by setting the WD_WDRST bit in register 1 */
-			wdrst_stat = inb_p(current_readport);
+			wdrst_stat = inb_p(pcwd_private.io_addr);
 			wdrst_stat &= 0x0F;
 			wdrst_stat |= WD_WDRST;
 
-			outb_p(wdrst_stat, current_readport + 1);
+			outb_p(wdrst_stat, pcwd_private.io_addr + 1);
 		} else {
 			/* Re-trigger watchdog by writing to port 0 */
-			outb_p(0x00, current_readport);
+			outb_p(0x00, pcwd_private.io_addr);
 		}
 
 		/* Re-set the timer interval */
-		mod_timer(&timer, jiffies + WDT_INTERVAL);
+		mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
 
-		spin_unlock(&io_lock);
+		spin_unlock(&pcwd_private.io_lock);
 	} else {
 		printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
 	}
@@ -250,19 +345,19 @@
 {
 	int stat_reg;
 
-	next_heartbeat = jiffies + (heartbeat * HZ);
+	pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
 
 	/* Start the timer */
-	mod_timer(&timer, jiffies + WDT_INTERVAL);
+	mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
 
 	/* Enable the port */
-	if (revision == PCWD_REVISION_C) {
-		spin_lock(&io_lock);
-		outb_p(0x00, current_readport + 3);
+	if (pcwd_private.revision == PCWD_REVISION_C) {
+		spin_lock(&pcwd_private.io_lock);
+		outb_p(0x00, pcwd_private.io_addr + 3);
 		udelay(ISA_COMMAND_TIMEOUT);
-		stat_reg = inb_p(current_readport + 2);
-		spin_unlock(&io_lock);
-		if (stat_reg & 0x10) {
+		stat_reg = inb_p(pcwd_private.io_addr + 2);
+		spin_unlock(&pcwd_private.io_lock);
+		if (stat_reg & WD_WDIS) {
 			printk(KERN_INFO PFX "Could not start watchdog\n");
 			return -EIO;
 		}
@@ -275,18 +370,18 @@
 	int stat_reg;
 
 	/* Stop the timer */
-	del_timer(&timer);
+	del_timer(&pcwd_private.timer);
 
 	/*  Disable the board  */
-	if (revision == PCWD_REVISION_C) {
-		spin_lock(&io_lock);
-		outb_p(0xA5, current_readport + 3);
+	if (pcwd_private.revision == PCWD_REVISION_C) {
+		spin_lock(&pcwd_private.io_lock);
+		outb_p(0xA5, pcwd_private.io_addr + 3);
 		udelay(ISA_COMMAND_TIMEOUT);
-		outb_p(0xA5, current_readport + 3);
+		outb_p(0xA5, pcwd_private.io_addr + 3);
 		udelay(ISA_COMMAND_TIMEOUT);
-		stat_reg = inb_p(current_readport + 2);
-		spin_unlock(&io_lock);
-		if ((stat_reg & 0x10) == 0) {
+		stat_reg = inb_p(pcwd_private.io_addr + 2);
+		spin_unlock(&pcwd_private.io_lock);
+		if ((stat_reg & WD_WDIS) == 0) {
 			printk(KERN_INFO PFX "Could not stop watchdog\n");
 			return -EIO;
 		}
@@ -297,7 +392,7 @@
 static int pcwd_keepalive(void)
 {
 	/* user land ping */
-	next_heartbeat = jiffies + (heartbeat * HZ);
+	pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
 	return 0;
 }
 
@@ -315,23 +410,23 @@
 	int card_status;
 
 	*status=0;
-	spin_lock(&io_lock);
-	if (revision == PCWD_REVISION_A)
+	spin_lock(&pcwd_private.io_lock);
+	if (pcwd_private.revision == PCWD_REVISION_A)
 		/* Rev A cards return status information from
 		 * the base register, which is used for the
 		 * temperature in other cards. */
-		card_status = inb(current_readport);
+		card_status = inb(pcwd_private.io_addr);
 	else {
 		/* Rev C cards return card status in the base
 		 * address + 1 register. And use different bits
 		 * to indicate a card initiated reset, and an
 		 * over-temperature condition. And the reboot
 		 * status can be reset. */
-		card_status = inb(current_readport + 1);
+		card_status = inb(pcwd_private.io_addr + 1);
 	}
-	spin_unlock(&io_lock);
+	spin_unlock(&pcwd_private.io_lock);
 
-	if (revision == PCWD_REVISION_A) {
+	if (pcwd_private.revision == PCWD_REVISION_A) {
 		if (card_status & WD_WDRST)
 			*status |= WDIOF_CARDRESET;
 
@@ -360,10 +455,10 @@
 
 static int pcwd_clear_status(void)
 {
-	if (revision == PCWD_REVISION_C) {
-		spin_lock(&io_lock);
-		outb_p(0x00, current_readport + 1); /* clear reset status */
-		spin_unlock(&io_lock);
+	if (pcwd_private.revision == PCWD_REVISION_C) {
+		spin_lock(&pcwd_private.io_lock);
+		outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */
+		spin_unlock(&pcwd_private.io_lock);
 	}
 	return 0;
 }
@@ -371,20 +466,20 @@
 static int pcwd_get_temperature(int *temperature)
 {
 	/* check that port 0 gives temperature info and no command results */
-	if (command_mode)
+	if (pcwd_private.command_mode)
 		return -1;
 
 	*temperature = 0;
-	if (!supports_temp)
+	if (!pcwd_private.supports_temp)
 		return -ENODEV;
 
 	/*
 	 * Convert celsius to fahrenheit, since this was
 	 * the decided 'standard' for this return value.
 	 */
-	spin_lock(&io_lock);
-	*temperature = ((inb(current_readport)) * 9 / 5) + 32;
-	spin_unlock(&io_lock);
+	spin_lock(&pcwd_private.io_lock);
+	*temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32;
+	spin_unlock(&pcwd_private.io_lock);
 
 	return 0;
 }
@@ -425,7 +520,7 @@
 		return put_user(status, argp);
 
 	case WDIOC_GETBOOTSTATUS:
-		return put_user(initial_status, argp);
+		return put_user(pcwd_private.boot_status, argp);
 
 	case WDIOC_GETTEMP:
 		if (pcwd_get_temperature(&temperature))
@@ -434,7 +529,7 @@
 		return put_user(temperature, argp);
 
 	case WDIOC_SETOPTIONS:
-		if (revision == PCWD_REVISION_C)
+		if (pcwd_private.revision == PCWD_REVISION_C)
 		{
 			if(copy_from_user(&rv, argp, sizeof(int)))
 				return -EFAULT;
@@ -550,7 +645,7 @@
 
 static int pcwd_temp_open(struct inode *inode, struct file *file)
 {
-	if (!supports_temp)
+	if (!pcwd_private.supports_temp)
 		return -ENODEV;
 
 	return nonseekable_open(inode, file);
@@ -616,68 +711,24 @@
  *	Init & exit routines
  */
 
-static inline void get_support(void)
-{
-	if (inb(current_readport) != 0xF0)
-		supports_temp = 1;
-}
-
 static inline int get_revision(void)
 {
 	int r = PCWD_REVISION_C;
 
-	spin_lock(&io_lock);
+	spin_lock(&pcwd_private.io_lock);
 	/* REV A cards use only 2 io ports; test
 	 * presumes a floating bus reads as 0xff. */
-	if ((inb(current_readport + 2) == 0xFF) ||
-	    (inb(current_readport + 3) == 0xFF))
+	if ((inb(pcwd_private.io_addr + 2) == 0xFF) ||
+	    (inb(pcwd_private.io_addr + 3) == 0xFF))
 		r=PCWD_REVISION_A;
-	spin_unlock(&io_lock);
+	spin_unlock(&pcwd_private.io_lock);
 
 	return r;
 }
 
-static inline char *get_firmware(void)
-{
-	int one, ten, hund, minor;
-	char *ret;
-
-	ret = kmalloc(6, GFP_KERNEL);
-	if(ret == NULL)
-		return NULL;
-
-	if (set_command_mode()) {
-		one = send_isa_command(CMD_ISA_VERSION_INTEGER);
-		ten = send_isa_command(CMD_ISA_VERSION_TENTH);
-		hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
-		minor = send_isa_command(CMD_ISA_VERSION_MINOR);
-		sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
-	}
-	else
-		sprintf(ret, "ERROR");
-
-	unset_command_mode();
-	return(ret);
-}
-
-static inline int get_option_switches(void)
-{
-	int rv=0;
-
-	if (set_command_mode()) {
-		/* Get switch settings */
-		rv = send_isa_command(CMD_ISA_SWITCH_SETTINGS);
-	}
-
-	unset_command_mode();
-	return(rv);
-}
-
 static int __devinit pcwatchdog_init(int base_addr)
 {
 	int ret;
-	char *firmware;
-	int option_switches;
 
 	cards_found++;
 	if (cards_found == 1)
@@ -692,104 +743,66 @@
 		printk(KERN_ERR PFX "No I/O-Address for card detected\n");
 		return -ENODEV;
 	}
-	current_readport = base_addr;
+	pcwd_private.io_addr = base_addr;
 
 	/* Check card's revision */
-	revision = get_revision();
+	pcwd_private.revision = get_revision();
 
-	if (!request_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
+	if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
 		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-			current_readport);
-		current_readport = 0x0000;
+			pcwd_private.io_addr);
+		pcwd_private.io_addr = 0x0000;
 		return -EIO;
 	}
 
 	/* Initial variables */
-	supports_temp = 0;
+	pcwd_private.supports_temp = 0;
 	temp_panic = 0;
-	initial_status = 0x0000;
+	pcwd_private.boot_status = 0x0000;
 
 	/* get the boot_status */
-	pcwd_get_status(&initial_status);
+	pcwd_get_status(&pcwd_private.boot_status);
 
 	/* clear the "card caused reboot" flag */
 	pcwd_clear_status();
 
-	init_timer(&timer);
-	timer.function = pcwd_timer_ping;
-	timer.data = 0;
+	init_timer(&pcwd_private.timer);
+	pcwd_private.timer.function = pcwd_timer_ping;
+	pcwd_private.timer.data = 0;
 
 	/*  Disable the board  */
 	pcwd_stop();
 
 	/*  Check whether or not the card supports the temperature device */
-	get_support();
+	pcwd_check_temperature_support();
 
-	/* Get some extra info from the hardware (in command/debug/diag mode) */
-	if (revision == PCWD_REVISION_A)
-		printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", current_readport);
-	else if (revision == PCWD_REVISION_C) {
-		firmware = get_firmware();
-		printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
-			current_readport, firmware);
-		kfree(firmware);
-		option_switches = get_option_switches();
-		printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
-			option_switches,
-			((option_switches & 0x10) ? "ON" : "OFF"),
-			((option_switches & 0x08) ? "ON" : "OFF"));
-
-		/* Reprogram internal heartbeat to 2 seconds */
-		if (set_command_mode()) {
-			send_isa_command(CMD_ISA_DELAY_TIME_2SECS);
-			unset_command_mode();
-		}
-	} else {
-		/* Should NEVER happen, unless get_revision() fails. */
-		printk(KERN_INFO PFX "Unable to get revision\n");
-		release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
-		current_readport = 0x0000;
-		return -1;
-	}
-
-	if (supports_temp)
-		printk(KERN_INFO PFX "Temperature Option Detected\n");
-
-	if (initial_status & WDIOF_CARDRESET)
-		printk(KERN_INFO PFX "Previous reboot was caused by the card\n");
-
-	if (initial_status & WDIOF_OVERHEAT) {
-		printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n");
-		printk(KERN_EMERG PFX "CPU Overheat\n");
-	}
-
-	if (initial_status == 0)
-		printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
+	/* Show info about the card itself */
+	pcwd_show_card_info();
 
 	/* Check that the heartbeat value is within it's range ; if not reset to the default */
-        if (pcwd_set_heartbeat(heartbeat)) {
-                pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
-                printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n",
-                        WATCHDOG_HEARTBEAT);
+	if (pcwd_set_heartbeat(heartbeat)) {
+		pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
+		printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n",
+			WATCHDOG_HEARTBEAT);
 	}
 
 	ret = register_reboot_notifier(&pcwd_notifier);
 	if (ret) {
 		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
 			ret);
-		release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
-		current_readport = 0x0000;
+		release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+		pcwd_private.io_addr = 0x0000;
 		return ret;
 	}
 
-	if (supports_temp) {
+	if (pcwd_private.supports_temp) {
 		ret = misc_register(&temp_miscdev);
 		if (ret) {
 			printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
 				TEMP_MINOR, ret);
 			unregister_reboot_notifier(&pcwd_notifier);
-			release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
-			current_readport = 0x0000;
+			release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+			pcwd_private.io_addr = 0x0000;
 			return ret;
 		}
 	}
@@ -798,11 +811,11 @@
 	if (ret) {
 		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
 			WATCHDOG_MINOR, ret);
-		if (supports_temp)
+		if (pcwd_private.supports_temp)
 			misc_deregister(&temp_miscdev);
 		unregister_reboot_notifier(&pcwd_notifier);
-		release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
-		current_readport = 0x0000;
+		release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+		pcwd_private.io_addr = 0x0000;
 		return ret;
 	}
 
@@ -820,11 +833,12 @@
 
 	/* Deregister */
 	misc_deregister(&pcwd_miscdev);
-	if (supports_temp)
+	if (pcwd_private.supports_temp)
 		misc_deregister(&temp_miscdev);
 	unregister_reboot_notifier(&pcwd_notifier);
-	release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
-	current_readport = 0x0000;
+	release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+	pcwd_private.io_addr = 0x0000;
+	cards_found--;
 }
 
 /*
@@ -887,7 +901,7 @@
 {
 	int i, found = 0;
 
-	spin_lock_init(&io_lock);
+	spin_lock_init(&pcwd_private.io_lock);
 
 	for (i = 0; pcwd_ioports[i] != 0; i++) {
 		if (pcwd_checkcard(pcwd_ioports[i])) {
@@ -906,7 +920,7 @@
 
 static void __exit pcwd_cleanup_module(void)
 {
-	if (current_readport)
+	if (pcwd_private.io_addr)
 		pcwatchdog_exit();
 	return;
 }
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index b474ea5..522a937 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -93,23 +93,25 @@
 {
 	int ret = -ENOIOCTLCMD;
 	int time;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
-		ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
+		ret = copy_to_user(argp, &ident,
 				   sizeof(ident)) ? -EFAULT : 0;
 		break;
 
 	case WDIOC_GETSTATUS:
-		ret = put_user(0, (int __user *)arg);
+		ret = put_user(0, p);
 		break;
 
 	case WDIOC_GETBOOTSTATUS:
-		ret = put_user(boot_status, (int __user *)arg);
+		ret = put_user(boot_status, p);
 		break;
 
 	case WDIOC_SETTIMEOUT:
-		ret = get_user(time, (int __user *)arg);
+		ret = get_user(time, p);
 		if (ret)
 			break;
 
@@ -123,7 +125,7 @@
 		/*fall through*/
 
 	case WDIOC_GETTIMEOUT:
-		ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg);
+		ret = put_user(pre_margin / OSCR_FREQ, p);
 		break;
 
 	case WDIOC_KEEPALIVE:
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c
index 9517646..837b1ec 100644
--- a/drivers/char/watchdog/sbc_epx_c3.c
+++ b/drivers/char/watchdog/sbc_epx_c3.c
@@ -25,6 +25,7 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
@@ -91,7 +92,7 @@
 	return 0;
 }
 
-static ssize_t epx_c3_write(struct file *file, const char *data,
+static ssize_t epx_c3_write(struct file *file, const char __user *data,
 			size_t len, loff_t *ppos)
 {
 	/* Refresh the timer. */
@@ -104,6 +105,7 @@
 			unsigned int cmd, unsigned long arg)
 {
 	int options, retval = -EINVAL;
+	int __user *argp = (void __user *)arg;
 	static struct watchdog_info ident = {
 		.options		= WDIOF_KEEPALIVEPING |
 					  WDIOF_MAGICCLOSE,
@@ -113,20 +115,19 @@
 
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
-		if (copy_to_user((struct watchdog_info *)arg,
-				 &ident, sizeof(ident)))
+		if (copy_to_user(argp, &ident, sizeof(ident)))
 			return -EFAULT;
 		return 0;
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETBOOTSTATUS:
-		return put_user(0,(int *)arg);
+		return put_user(0, argp);
 	case WDIOC_KEEPALIVE:
 		epx_c3_pet();
 		return 0;
 	case WDIOC_GETTIMEOUT:
-		return put_user(WATCHDOG_TIMEOUT,(int *)arg);
-	case WDIOC_SETOPTIONS: {
-		if (get_user(options, (int *)arg))
+		return put_user(WATCHDOG_TIMEOUT, argp);
+	case WDIOC_SETOPTIONS:
+		if (get_user(options, argp))
 			return -EFAULT;
 
 		if (options & WDIOS_DISABLECARD) {
@@ -140,7 +141,6 @@
 		}
 
 		return retval;
-	}
 	default:
 		return -ENOIOCTLCMD;
 	}
@@ -181,11 +181,14 @@
 {
 	int ret;
 
+	if (!request_region(EPXC3_WATCHDOG_CTL_REG, 2, "epxc3_watchdog"))
+		return -EBUSY;
+
 	ret = register_reboot_notifier(&epx_c3_notifier);
 	if (ret) {
 		printk(KERN_ERR PFX "cannot register reboot notifier "
 			"(err=%d)\n", ret);
-		return ret;
+		goto out;
 	}
 
 	ret = misc_register(&epx_c3_miscdev);
@@ -193,18 +196,23 @@
 		printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
 			"(err=%d)\n", WATCHDOG_MINOR, ret);
 		unregister_reboot_notifier(&epx_c3_notifier);
-		return ret;
+		goto out;
 	}
 
 	printk(banner);
 
 	return 0;
+
+out:
+	release_region(EPXC3_WATCHDOG_CTL_REG, 2);
+	return ret;
 }
 
 static void __exit watchdog_exit(void)
 {
 	misc_deregister(&epx_c3_miscdev);
 	unregister_reboot_notifier(&epx_c3_notifier);
+	release_region(EPXC3_WATCHDOG_CTL_REG, 2);
 }
 
 module_init(watchdog_init);
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
new file mode 100644
index 0000000..18a4556
--- /dev/null
+++ b/drivers/edac/Kconfig
@@ -0,0 +1,101 @@
+#
+#	EDAC Kconfig
+#	Copyright (c) 2003 Linux Networx
+#	Licensed and distributed under the GPL
+#
+# $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $
+#
+
+menu 'EDAC - error detection and reporting (RAS)'
+
+config EDAC
+	tristate "EDAC core system error reporting"
+	depends on X86
+	help
+	  EDAC is designed to report errors in the core system.
+	  These are low-level errors that are reported in the CPU or
+	  supporting chipset: memory errors, cache errors, PCI errors,
+	  thermal throttling, etc..  If unsure, select 'Y'.
+
+
+comment "Reporting subsystems"
+	depends on EDAC
+
+config EDAC_DEBUG
+	bool "Debugging"
+	depends on EDAC
+	help
+	  This turns on debugging information for the entire EDAC
+	  sub-system. You can insert module with "debug_level=x", current
+	  there're four debug levels (x=0,1,2,3 from low to high).
+	  Usually you should select 'N'.
+
+config EDAC_MM_EDAC
+	tristate "Main Memory EDAC (Error Detection And Correction) reporting"
+	depends on EDAC
+	default y
+	help
+	  Some systems are able to detect and correct errors in main
+	  memory.  EDAC can report statistics on memory error
+	  detection and correction (EDAC - or commonly referred to ECC
+	  errors).  EDAC will also try to decode where these errors
+	  occurred so that a particular failing memory module can be
+	  replaced.  If unsure, select 'Y'.
+
+
+config EDAC_AMD76X
+	tristate "AMD 76x (760, 762, 768)"
+	depends on EDAC_MM_EDAC && PCI && X86_32
+	help
+	  Support for error detection and correction on the AMD 76x
+	  series of chipsets used with the Athlon processor.
+
+config EDAC_E7XXX
+	tristate "Intel e7xxx (e7205, e7500, e7501, e7505)"
+	depends on EDAC_MM_EDAC && PCI
+	help
+	  Support for error detection and correction on the Intel
+	  E7205, E7500, E7501 and E7505 server chipsets.
+
+config EDAC_E752X
+	tristate "Intel e752x (e7520, e7525, e7320)"
+	depends on EDAC_MM_EDAC && PCI
+	help
+	  Support for error detection and correction on the Intel
+	  E7520, E7525, E7320 server chipsets.
+
+config EDAC_I82875P
+	tristate "Intel 82875p (D82875P, E7210)"
+	depends on EDAC_MM_EDAC && PCI
+	help
+	  Support for error detection and correction on the Intel
+	  DP82785P and E7210 server chipsets.
+
+config EDAC_I82860
+	tristate "Intel 82860"
+	depends on EDAC_MM_EDAC && PCI
+	help
+	  Support for error detection and correction on the Intel
+	  82860 chipset.
+
+config EDAC_R82600
+	tristate "Radisys 82600 embedded chipset"
+	depends on EDAC_MM_EDAC
+	help
+	  Support for error detection and correction on the Radisys
+	  82600 embedded chipset.
+
+choice
+	prompt "Error detecting method"
+	depends on EDAC
+	default EDAC_POLL
+
+config EDAC_POLL
+	bool "Poll for errors"
+	depends on EDAC
+	help
+	  Poll the chipset periodically to detect errors.
+
+endchoice
+
+endmenu
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
new file mode 100644
index 0000000..93137fd
--- /dev/null
+++ b/drivers/edac/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Linux kernel EDAC drivers.
+#
+# Copyright 02 Jul 2003, Linux Networx (http://lnxi.com)
+# This file may be distributed under the terms of the
+# GNU General Public License.
+#
+# $Id: Makefile,v 1.4.2.3 2005/07/08 22:05:38 dsp_llnl Exp $
+
+
+obj-$(CONFIG_EDAC_MM_EDAC)		+= edac_mc.o
+obj-$(CONFIG_EDAC_AMD76X)		+= amd76x_edac.o
+obj-$(CONFIG_EDAC_E7XXX)		+= e7xxx_edac.o
+obj-$(CONFIG_EDAC_E752X)		+= e752x_edac.o
+obj-$(CONFIG_EDAC_I82875P)		+= i82875p_edac.o
+obj-$(CONFIG_EDAC_I82860)		+= i82860_edac.o
+obj-$(CONFIG_EDAC_R82600)		+= r82600_edac.o
+
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c
new file mode 100644
index 0000000..2fcc812
--- /dev/null
+++ b/drivers/edac/amd76x_edac.c
@@ -0,0 +1,356 @@
+/*
+ * AMD 76x Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ *	http://www.anime.net/~goemon/linux-ecc/
+ *
+ * $Id: edac_amd76x.c,v 1.4.2.5 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#define AMD76X_NR_CSROWS 8
+#define AMD76X_NR_CHANS  1
+#define AMD76X_NR_DIMMS  4
+
+
+/* AMD 76x register addresses - device 0 function 0 - PCI bridge */
+#define AMD76X_ECC_MODE_STATUS	0x48	/* Mode and status of ECC (32b)
+					 *
+					 * 31:16 reserved
+					 * 15:14 SERR enabled: x1=ue 1x=ce
+					 * 13    reserved
+					 * 12    diag: disabled, enabled
+					 * 11:10 mode: dis, EC, ECC, ECC+scrub
+					 *  9:8  status: x1=ue 1x=ce
+					 *  7:4  UE cs row
+					 *  3:0  CE cs row
+					 */
+#define AMD76X_DRAM_MODE_STATUS	0x58	/* DRAM Mode and status (32b)
+					 *
+					 * 31:26 clock disable 5 - 0
+					 * 25    SDRAM init
+					 * 24    reserved
+					 * 23    mode register service
+					 * 22:21 suspend to RAM
+					 * 20    burst refresh enable
+					 * 19    refresh disable
+					 * 18    reserved
+					 * 17:16 cycles-per-refresh
+					 * 15:8  reserved
+					 *  7:0  x4 mode enable 7 - 0
+					 */
+#define AMD76X_MEM_BASE_ADDR	0xC0	/* Memory base address (8 x 32b)
+					 *
+					 * 31:23 chip-select base
+					 * 22:16 reserved
+					 * 15:7  chip-select mask
+					 *  6:3  reserved
+					 *  2:1  address mode
+					 *  0    chip-select enable
+					 */
+
+
+struct amd76x_error_info {
+	u32 ecc_mode_status;
+};
+
+
+enum amd76x_chips {
+	AMD761 = 0,
+	AMD762
+};
+
+
+struct amd76x_dev_info {
+	const char *ctl_name;
+};
+
+
+static const struct amd76x_dev_info amd76x_devs[] = {
+	[AMD761] = {.ctl_name = "AMD761"},
+	[AMD762] = {.ctl_name = "AMD762"},
+};
+
+
+/**
+ *	amd76x_get_error_info	-	fetch error information
+ *	@mci: Memory controller
+ *	@info: Info to fill in
+ *
+ *	Fetch and store the AMD76x ECC status. Clear pending status
+ *	on the chip so that further errors will be reported
+ */
+
+static void amd76x_get_error_info (struct mem_ctl_info *mci,
+				   struct amd76x_error_info *info)
+{
+	pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS,
+				&info->ecc_mode_status);
+
+	if (info->ecc_mode_status & BIT(8))
+		pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
+				   (u32) BIT(8), (u32) BIT(8));
+
+	if (info->ecc_mode_status & BIT(9))
+		pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
+				   (u32) BIT(9), (u32) BIT(9));
+}
+
+
+/**
+ *	amd76x_process_error_info	-	Error check
+ *	@mci: Memory controller
+ *	@info: Previously fetched information from chip
+ *	@handle_errors: 1 if we should do recovery
+ *
+ *	Process the chip state and decide if an error has occurred.
+ *	A return of 1 indicates an error. Also if handle_errors is true
+ *	then attempt to handle and clean up after the error
+ */
+
+static int amd76x_process_error_info (struct mem_ctl_info *mci,
+		struct amd76x_error_info *info, int handle_errors)
+{
+	int error_found;
+	u32 row;
+
+	error_found = 0;
+
+	/*
+	 *	Check for an uncorrectable error
+	 */
+	if (info->ecc_mode_status & BIT(8)) {
+		error_found = 1;
+
+		if (handle_errors) {
+			row = (info->ecc_mode_status >> 4) & 0xf;
+			edac_mc_handle_ue(mci,
+			    mci->csrows[row].first_page, 0, row,
+			    mci->ctl_name);
+		}
+	}
+
+	/*
+	 *	Check for a correctable error
+	 */
+	if (info->ecc_mode_status & BIT(9)) {
+		error_found = 1;
+
+		if (handle_errors) {
+			row = info->ecc_mode_status & 0xf;
+			edac_mc_handle_ce(mci,
+			    mci->csrows[row].first_page, 0, 0, row, 0,
+			    mci->ctl_name);
+		}
+	}
+	return error_found;
+}
+
+/**
+ *	amd76x_check	-	Poll the controller
+ *	@mci: Memory controller
+ *
+ *	Called by the poll handlers this function reads the status
+ *	from the controller and checks for errors.
+ */
+
+static void amd76x_check(struct mem_ctl_info *mci)
+{
+	struct amd76x_error_info info;
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	amd76x_get_error_info(mci, &info);
+	amd76x_process_error_info(mci, &info, 1);
+}
+
+
+/**
+ *	amd76x_probe1	-	Perform set up for detected device
+ *	@pdev; PCI device detected
+ *	@dev_idx: Device type index
+ *
+ *	We have found an AMD76x and now need to set up the memory
+ *	controller status reporting. We configure and set up the
+ *	memory controller reporting and claim the device.
+ */
+
+static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
+{
+	int rc = -ENODEV;
+	int index;
+	struct mem_ctl_info *mci = NULL;
+	enum edac_type ems_modes[] = {
+		EDAC_NONE,
+		EDAC_EC,
+		EDAC_SECDED,
+		EDAC_SECDED
+	};
+	u32 ems;
+	u32 ems_mode;
+
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
+	ems_mode = (ems >> 10) & 0x3;
+
+	mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS);
+
+	if (mci == NULL) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+	mci->pdev = pci_dev_get(pdev);
+	mci->mtype_cap = MEM_FLAG_RDDR;
+
+	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+	mci->edac_cap = ems_mode ?
+	    (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
+
+	mci->mod_name = BS_MOD_STR;
+	mci->mod_ver = "$Revision: 1.4.2.5 $";
+	mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
+	mci->edac_check = amd76x_check;
+	mci->ctl_page_to_phys = NULL;
+
+	for (index = 0; index < mci->nr_csrows; index++) {
+		struct csrow_info *csrow = &mci->csrows[index];
+		u32 mba;
+		u32 mba_base;
+		u32 mba_mask;
+		u32 dms;
+
+		/* find the DRAM Chip Select Base address and mask */
+		pci_read_config_dword(mci->pdev,
+				      AMD76X_MEM_BASE_ADDR + (index * 4),
+				      &mba);
+
+		if (!(mba & BIT(0)))
+			continue;
+
+		mba_base = mba & 0xff800000UL;
+		mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
+
+		pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS,
+				      &dms);
+
+		csrow->first_page = mba_base >> PAGE_SHIFT;
+		csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
+		csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+		csrow->page_mask = mba_mask >> PAGE_SHIFT;
+		csrow->grain = csrow->nr_pages << PAGE_SHIFT;
+		csrow->mtype = MEM_RDDR;
+		csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
+		csrow->edac_mode = ems_modes[ems_mode];
+	}
+
+	/* clear counters */
+	pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, (u32) (0x3 << 8),
+			 (u32) (0x3 << 8));
+
+	if (edac_mc_add_mc(mci)) {
+		debugf3("MC: " __FILE__
+			": %s(): failed edac_mc_add_mc()\n", __func__);
+		goto fail;
+	}
+
+	/* get this far and it's successful */
+	debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+	return 0;
+
+fail:
+	if (mci) {
+		if(mci->pdev)
+			pci_dev_put(mci->pdev);
+		edac_mc_free(mci);
+	}
+	return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit amd76x_init_one(struct pci_dev *pdev,
+				     const struct pci_device_id *ent)
+{
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* don't need to call pci_device_enable() */
+	return amd76x_probe1(pdev, ent->driver_data);
+}
+
+
+/**
+ *	amd76x_remove_one	-	driver shutdown
+ *	@pdev: PCI device being handed back
+ *
+ *	Called when the driver is unloaded. Find the matching mci
+ *	structure for the device then delete the mci and free the
+ *	resources.
+ */
+
+static void __devexit amd76x_remove_one(struct pci_dev *pdev)
+{
+	struct mem_ctl_info *mci;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+
+	if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+		return;
+	if (edac_mc_del_mc(mci))
+		return;
+	pci_dev_put(mci->pdev);
+	edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id amd76x_pci_tbl[] __devinitdata = {
+	{PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 AMD762},
+	{PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 AMD761},
+	{0,}			/* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
+
+
+static struct pci_driver amd76x_driver = {
+	.name = BS_MOD_STR,
+	.probe = amd76x_init_one,
+	.remove = __devexit_p(amd76x_remove_one),
+	.id_table = amd76x_pci_tbl,
+};
+
+static int __init amd76x_init(void)
+{
+	return pci_register_driver(&amd76x_driver);
+}
+
+static void __exit amd76x_exit(void)
+{
+	pci_unregister_driver(&amd76x_driver);
+}
+
+module_init(amd76x_init);
+module_exit(amd76x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for AMD 76x memory controllers");
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
new file mode 100644
index 0000000..c454ded
--- /dev/null
+++ b/drivers/edac/e752x_edac.c
@@ -0,0 +1,1071 @@
+/*
+ * Intel e752x Memory Controller kernel module
+ * (C) 2004 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * See "enum e752x_chips" below for supported chipsets
+ *
+ * Written by Tom Zimmerman
+ *
+ * Contributors:
+ * 	Thayne Harbaugh at realmsys.com (?)
+ * 	Wang Zhenyu at intel.com
+ * 	Dave Jiang at mvista.com
+ *
+ * $Id: edac_e752x.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_7520_0
+#define PCI_DEVICE_ID_INTEL_7520_0      0x3590
+#endif				/* PCI_DEVICE_ID_INTEL_7520_0      */
+
+#ifndef PCI_DEVICE_ID_INTEL_7520_1_ERR
+#define PCI_DEVICE_ID_INTEL_7520_1_ERR  0x3591
+#endif				/* PCI_DEVICE_ID_INTEL_7520_1_ERR  */
+
+#ifndef PCI_DEVICE_ID_INTEL_7525_0
+#define PCI_DEVICE_ID_INTEL_7525_0      0x359E
+#endif				/* PCI_DEVICE_ID_INTEL_7525_0      */
+
+#ifndef PCI_DEVICE_ID_INTEL_7525_1_ERR
+#define PCI_DEVICE_ID_INTEL_7525_1_ERR  0x3593
+#endif				/* PCI_DEVICE_ID_INTEL_7525_1_ERR  */
+
+#ifndef PCI_DEVICE_ID_INTEL_7320_0
+#define PCI_DEVICE_ID_INTEL_7320_0	0x3592
+#endif				/* PCI_DEVICE_ID_INTEL_7320_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7320_1_ERR
+#define PCI_DEVICE_ID_INTEL_7320_1_ERR	0x3593
+#endif				/* PCI_DEVICE_ID_INTEL_7320_1_ERR */
+
+#define E752X_NR_CSROWS		8	/* number of csrows */
+
+
+/* E752X register addresses - device 0 function 0 */
+#define E752X_DRB		0x60	/* DRAM row boundary register (8b) */
+#define E752X_DRA		0x70	/* DRAM row attribute register (8b) */
+					/*
+					 * 31:30   Device width row 7
+					 *      01=x8 10=x4 11=x8 DDR2
+					 * 27:26   Device width row 6
+					 * 23:22   Device width row 5
+					 * 19:20   Device width row 4
+					 * 15:14   Device width row 3
+					 * 11:10   Device width row 2
+					 *  7:6    Device width row 1
+					 *  3:2    Device width row 0
+					 */
+#define E752X_DRC		0x7C	/* DRAM controller mode reg (32b) */
+					/* FIXME:IS THIS RIGHT? */
+					/*
+					 * 22    Number channels 0=1,1=2
+					 * 19:18 DRB Granularity 32/64MB
+					 */
+#define E752X_DRM		0x80	/* Dimm mapping register */
+#define E752X_DDRCSR		0x9A	/* DDR control and status reg (16b) */
+					/*
+					 * 14:12 1 single A, 2 single B, 3 dual
+					 */
+#define E752X_TOLM		0xC4	/* DRAM top of low memory reg (16b) */
+#define E752X_REMAPBASE		0xC6	/* DRAM remap base address reg (16b) */
+#define E752X_REMAPLIMIT	0xC8	/* DRAM remap limit address reg (16b) */
+#define E752X_REMAPOFFSET	0xCA	/* DRAM remap limit offset reg (16b) */
+
+/* E752X register addresses - device 0 function 1 */
+#define E752X_FERR_GLOBAL	0x40	/* Global first error register (32b) */
+#define E752X_NERR_GLOBAL	0x44	/* Global next error register (32b) */
+#define E752X_HI_FERR		0x50	/* Hub interface first error reg (8b) */
+#define E752X_HI_NERR		0x52	/* Hub interface next error reg (8b) */
+#define E752X_HI_ERRMASK	0x54	/* Hub interface error mask reg (8b) */
+#define E752X_HI_SMICMD		0x5A	/* Hub interface SMI command reg (8b) */
+#define E752X_SYSBUS_FERR	0x60	/* System buss first error reg (16b) */
+#define E752X_SYSBUS_NERR	0x62	/* System buss next error reg (16b) */
+#define E752X_SYSBUS_ERRMASK	0x64	/* System buss error mask reg (16b) */
+#define E752X_SYSBUS_SMICMD	0x6A	/* System buss SMI command reg (16b) */
+#define E752X_BUF_FERR		0x70	/* Memory buffer first error reg (8b) */
+#define E752X_BUF_NERR		0x72	/* Memory buffer next error reg (8b) */
+#define E752X_BUF_ERRMASK	0x74	/* Memory buffer error mask reg (8b) */
+#define E752X_BUF_SMICMD	0x7A	/* Memory buffer SMI command reg (8b) */
+#define E752X_DRAM_FERR		0x80	/* DRAM first error register (16b) */
+#define E752X_DRAM_NERR		0x82	/* DRAM next error register (16b) */
+#define E752X_DRAM_ERRMASK	0x84	/* DRAM error mask register (8b) */
+#define E752X_DRAM_SMICMD	0x8A	/* DRAM SMI command register (8b) */
+#define E752X_DRAM_RETR_ADD	0xAC	/* DRAM Retry address register (32b) */
+#define E752X_DRAM_SEC1_ADD	0xA0	/* DRAM first correctable memory */
+					/*     error address register (32b) */
+					/*
+					 * 31    Reserved
+					 * 30:2  CE address (64 byte block 34:6)
+					 * 1     Reserved
+					 * 0     HiLoCS
+					 */
+#define E752X_DRAM_SEC2_ADD	0xC8	/* DRAM first correctable memory */
+					/*     error address register (32b) */
+					/*
+					 * 31    Reserved
+					 * 30:2  CE address (64 byte block 34:6)
+					 * 1     Reserved
+					 * 0     HiLoCS
+					 */
+#define E752X_DRAM_DED_ADD	0xA4	/* DRAM first uncorrectable memory */
+					/*     error address register (32b) */
+					/*
+					 * 31    Reserved
+					 * 30:2  CE address (64 byte block 34:6)
+					 * 1     Reserved
+					 * 0     HiLoCS
+					 */
+#define E752X_DRAM_SCRB_ADD	0xA8	/* DRAM first uncorrectable scrub memory */
+					/*     error address register (32b) */
+					/*
+					 * 31    Reserved
+					 * 30:2  CE address (64 byte block 34:6)
+					 * 1     Reserved
+					 * 0     HiLoCS
+					 */
+#define E752X_DRAM_SEC1_SYNDROME 0xC4	/* DRAM first correctable memory */
+					/*     error syndrome register (16b) */
+#define E752X_DRAM_SEC2_SYNDROME 0xC6	/* DRAM second correctable memory */
+					/*     error syndrome register (16b) */
+#define E752X_DEVPRES1		0xF4	/* Device Present 1 register (8b) */
+
+/* ICH5R register addresses - device 30 function 0 */
+#define ICH5R_PCI_STAT		0x06	/* PCI status register (16b) */
+#define ICH5R_PCI_2ND_STAT	0x1E	/* PCI status secondary reg (16b) */
+#define ICH5R_PCI_BRIDGE_CTL	0x3E	/* PCI bridge control register (16b) */
+
+enum e752x_chips {
+	E7520 = 0,
+	E7525 = 1,
+	E7320 = 2
+};
+
+
+struct e752x_pvt {
+	struct pci_dev *bridge_ck;
+	struct pci_dev *dev_d0f0;
+	struct pci_dev *dev_d0f1;
+	u32 tolm;
+	u32 remapbase;
+	u32 remaplimit;
+	int mc_symmetric;
+	u8 map[8];
+	int map_type;
+	const struct e752x_dev_info *dev_info;
+};
+
+
+struct e752x_dev_info {
+	u16 err_dev;
+	const char *ctl_name;
+};
+
+struct e752x_error_info {
+	u32 ferr_global;
+	u32 nerr_global;
+	u8 hi_ferr;
+	u8 hi_nerr;
+	u16 sysbus_ferr;
+	u16 sysbus_nerr;
+	u8 buf_ferr;
+	u8 buf_nerr;
+	u16 dram_ferr;
+	u16 dram_nerr;
+	u32 dram_sec1_add;
+	u32 dram_sec2_add;
+	u16 dram_sec1_syndrome;
+	u16 dram_sec2_syndrome;
+	u32 dram_ded_add;
+	u32 dram_scrb_add;
+	u32 dram_retr_add;
+};
+
+static const struct e752x_dev_info e752x_devs[] = {
+	[E7520] = {
+		   .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR,
+		   .ctl_name = "E7520"},
+	[E7525] = {
+		   .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR,
+		   .ctl_name = "E7525"},
+	[E7320] = {
+		   .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
+		   .ctl_name = "E7320"},
+};
+
+
+static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
+				      unsigned long page)
+{
+	u32 remap;
+	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	if (page < pvt->tolm)
+		return page;
+	if ((page >= 0x100000) && (page < pvt->remapbase))
+		return page;
+	remap = (page - pvt->tolm) + pvt->remapbase;
+	if (remap < pvt->remaplimit)
+		return remap;
+	printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+	return pvt->tolm - 1;
+}
+
+static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
+		       u32 sec1_add, u16 sec1_syndrome)
+{
+	u32 page;
+	int row;
+	int channel;
+	int i;
+	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* convert the addr to 4k page */
+	page = sec1_add >> (PAGE_SHIFT - 4);
+
+	/* FIXME - check for -1 */
+	if (pvt->mc_symmetric) {
+		/* chip select are bits 14 & 13 */
+		row = ((page >> 1) & 3);
+		printk(KERN_WARNING
+		       "Test row %d Table %d %d %d %d %d %d %d %d\n",
+		       row, pvt->map[0], pvt->map[1], pvt->map[2],
+		       pvt->map[3], pvt->map[4], pvt->map[5],
+		       pvt->map[6], pvt->map[7]);
+
+		/* test for channel remapping */
+		for (i = 0; i < 8; i++) {
+			if (pvt->map[i] == row)
+				break;
+		}
+		printk(KERN_WARNING "Test computed row %d\n", i);
+		if (i < 8)
+			row = i;
+		else
+			printk(KERN_WARNING
+			       "MC%d: row %d not found in remap table\n",
+			       mci->mc_idx, row);
+	} else
+		row = edac_mc_find_csrow_by_page(mci, page);
+	/* 0 = channel A, 1 = channel B */
+	channel = !(error_one & 1);
+
+	if (!pvt->map_type)
+		row = 7 - row;
+	edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel,
+	    "e752x CE");
+}
+
+
+static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
+		u32 sec1_add, u16 sec1_syndrome, int *error_found,
+		int handle_error)
+{
+	*error_found = 1;
+
+	if (handle_error)
+		do_process_ce(mci, error_one, sec1_add, sec1_syndrome);
+}
+
+static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add,
+		u32 scrb_add)
+{
+	u32 error_2b, block_page;
+	int row;
+	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	if (error_one & 0x0202) {
+		error_2b = ded_add;
+		/* convert to 4k address */
+		block_page = error_2b >> (PAGE_SHIFT - 4);
+		row = pvt->mc_symmetric ?
+		    /* chip select are bits 14 & 13 */
+		    ((block_page >> 1) & 3) :
+		    edac_mc_find_csrow_by_page(mci, block_page);
+		edac_mc_handle_ue(mci, block_page, 0, row,
+				       "e752x UE from Read");
+	}
+	if (error_one & 0x0404) {
+		error_2b = scrb_add;
+		/* convert to 4k address */
+		block_page = error_2b >> (PAGE_SHIFT - 4);
+		row = pvt->mc_symmetric ?
+		    /* chip select are bits 14 & 13 */
+		    ((block_page >> 1) & 3) :
+		    edac_mc_find_csrow_by_page(mci, block_page);
+		edac_mc_handle_ue(mci, block_page, 0, row,
+				       "e752x UE from Scruber");
+	}
+}
+
+static inline void process_ue(struct mem_ctl_info *mci, u16 error_one,
+		u32 ded_add, u32 scrb_add, int *error_found, int handle_error)
+{
+	*error_found = 1;
+
+	if (handle_error)
+		do_process_ue(mci, error_one, ded_add, scrb_add);
+}
+
+static inline void process_ue_no_info_wr(struct mem_ctl_info *mci,
+		int *error_found, int handle_error)
+{
+	*error_found = 1;
+
+	if (!handle_error)
+		return;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	edac_mc_handle_ue_no_info(mci, "e752x UE log memory write");
+}
+
+static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
+		u32 retry_add)
+{
+	u32 error_1b, page;
+	int row;
+	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+	error_1b = retry_add;
+	page = error_1b >> (PAGE_SHIFT - 4);	/* convert the addr to 4k page */
+	row = pvt->mc_symmetric ?
+	    ((page >> 1) & 3) :	/* chip select are bits 14 & 13 */
+	    edac_mc_find_csrow_by_page(mci, page);
+	printk(KERN_WARNING
+	       "MC%d: CE page 0x%lx, row %d : Memory read retry\n",
+	       mci->mc_idx, (long unsigned int) page, row);
+}
+
+static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error,
+		u32 retry_add, int *error_found, int handle_error)
+{
+	*error_found = 1;
+
+	if (handle_error)
+		do_process_ded_retry(mci, error, retry_add);
+}
+
+static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
+		int *error_found, int handle_error)
+{
+	*error_found = 1;
+
+	if (handle_error)
+		printk(KERN_WARNING "MC%d: Memory threshold CE\n",
+		       mci->mc_idx);
+}
+
+static char *global_message[11] = {
+	"PCI Express C1", "PCI Express C", "PCI Express B1",
+	"PCI Express B", "PCI Express A1", "PCI Express A",
+	"DMA Controler", "HUB Interface", "System Bus",
+	"DRAM Controler", "Internal Buffer"
+};
+
+static char *fatal_message[2] = { "Non-Fatal ", "Fatal " };
+
+static void do_global_error(int fatal, u32 errors)
+{
+	int i;
+
+	for (i = 0; i < 11; i++) {
+		if (errors & (1 << i))
+			printk(KERN_WARNING "%sError %s\n",
+			       fatal_message[fatal], global_message[i]);
+	}
+}
+
+static inline void global_error(int fatal, u32 errors, int *error_found,
+		int handle_error)
+{
+	*error_found = 1;
+
+	if (handle_error)
+		do_global_error(fatal, errors);
+}
+
+static char *hub_message[7] = {
+	"HI Address or Command Parity", "HI Illegal Access",
+	"HI Internal Parity", "Out of Range Access",
+	"HI Data Parity", "Enhanced Config Access",
+	"Hub Interface Target Abort"
+};
+
+static void do_hub_error(int fatal, u8 errors)
+{
+	int i;
+
+	for (i = 0; i < 7; i++) {
+		if (errors & (1 << i))
+			printk(KERN_WARNING "%sError %s\n",
+			       fatal_message[fatal], hub_message[i]);
+	}
+}
+
+static inline void hub_error(int fatal, u8 errors, int *error_found,
+		int handle_error)
+{
+	*error_found = 1;
+
+	if (handle_error)
+		do_hub_error(fatal, errors);
+}
+
+static char *membuf_message[4] = {
+	"Internal PMWB to DRAM parity",
+	"Internal PMWB to System Bus Parity",
+	"Internal System Bus or IO to PMWB Parity",
+	"Internal DRAM to PMWB Parity"
+};
+
+static void do_membuf_error(u8 errors)
+{
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		if (errors & (1 << i))
+			printk(KERN_WARNING "Non-Fatal Error %s\n",
+			       membuf_message[i]);
+	}
+}
+
+static inline void membuf_error(u8 errors, int *error_found, int handle_error)
+{
+	*error_found = 1;
+
+	if (handle_error)
+		do_membuf_error(errors);
+}
+
+#if 0
+char *sysbus_message[10] = {
+	"Addr or Request Parity",
+	"Data Strobe Glitch",
+	"Addr Strobe Glitch",
+	"Data Parity",
+	"Addr Above TOM",
+	"Non DRAM Lock Error",
+	"MCERR", "BINIT",
+	"Memory Parity",
+	"IO Subsystem Parity"
+};
+#endif  /*  0  */
+
+static void do_sysbus_error(int fatal, u32 errors)
+{
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		if (errors & (1 << i))
+			printk(KERN_WARNING "%sError System Bus %s\n",
+			       fatal_message[fatal], global_message[i]);
+	}
+}
+
+static inline void sysbus_error(int fatal, u32 errors, int *error_found,
+		int handle_error)
+{
+	*error_found = 1;
+
+	if (handle_error)
+		do_sysbus_error(fatal, errors);
+}
+
+static void e752x_check_hub_interface (struct e752x_error_info *info,
+		int *error_found, int handle_error)
+{
+	u8 stat8;
+
+	//pci_read_config_byte(dev,E752X_HI_FERR,&stat8);
+	stat8 = info->hi_ferr;
+	if(stat8 & 0x7f) { /* Error, so process */
+		stat8 &= 0x7f;
+		if(stat8 & 0x2b)
+			hub_error(1, stat8 & 0x2b, error_found, handle_error);
+		if(stat8 & 0x54)
+			hub_error(0, stat8 & 0x54, error_found, handle_error);
+	}
+	//pci_read_config_byte(dev,E752X_HI_NERR,&stat8);
+	stat8 = info->hi_nerr;
+	if(stat8 & 0x7f) { /* Error, so process */
+		stat8 &= 0x7f;
+		if (stat8 & 0x2b)
+			hub_error(1, stat8 & 0x2b, error_found, handle_error);
+		if(stat8 & 0x54)
+			hub_error(0, stat8 & 0x54, error_found, handle_error);
+	}
+}
+
+static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found,
+		int handle_error)
+{
+	u32 stat32, error32;
+
+	//pci_read_config_dword(dev,E752X_SYSBUS_FERR,&stat32);
+	stat32 = info->sysbus_ferr + (info->sysbus_nerr << 16);
+
+	if (stat32 == 0)
+		return;  /* no errors */
+
+	error32 = (stat32 >> 16) & 0x3ff;
+	stat32 = stat32 & 0x3ff;
+	if(stat32 & 0x083)
+		sysbus_error(1, stat32 & 0x083, error_found, handle_error);
+	if(stat32 & 0x37c)
+		sysbus_error(0, stat32 & 0x37c, error_found, handle_error);
+	if(error32 & 0x083)
+		sysbus_error(1, error32 & 0x083, error_found, handle_error);
+	if(error32 & 0x37c)
+		sysbus_error(0, error32 & 0x37c, error_found, handle_error);
+}
+
+static void e752x_check_membuf (struct e752x_error_info *info, int *error_found,
+		int handle_error)
+{
+	u8 stat8;
+
+	stat8 = info->buf_ferr;
+	if (stat8 & 0x0f) { /* Error, so process */
+		stat8 &= 0x0f;
+		membuf_error(stat8, error_found, handle_error);
+	}
+	stat8 = info->buf_nerr;
+	if (stat8 & 0x0f) { /* Error, so process */
+		stat8 &= 0x0f;
+		membuf_error(stat8, error_found, handle_error);
+	}
+}
+
+static void e752x_check_dram (struct mem_ctl_info *mci,
+		struct e752x_error_info *info, int *error_found, int handle_error)
+{
+	u16 error_one, error_next;
+
+	error_one = info->dram_ferr;
+	error_next = info->dram_nerr;
+
+	/* decode and report errors */
+	if(error_one & 0x0101)  /* check first error correctable */
+		process_ce(mci, error_one, info->dram_sec1_add,
+			   info->dram_sec1_syndrome, error_found,
+			   handle_error);
+
+	if(error_next & 0x0101)  /* check next error correctable */
+		process_ce(mci, error_next, info->dram_sec2_add,
+			   info->dram_sec2_syndrome, error_found,
+			   handle_error);
+
+	if(error_one & 0x4040)
+		process_ue_no_info_wr(mci, error_found, handle_error);
+
+	if(error_next & 0x4040)
+		process_ue_no_info_wr(mci, error_found, handle_error);
+
+	if(error_one & 0x2020)
+		process_ded_retry(mci, error_one, info->dram_retr_add,
+				  error_found, handle_error);
+
+	if(error_next & 0x2020)
+		process_ded_retry(mci, error_next, info->dram_retr_add,
+				  error_found, handle_error);
+
+	if(error_one & 0x0808)
+		process_threshold_ce(mci, error_one, error_found,
+				     handle_error);
+
+	if(error_next & 0x0808)
+		process_threshold_ce(mci, error_next, error_found,
+				     handle_error);
+
+	if(error_one & 0x0606)
+		process_ue(mci, error_one, info->dram_ded_add,
+			   info->dram_scrb_add, error_found, handle_error);
+
+	if(error_next & 0x0606)
+		process_ue(mci, error_next, info->dram_ded_add,
+			   info->dram_scrb_add, error_found, handle_error);
+}
+
+static void e752x_get_error_info (struct mem_ctl_info *mci,
+				  struct e752x_error_info *info)
+{
+	struct pci_dev *dev;
+	struct e752x_pvt *pvt;
+
+	memset(info, 0, sizeof(*info));
+	pvt = (struct e752x_pvt *) mci->pvt_info;
+	dev = pvt->dev_d0f1;
+
+	pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
+
+	if (info->ferr_global) {
+		pci_read_config_byte(dev, E752X_HI_FERR, &info->hi_ferr);
+		pci_read_config_word(dev, E752X_SYSBUS_FERR,
+				&info->sysbus_ferr);
+		pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr);
+		pci_read_config_word(dev, E752X_DRAM_FERR,
+				&info->dram_ferr);
+		pci_read_config_dword(dev, E752X_DRAM_SEC1_ADD,
+				&info->dram_sec1_add);
+		pci_read_config_word(dev, E752X_DRAM_SEC1_SYNDROME,
+				&info->dram_sec1_syndrome);
+		pci_read_config_dword(dev, E752X_DRAM_DED_ADD,
+				&info->dram_ded_add);
+		pci_read_config_dword(dev, E752X_DRAM_SCRB_ADD,
+				&info->dram_scrb_add);
+		pci_read_config_dword(dev, E752X_DRAM_RETR_ADD,
+				&info->dram_retr_add);
+
+		if (info->hi_ferr & 0x7f)
+			pci_write_config_byte(dev, E752X_HI_FERR,
+					info->hi_ferr);
+
+		if (info->sysbus_ferr)
+			pci_write_config_word(dev, E752X_SYSBUS_FERR,
+					info->sysbus_ferr);
+
+		if (info->buf_ferr & 0x0f)
+			pci_write_config_byte(dev, E752X_BUF_FERR,
+					info->buf_ferr);
+
+		if (info->dram_ferr)
+			pci_write_bits16(pvt->bridge_ck, E752X_DRAM_FERR,
+					info->dram_ferr, info->dram_ferr);
+
+		pci_write_config_dword(dev, E752X_FERR_GLOBAL,
+				info->ferr_global);
+	}
+
+	pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global);
+
+	if (info->nerr_global) {
+		pci_read_config_byte(dev, E752X_HI_NERR, &info->hi_nerr);
+		pci_read_config_word(dev, E752X_SYSBUS_NERR,
+				&info->sysbus_nerr);
+		pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr);
+		pci_read_config_word(dev, E752X_DRAM_NERR,
+				&info->dram_nerr);
+		pci_read_config_dword(dev, E752X_DRAM_SEC2_ADD,
+				&info->dram_sec2_add);
+		pci_read_config_word(dev, E752X_DRAM_SEC2_SYNDROME,
+				&info->dram_sec2_syndrome);
+
+		if (info->hi_nerr & 0x7f)
+			pci_write_config_byte(dev, E752X_HI_NERR,
+					info->hi_nerr);
+
+		if (info->sysbus_nerr)
+			pci_write_config_word(dev, E752X_SYSBUS_NERR,
+					info->sysbus_nerr);
+
+		if (info->buf_nerr & 0x0f)
+			pci_write_config_byte(dev, E752X_BUF_NERR,
+					info->buf_nerr);
+
+		if (info->dram_nerr)
+			pci_write_bits16(pvt->bridge_ck, E752X_DRAM_NERR,
+					info->dram_nerr, info->dram_nerr);
+
+		pci_write_config_dword(dev, E752X_NERR_GLOBAL,
+				info->nerr_global);
+	}
+}
+
+static int e752x_process_error_info (struct mem_ctl_info *mci,
+		struct e752x_error_info *info, int handle_errors)
+{
+	u32 error32, stat32;
+	int error_found;
+
+	error_found = 0;
+	error32 = (info->ferr_global >> 18) & 0x3ff;
+	stat32 = (info->ferr_global >> 4) & 0x7ff;
+
+	if (error32)
+		global_error(1, error32, &error_found, handle_errors);
+
+	if (stat32)
+		global_error(0, stat32, &error_found, handle_errors);
+
+	error32 = (info->nerr_global >> 18) & 0x3ff;
+	stat32 = (info->nerr_global >> 4) & 0x7ff;
+
+	if (error32)
+		global_error(1, error32, &error_found, handle_errors);
+
+	if (stat32)
+		global_error(0, stat32, &error_found, handle_errors);
+
+	e752x_check_hub_interface(info, &error_found, handle_errors);
+	e752x_check_sysbus(info, &error_found, handle_errors);
+	e752x_check_membuf(info, &error_found, handle_errors);
+	e752x_check_dram(mci, info, &error_found, handle_errors);
+	return error_found;
+}
+
+static void e752x_check(struct mem_ctl_info *mci)
+{
+	struct e752x_error_info info;
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	e752x_get_error_info(mci, &info);
+	e752x_process_error_info(mci, &info, 1);
+}
+
+static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
+{
+	int rc = -ENODEV;
+	int index;
+	u16 pci_data, stat;
+	u32 stat32;
+	u16 stat16;
+	u8 stat8;
+	struct mem_ctl_info *mci = NULL;
+	struct e752x_pvt *pvt = NULL;
+	u16 ddrcsr;
+	u32 drc;
+	int drc_chan;		/* Number of channels 0=1chan,1=2chan */
+	int drc_drbg;		/* DRB granularity 0=64mb,1=128mb */
+	int drc_ddim;		/* DRAM Data Integrity Mode 0=none,2=edac */
+	u32 dra;
+	unsigned long last_cumul_size;
+	struct pci_dev *pres_dev;
+	struct pci_dev *dev = NULL;
+
+	debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+	debugf0("Starting Probe1\n");
+
+	/* enable device 0 function 1 */
+	pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8);
+	stat8 |= (1 << 5);
+	pci_write_config_byte(pdev, E752X_DEVPRES1, stat8);
+
+	/* need to find out the number of channels */
+	pci_read_config_dword(pdev, E752X_DRC, &drc);
+	pci_read_config_word(pdev, E752X_DDRCSR, &ddrcsr);
+	/* FIXME: should check >>12 or 0xf, true for all? */
+	/* Dual channel = 1, Single channel = 0 */
+	drc_chan = (((ddrcsr >> 12) & 3) == 3);
+	drc_drbg = drc_chan + 1;	/* 128 in dual mode, 64 in single */
+	drc_ddim = (drc >> 20) & 0x3;
+
+	mci = edac_mc_alloc(sizeof(*pvt), E752X_NR_CSROWS, drc_chan + 1);
+
+	if (mci == NULL) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+	mci->mtype_cap = MEM_FLAG_RDDR;
+	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
+	    EDAC_FLAG_S4ECD4ED;
+	/* FIXME - what if different memory types are in different csrows? */
+	mci->mod_name = BS_MOD_STR;
+	mci->mod_ver = "$Revision: 1.5.2.11 $";
+	mci->pdev = pdev;
+
+	debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+	pvt = (struct e752x_pvt *) mci->pvt_info;
+	pvt->dev_info = &e752x_devs[dev_idx];
+	pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
+					 pvt->dev_info->err_dev,
+					 pvt->bridge_ck);
+	if (pvt->bridge_ck == NULL)
+		pvt->bridge_ck = pci_scan_single_device(pdev->bus,
+							PCI_DEVFN(0, 1));
+	if (pvt->bridge_ck == NULL) {
+		printk(KERN_ERR "MC: error reporting device not found:"
+		       "vendor %x device 0x%x (broken BIOS?)\n",
+		       PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
+		goto fail;
+	}
+	pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
+
+	debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+	mci->ctl_name = pvt->dev_info->ctl_name;
+	mci->edac_check = e752x_check;
+	mci->ctl_page_to_phys = ctl_page_to_phys;
+
+	/* find out the device types */
+	pci_read_config_dword(pdev, E752X_DRA, &dra);
+
+	/*
+	 * The dram row boundary (DRB) reg values are boundary address for
+	 * each DRAM row with a granularity of 64 or 128MB (single/dual
+	 * channel operation).  DRB regs are cumulative; therefore DRB7 will
+	 * contain the total memory contained in all eight rows.
+	 */
+	for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+		u8 value;
+		u32 cumul_size;
+		/* mem_dev 0=x8, 1=x4 */
+		int mem_dev = (dra >> (index * 4 + 2)) & 0x3;
+		struct csrow_info *csrow = &mci->csrows[index];
+
+		mem_dev = (mem_dev == 2);
+		pci_read_config_byte(mci->pdev, E752X_DRB + index, &value);
+		/* convert a 128 or 64 MiB DRB to a page size. */
+		cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
+		debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+			__func__, index, cumul_size);
+		if (cumul_size == last_cumul_size)
+			continue;	/* not populated */
+
+		csrow->first_page = last_cumul_size;
+		csrow->last_page = cumul_size - 1;
+		csrow->nr_pages = cumul_size - last_cumul_size;
+		last_cumul_size = cumul_size;
+		csrow->grain = 1 << 12;	/* 4KiB - resolution of CELOG */
+		csrow->mtype = MEM_RDDR;	/* only one type supported */
+		csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
+
+		/*
+		 * if single channel or x8 devices then SECDED
+		 * if dual channel and x4 then S4ECD4ED
+		 */
+		if (drc_ddim) {
+			if (drc_chan && mem_dev) {
+				csrow->edac_mode = EDAC_S4ECD4ED;
+				mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
+			} else {
+				csrow->edac_mode = EDAC_SECDED;
+				mci->edac_cap |= EDAC_FLAG_SECDED;
+			}
+		} else
+			csrow->edac_mode = EDAC_NONE;
+	}
+
+	/* Fill in the memory map table */
+	{
+		u8 value;
+		u8 last = 0;
+		u8 row = 0;
+		for (index = 0; index < 8; index += 2) {
+
+			pci_read_config_byte(mci->pdev, E752X_DRB + index,
+					     &value);
+			/* test if there is a dimm in this slot */
+			if (value == last) {
+				/* no dimm in the slot, so flag it as empty */
+				pvt->map[index] = 0xff;
+				pvt->map[index + 1] = 0xff;
+			} else {	/* there is a dimm in the slot */
+				pvt->map[index] = row;
+				row++;
+				last = value;
+				/* test the next value to see if the dimm is
+				   double sided */
+				pci_read_config_byte(mci->pdev,
+						     E752X_DRB + index + 1,
+						     &value);
+				pvt->map[index + 1] = (value == last) ?
+				    0xff :	/* the dimm is single sided,
+						   so flag as empty */
+				    row;	/* this is a double sided dimm
+						   to save the next row # */
+				row++;
+				last = value;
+			}
+		}
+	}
+
+	/* set the map type.  1 = normal, 0 = reversed */
+	pci_read_config_byte(mci->pdev, E752X_DRM, &stat8);
+	pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f));
+
+	mci->edac_cap |= EDAC_FLAG_NONE;
+
+	debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
+		__func__);
+	/* load the top of low memory, remap base, and remap limit vars */
+	pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data);
+	pvt->tolm = ((u32) pci_data) << 4;
+	pci_read_config_word(mci->pdev, E752X_REMAPBASE, &pci_data);
+	pvt->remapbase = ((u32) pci_data) << 14;
+	pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data);
+	pvt->remaplimit = ((u32) pci_data) << 14;
+	printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+	       pvt->remapbase, pvt->remaplimit);
+
+	if (edac_mc_add_mc(mci)) {
+		debugf3("MC: " __FILE__
+			": %s(): failed edac_mc_add_mc()\n",
+			__func__);
+		goto fail;
+	}
+
+	/* Walk through the PCI table and clear errors */
+	switch (dev_idx) {
+	case E7520:
+		dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_7520_0, NULL);
+		break;
+	case E7525:
+		dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_7525_0, NULL);
+		break;
+	case E7320:
+		dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_7320_0, NULL);
+		break;
+	}
+
+
+	pvt->dev_d0f0 = dev;
+	for (pres_dev = dev;
+	     ((struct pci_dev *) pres_dev->global_list.next != dev);
+	     pres_dev = (struct pci_dev *) pres_dev->global_list.next) {
+		pci_read_config_dword(pres_dev, PCI_COMMAND, &stat32);
+		stat = (u16) (stat32 >> 16);
+		/* clear any error bits */
+		if (stat32 & ((1 << 6) + (1 << 8)))
+			pci_write_config_word(pres_dev, PCI_STATUS, stat);
+	}
+	/* find the error reporting device and clear errors */
+	dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck);
+	/* Turn off error disable & SMI in case the BIOS turned it on */
+	pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
+	pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
+	pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00);
+	pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00);
+	pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00);
+	pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00);
+	pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00);
+	pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00);
+	/* clear other MCH errors */
+	pci_read_config_dword(dev, E752X_FERR_GLOBAL, &stat32);
+	pci_write_config_dword(dev, E752X_FERR_GLOBAL, stat32);
+	pci_read_config_dword(dev, E752X_NERR_GLOBAL, &stat32);
+	pci_write_config_dword(dev, E752X_NERR_GLOBAL, stat32);
+	pci_read_config_byte(dev, E752X_HI_FERR, &stat8);
+	pci_write_config_byte(dev, E752X_HI_FERR, stat8);
+	pci_read_config_byte(dev, E752X_HI_NERR, &stat8);
+	pci_write_config_byte(dev, E752X_HI_NERR, stat8);
+	pci_read_config_dword(dev, E752X_SYSBUS_FERR, &stat32);
+	pci_write_config_dword(dev, E752X_SYSBUS_FERR, stat32);
+	pci_read_config_byte(dev, E752X_BUF_FERR, &stat8);
+	pci_write_config_byte(dev, E752X_BUF_FERR, stat8);
+	pci_read_config_byte(dev, E752X_BUF_NERR, &stat8);
+	pci_write_config_byte(dev, E752X_BUF_NERR, stat8);
+	pci_read_config_word(dev, E752X_DRAM_FERR, &stat16);
+	pci_write_config_word(dev, E752X_DRAM_FERR, stat16);
+	pci_read_config_word(dev, E752X_DRAM_NERR, &stat16);
+	pci_write_config_word(dev, E752X_DRAM_NERR, stat16);
+
+	/* get this far and it's successful */
+	debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+	return 0;
+
+fail:
+	if (mci) {
+		if (pvt->dev_d0f0)
+			pci_dev_put(pvt->dev_d0f0);
+		if (pvt->dev_d0f1)
+			pci_dev_put(pvt->dev_d0f1);
+		if (pvt->bridge_ck)
+			pci_dev_put(pvt->bridge_ck);
+		edac_mc_free(mci);
+	}
+	return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit e752x_init_one(struct pci_dev *pdev,
+				    const struct pci_device_id *ent)
+{
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* wake up and enable device */
+	if(pci_enable_device(pdev) < 0)
+		return -EIO;
+	return e752x_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit e752x_remove_one(struct pci_dev *pdev)
+{
+	struct mem_ctl_info *mci;
+	struct e752x_pvt *pvt;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+
+	if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+		return;
+
+	if (edac_mc_del_mc(mci))
+		return;
+
+	pvt = (struct e752x_pvt *) mci->pvt_info;
+	pci_dev_put(pvt->dev_d0f0);
+	pci_dev_put(pvt->dev_d0f1);
+	pci_dev_put(pvt->bridge_ck);
+	edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
+	{PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 E7520},
+	{PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 E7525},
+	{PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 E7320},
+	{0,}			/* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, e752x_pci_tbl);
+
+
+static struct pci_driver e752x_driver = {
+	.name = BS_MOD_STR,
+	.probe = e752x_init_one,
+	.remove = __devexit_p(e752x_remove_one),
+	.id_table = e752x_pci_tbl,
+};
+
+
+static int __init e752x_init(void)
+{
+	int pci_rc;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	pci_rc = pci_register_driver(&e752x_driver);
+	return (pci_rc < 0) ? pci_rc : 0;
+}
+
+
+static void __exit e752x_exit(void)
+{
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	pci_unregister_driver(&e752x_driver);
+}
+
+
+module_init(e752x_init);
+module_exit(e752x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
+MODULE_DESCRIPTION("MC support for Intel e752x memory controllers");
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c
new file mode 100644
index 0000000..d5e320d
--- /dev/null
+++ b/drivers/edac/e7xxx_edac.c
@@ -0,0 +1,558 @@
+/*
+ * Intel e7xxx Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * See "enum e7xxx_chips" below for supported chipsets
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ *	http://www.anime.net/~goemon/linux-ecc/
+ *
+ * Contributors:
+ * 	Eric Biederman (Linux Networx)
+ * 	Tom Zimmerman (Linux Networx)
+ * 	Jim Garlick (Lawrence Livermore National Labs)
+ *	Dave Peterson (Lawrence Livermore National Labs)
+ *	That One Guy (Some other place)
+ *	Wang Zhenyu (intel.com)
+ *
+ * $Id: edac_e7xxx.c,v 1.5.2.9 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_7205_0
+#define PCI_DEVICE_ID_INTEL_7205_0	0x255d
+#endif				/* PCI_DEVICE_ID_INTEL_7205_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7205_1_ERR
+#define PCI_DEVICE_ID_INTEL_7205_1_ERR	0x2551
+#endif				/* PCI_DEVICE_ID_INTEL_7205_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7500_0
+#define PCI_DEVICE_ID_INTEL_7500_0	0x2540
+#endif				/* PCI_DEVICE_ID_INTEL_7500_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7500_1_ERR
+#define PCI_DEVICE_ID_INTEL_7500_1_ERR	0x2541
+#endif				/* PCI_DEVICE_ID_INTEL_7500_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7501_0
+#define PCI_DEVICE_ID_INTEL_7501_0	0x254c
+#endif				/* PCI_DEVICE_ID_INTEL_7501_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7501_1_ERR
+#define PCI_DEVICE_ID_INTEL_7501_1_ERR	0x2541
+#endif				/* PCI_DEVICE_ID_INTEL_7501_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7505_0
+#define PCI_DEVICE_ID_INTEL_7505_0	0x2550
+#endif				/* PCI_DEVICE_ID_INTEL_7505_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7505_1_ERR
+#define PCI_DEVICE_ID_INTEL_7505_1_ERR	0x2551
+#endif				/* PCI_DEVICE_ID_INTEL_7505_1_ERR */
+
+
+#define E7XXX_NR_CSROWS		8	/* number of csrows */
+#define E7XXX_NR_DIMMS		8	/* FIXME - is this correct? */
+
+
+/* E7XXX register addresses - device 0 function 0 */
+#define E7XXX_DRB		0x60	/* DRAM row boundary register (8b) */
+#define E7XXX_DRA		0x70	/* DRAM row attribute register (8b) */
+					/*
+					 * 31   Device width row 7 0=x8 1=x4
+					 * 27   Device width row 6
+					 * 23   Device width row 5
+					 * 19   Device width row 4
+					 * 15   Device width row 3
+					 * 11   Device width row 2
+					 *  7   Device width row 1
+					 *  3   Device width row 0
+					 */
+#define E7XXX_DRC		0x7C	/* DRAM controller mode reg (32b) */
+					/*
+					 * 22    Number channels 0=1,1=2
+					 * 19:18 DRB Granularity 32/64MB
+					 */
+#define E7XXX_TOLM		0xC4	/* DRAM top of low memory reg (16b) */
+#define E7XXX_REMAPBASE		0xC6	/* DRAM remap base address reg (16b) */
+#define E7XXX_REMAPLIMIT	0xC8	/* DRAM remap limit address reg (16b) */
+
+/* E7XXX register addresses - device 0 function 1 */
+#define E7XXX_DRAM_FERR		0x80	/* DRAM first error register (8b) */
+#define E7XXX_DRAM_NERR		0x82	/* DRAM next error register (8b) */
+#define E7XXX_DRAM_CELOG_ADD	0xA0	/* DRAM first correctable memory */
+					/*     error address register (32b) */
+					/*
+					 * 31:28 Reserved
+					 * 27:6  CE address (4k block 33:12)
+					 *  5:0  Reserved
+					 */
+#define E7XXX_DRAM_UELOG_ADD	0xB0	/* DRAM first uncorrectable memory */
+					/*     error address register (32b) */
+					/*
+					 * 31:28 Reserved
+					 * 27:6  CE address (4k block 33:12)
+					 *  5:0  Reserved
+					 */
+#define E7XXX_DRAM_CELOG_SYNDROME 0xD0	/* DRAM first correctable memory */
+					/*     error syndrome register (16b) */
+
+enum e7xxx_chips {
+	E7500 = 0,
+	E7501,
+	E7505,
+	E7205,
+};
+
+
+struct e7xxx_pvt {
+	struct pci_dev *bridge_ck;
+	u32 tolm;
+	u32 remapbase;
+	u32 remaplimit;
+	const struct e7xxx_dev_info *dev_info;
+};
+
+
+struct e7xxx_dev_info {
+	u16 err_dev;
+	const char *ctl_name;
+};
+
+
+struct e7xxx_error_info {
+	u8 dram_ferr;
+	u8 dram_nerr;
+	u32 dram_celog_add;
+	u16 dram_celog_syndrome;
+	u32 dram_uelog_add;
+};
+
+static const struct e7xxx_dev_info e7xxx_devs[] = {
+	[E7500] = {
+		   .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR,
+		   .ctl_name = "E7500"},
+	[E7501] = {
+		   .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR,
+		   .ctl_name = "E7501"},
+	[E7505] = {
+		   .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR,
+		   .ctl_name = "E7505"},
+	[E7205] = {
+		   .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR,
+		   .ctl_name = "E7205"},
+};
+
+
+/* FIXME - is this valid for both SECDED and S4ECD4ED? */
+static inline int e7xxx_find_channel(u16 syndrome)
+{
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	if ((syndrome & 0xff00) == 0)
+		return 0;
+	if ((syndrome & 0x00ff) == 0)
+		return 1;
+	if ((syndrome & 0xf000) == 0 || (syndrome & 0x0f00) == 0)
+		return 0;
+	return 1;
+}
+
+
+static unsigned long
+ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page)
+{
+	u32 remap;
+	struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	if ((page < pvt->tolm) ||
+	    ((page >= 0x100000) && (page < pvt->remapbase)))
+		return page;
+	remap = (page - pvt->tolm) + pvt->remapbase;
+	if (remap < pvt->remaplimit)
+		return remap;
+	printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+	return pvt->tolm - 1;
+}
+
+
+static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+{
+	u32 error_1b, page;
+	u16 syndrome;
+	int row;
+	int channel;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* read the error address */
+	error_1b = info->dram_celog_add;
+	/* FIXME - should use PAGE_SHIFT */
+	page = error_1b >> 6;	/* convert the address to 4k page */
+	/* read the syndrome */
+	syndrome = info->dram_celog_syndrome;
+	/* FIXME - check for -1 */
+	row = edac_mc_find_csrow_by_page(mci, page);
+	/* convert syndrome to channel */
+	channel = e7xxx_find_channel(syndrome);
+	edac_mc_handle_ce(mci, page, 0, syndrome, row, channel,
+			       "e7xxx CE");
+}
+
+
+static void process_ce_no_info(struct mem_ctl_info *mci)
+{
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow");
+}
+
+
+static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+{
+	u32 error_2b, block_page;
+	int row;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* read the error address */
+	error_2b = info->dram_uelog_add;
+	/* FIXME - should use PAGE_SHIFT */
+	block_page = error_2b >> 6;	/* convert to 4k address */
+	row = edac_mc_find_csrow_by_page(mci, block_page);
+	edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE");
+}
+
+
+static void process_ue_no_info(struct mem_ctl_info *mci)
+{
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow");
+}
+
+
+static void e7xxx_get_error_info (struct mem_ctl_info *mci,
+		struct e7xxx_error_info *info)
+{
+	struct e7xxx_pvt *pvt;
+
+	pvt = (struct e7xxx_pvt *) mci->pvt_info;
+	pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR,
+	    &info->dram_ferr);
+	pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR,
+	    &info->dram_nerr);
+
+	if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) {
+		pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD,
+		    &info->dram_celog_add);
+		pci_read_config_word(pvt->bridge_ck,
+		    E7XXX_DRAM_CELOG_SYNDROME, &info->dram_celog_syndrome);
+	}
+
+	if ((info->dram_ferr & 2) || (info->dram_nerr & 2))
+		pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD,
+		    &info->dram_uelog_add);
+
+	if (info->dram_ferr & 3)
+		pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03,
+		    0x03);
+
+	if (info->dram_nerr & 3)
+		pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03,
+		    0x03);
+}
+
+
+static int e7xxx_process_error_info (struct mem_ctl_info *mci,
+		struct e7xxx_error_info *info, int handle_errors)
+{
+	int error_found;
+
+	error_found = 0;
+
+	/* decode and report errors */
+	if (info->dram_ferr & 1) {	/* check first error correctable */
+		error_found = 1;
+
+		if (handle_errors)
+			process_ce(mci, info);
+	}
+
+	if (info->dram_ferr & 2) {	/* check first error uncorrectable */
+		error_found = 1;
+
+		if (handle_errors)
+			process_ue(mci, info);
+	}
+
+	if (info->dram_nerr & 1) {	/* check next error correctable */
+		error_found = 1;
+
+		if (handle_errors) {
+			if (info->dram_ferr & 1)
+				process_ce_no_info(mci);
+			else
+				process_ce(mci, info);
+		}
+	}
+
+	if (info->dram_nerr & 2) {	/* check next error uncorrectable */
+		error_found = 1;
+
+		if (handle_errors) {
+			if (info->dram_ferr & 2)
+				process_ue_no_info(mci);
+			else
+				process_ue(mci, info);
+		}
+	}
+
+	return error_found;
+}
+
+
+static void e7xxx_check(struct mem_ctl_info *mci)
+{
+	struct e7xxx_error_info info;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	e7xxx_get_error_info(mci, &info);
+	e7xxx_process_error_info(mci, &info, 1);
+}
+
+
+static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
+{
+	int rc = -ENODEV;
+	int index;
+	u16 pci_data;
+	struct mem_ctl_info *mci = NULL;
+	struct e7xxx_pvt *pvt = NULL;
+	u32 drc;
+	int drc_chan = 1;	/* Number of channels 0=1chan,1=2chan */
+	int drc_drbg = 1;	/* DRB granularity 0=32mb,1=64mb */
+	int drc_ddim;		/* DRAM Data Integrity Mode 0=none,2=edac */
+	u32 dra;
+	unsigned long last_cumul_size;
+
+
+	debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+
+	/* need to find out the number of channels */
+	pci_read_config_dword(pdev, E7XXX_DRC, &drc);
+	/* only e7501 can be single channel */
+	if (dev_idx == E7501) {
+		drc_chan = ((drc >> 22) & 0x1);
+		drc_drbg = (drc >> 18) & 0x3;
+	}
+	drc_ddim = (drc >> 20) & 0x3;
+
+	mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1);
+
+	if (mci == NULL) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+	mci->mtype_cap = MEM_FLAG_RDDR;
+	mci->edac_ctl_cap =
+	    EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED;
+	/* FIXME - what if different memory types are in different csrows? */
+	mci->mod_name = BS_MOD_STR;
+	mci->mod_ver = "$Revision: 1.5.2.9 $";
+	mci->pdev = pdev;
+
+	debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+	pvt = (struct e7xxx_pvt *) mci->pvt_info;
+	pvt->dev_info = &e7xxx_devs[dev_idx];
+	pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
+					 pvt->dev_info->err_dev,
+					 pvt->bridge_ck);
+	if (!pvt->bridge_ck) {
+		printk(KERN_ERR
+		       "MC: error reporting device not found:"
+		       "vendor %x device 0x%x (broken BIOS?)\n",
+		       PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev);
+		goto fail;
+	}
+
+	debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+	mci->ctl_name = pvt->dev_info->ctl_name;
+
+	mci->edac_check = e7xxx_check;
+	mci->ctl_page_to_phys = ctl_page_to_phys;
+
+	/* find out the device types */
+	pci_read_config_dword(pdev, E7XXX_DRA, &dra);
+
+	/*
+	 * The dram row boundary (DRB) reg values are boundary address
+	 * for each DRAM row with a granularity of 32 or 64MB (single/dual
+	 * channel operation).  DRB regs are cumulative; therefore DRB7 will
+	 * contain the total memory contained in all eight rows.
+	 */
+	for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+		u8 value;
+		u32 cumul_size;
+		/* mem_dev 0=x8, 1=x4 */
+		int mem_dev = (dra >> (index * 4 + 3)) & 0x1;
+		struct csrow_info *csrow = &mci->csrows[index];
+
+		pci_read_config_byte(mci->pdev, E7XXX_DRB + index, &value);
+		/* convert a 64 or 32 MiB DRB to a page size. */
+		cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
+		debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+			__func__, index, cumul_size);
+		if (cumul_size == last_cumul_size)
+			continue;	/* not populated */
+
+		csrow->first_page = last_cumul_size;
+		csrow->last_page = cumul_size - 1;
+		csrow->nr_pages = cumul_size - last_cumul_size;
+		last_cumul_size = cumul_size;
+		csrow->grain = 1 << 12;	/* 4KiB - resolution of CELOG */
+		csrow->mtype = MEM_RDDR;	/* only one type supported */
+		csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
+
+		/*
+		 * if single channel or x8 devices then SECDED
+		 * if dual channel and x4 then S4ECD4ED
+		 */
+		if (drc_ddim) {
+			if (drc_chan && mem_dev) {
+				csrow->edac_mode = EDAC_S4ECD4ED;
+				mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
+			} else {
+				csrow->edac_mode = EDAC_SECDED;
+				mci->edac_cap |= EDAC_FLAG_SECDED;
+			}
+		} else
+			csrow->edac_mode = EDAC_NONE;
+	}
+
+	mci->edac_cap |= EDAC_FLAG_NONE;
+
+	debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
+		__func__);
+	/* load the top of low memory, remap base, and remap limit vars */
+	pci_read_config_word(mci->pdev, E7XXX_TOLM, &pci_data);
+	pvt->tolm = ((u32) pci_data) << 4;
+	pci_read_config_word(mci->pdev, E7XXX_REMAPBASE, &pci_data);
+	pvt->remapbase = ((u32) pci_data) << 14;
+	pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data);
+	pvt->remaplimit = ((u32) pci_data) << 14;
+	printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+	       pvt->remapbase, pvt->remaplimit);
+
+	/* clear any pending errors, or initial state bits */
+	pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03);
+	pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03);
+
+	if (edac_mc_add_mc(mci) != 0) {
+		debugf3("MC: " __FILE__
+			": %s(): failed edac_mc_add_mc()\n",
+			__func__);
+		goto fail;
+	}
+
+	/* get this far and it's successful */
+	debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+	return 0;
+
+fail:
+	if (mci != NULL) {
+		if(pvt != NULL && pvt->bridge_ck)
+			pci_dev_put(pvt->bridge_ck);
+		edac_mc_free(mci);
+	}
+
+	return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit
+e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* wake up and enable device */
+	return pci_enable_device(pdev) ?
+	    -EIO : e7xxx_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
+{
+	struct mem_ctl_info *mci;
+	struct e7xxx_pvt *pvt;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+
+	if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) &&
+	    edac_mc_del_mc(mci)) {
+		pvt = (struct e7xxx_pvt *) mci->pvt_info;
+		pci_dev_put(pvt->bridge_ck);
+		edac_mc_free(mci);
+	}
+}
+
+
+static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = {
+	{PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 E7205},
+	{PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 E7500},
+	{PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 E7501},
+	{PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 E7505},
+	{0,}			/* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl);
+
+
+static struct pci_driver e7xxx_driver = {
+	.name = BS_MOD_STR,
+	.probe = e7xxx_init_one,
+	.remove = __devexit_p(e7xxx_remove_one),
+	.id_table = e7xxx_pci_tbl,
+};
+
+
+static int __init e7xxx_init(void)
+{
+	return pci_register_driver(&e7xxx_driver);
+}
+
+
+static void __exit e7xxx_exit(void)
+{
+	pci_unregister_driver(&e7xxx_driver);
+}
+
+module_init(e7xxx_init);
+module_exit(e7xxx_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
+	      "Based on.work by Dan Hollis et al");
+MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers");
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
new file mode 100644
index 0000000..b10ee46
--- /dev/null
+++ b/drivers/edac/edac_mc.c
@@ -0,0 +1,2208 @@
+/*
+ * edac_mc kernel module
+ * (C) 2005 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ *	http://www.anime.net/~goemon/linux-ecc/
+ *
+ * Modified by Dave Peterson and Doug Thompson
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/highmem.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/sysdev.h>
+#include <linux/ctype.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/edac.h>
+
+#include "edac_mc.h"
+
+#define	EDAC_MC_VERSION	"edac_mc  Ver: 2.0.0 " __DATE__
+
+#ifdef CONFIG_EDAC_DEBUG
+/* Values of 0 to 4 will generate output */
+int edac_debug_level = 1;
+EXPORT_SYMBOL(edac_debug_level);
+#endif
+
+/* EDAC Controls, setable by module parameter, and sysfs */
+static int log_ue = 1;
+static int log_ce = 1;
+static int panic_on_ue = 1;
+static int poll_msec = 1000;
+
+static int check_pci_parity = 0;	/* default YES check PCI parity */
+static int panic_on_pci_parity;		/* default no panic on PCI Parity */
+static atomic_t pci_parity_count = ATOMIC_INIT(0);
+
+/* lock to memory controller's control array */
+static DECLARE_MUTEX(mem_ctls_mutex);
+static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
+
+/* Structure of the whitelist and blacklist arrays */
+struct edac_pci_device_list {
+	unsigned int  vendor;		/* Vendor ID */
+	unsigned int  device;		/* Deviice ID */
+};
+
+
+#define MAX_LISTED_PCI_DEVICES		32
+
+/* List of PCI devices (vendor-id:device-id) that should be skipped */
+static struct edac_pci_device_list pci_blacklist[MAX_LISTED_PCI_DEVICES];
+static int pci_blacklist_count;
+
+/* List of PCI devices (vendor-id:device-id) that should be scanned */
+static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES];
+static int pci_whitelist_count ;
+
+/*  START sysfs data and methods */
+
+static const char *mem_types[] = {
+	[MEM_EMPTY] = "Empty",
+	[MEM_RESERVED] = "Reserved",
+	[MEM_UNKNOWN] = "Unknown",
+	[MEM_FPM] = "FPM",
+	[MEM_EDO] = "EDO",
+	[MEM_BEDO] = "BEDO",
+	[MEM_SDR] = "Unbuffered-SDR",
+	[MEM_RDR] = "Registered-SDR",
+	[MEM_DDR] = "Unbuffered-DDR",
+	[MEM_RDDR] = "Registered-DDR",
+	[MEM_RMBS] = "RMBS"
+};
+
+static const char *dev_types[] = {
+	[DEV_UNKNOWN] = "Unknown",
+	[DEV_X1] = "x1",
+	[DEV_X2] = "x2",
+	[DEV_X4] = "x4",
+	[DEV_X8] = "x8",
+	[DEV_X16] = "x16",
+	[DEV_X32] = "x32",
+	[DEV_X64] = "x64"
+};
+
+static const char *edac_caps[] = {
+	[EDAC_UNKNOWN] = "Unknown",
+	[EDAC_NONE] = "None",
+	[EDAC_RESERVED] = "Reserved",
+	[EDAC_PARITY] = "PARITY",
+	[EDAC_EC] = "EC",
+	[EDAC_SECDED] = "SECDED",
+	[EDAC_S2ECD2ED] = "S2ECD2ED",
+	[EDAC_S4ECD4ED] = "S4ECD4ED",
+	[EDAC_S8ECD8ED] = "S8ECD8ED",
+	[EDAC_S16ECD16ED] = "S16ECD16ED"
+};
+
+
+/* sysfs object: /sys/devices/system/edac */
+static struct sysdev_class edac_class = {
+	set_kset_name("edac"),
+};
+
+/* sysfs objects:
+ *	/sys/devices/system/edac/mc
+ *	/sys/devices/system/edac/pci
+ */
+static struct kobject edac_memctrl_kobj;
+static struct kobject edac_pci_kobj;
+
+/*
+ * /sys/devices/system/edac/mc;
+ * 	data structures and methods
+ */
+static ssize_t memctrl_string_show(void *ptr, char *buffer)
+{
+	char *value = (char*) ptr;
+	return sprintf(buffer, "%s\n", value);
+}
+
+static ssize_t memctrl_int_show(void *ptr, char *buffer)
+{
+	int *value = (int*) ptr;
+	return sprintf(buffer, "%d\n", *value);
+}
+
+static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
+{
+	int *value = (int*) ptr;
+
+	if (isdigit(*buffer))
+		*value = simple_strtoul(buffer, NULL, 0);
+
+	return count;
+}
+
+struct memctrl_dev_attribute {
+	struct attribute	attr;
+	void	*value;
+	ssize_t (*show)(void *,char *);
+	ssize_t (*store)(void *, const char *, size_t);
+};
+
+/* Set of show/store abstract level functions for memory control object */
+static ssize_t
+memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
+{
+	struct memctrl_dev_attribute *memctrl_dev;
+	memctrl_dev = (struct memctrl_dev_attribute*)attr;
+
+	if (memctrl_dev->show)
+		return memctrl_dev->show(memctrl_dev->value, buffer);
+	return -EIO;
+}
+
+static ssize_t
+memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
+			const char *buffer, size_t count)
+{
+	struct memctrl_dev_attribute *memctrl_dev;
+	memctrl_dev = (struct memctrl_dev_attribute*)attr;
+
+	if (memctrl_dev->store)
+		return memctrl_dev->store(memctrl_dev->value, buffer, count);
+	return -EIO;
+}
+
+static struct sysfs_ops memctrlfs_ops = {
+	.show   = memctrl_dev_show,
+	.store  = memctrl_dev_store
+};
+
+#define MEMCTRL_ATTR(_name,_mode,_show,_store)			\
+struct memctrl_dev_attribute attr_##_name = {			\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.value  = &_name,					\
+	.show   = _show,					\
+	.store  = _store,					\
+};
+
+#define MEMCTRL_STRING_ATTR(_name,_data,_mode,_show,_store)	\
+struct memctrl_dev_attribute attr_##_name = {			\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.value  = _data,					\
+	.show   = _show,					\
+	.store  = _store,					\
+};
+
+/* cwrow<id> attribute f*/
+MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL);
+
+/* csrow<id> control files */
+MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+
+
+/* Base Attributes of the memory ECC object */
+static struct memctrl_dev_attribute *memctrl_attr[] = {
+	&attr_panic_on_ue,
+	&attr_log_ue,
+	&attr_log_ce,
+	&attr_poll_msec,
+	&attr_mc_version,
+	NULL,
+};
+
+/* Main MC kobject release() function */
+static void edac_memctrl_master_release(struct kobject *kobj)
+{
+	debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_memctrl = {
+	.release	= edac_memctrl_master_release,
+	.sysfs_ops	= &memctrlfs_ops,
+	.default_attrs	= (struct attribute **) memctrl_attr,
+};
+
+
+/* Initialize the main sysfs entries for edac:
+ *   /sys/devices/system/edac
+ *
+ * and children
+ *
+ * Return:  0 SUCCESS
+ *         !0 FAILURE
+ */
+static int edac_sysfs_memctrl_setup(void)
+{
+	int err=0;
+
+	debugf1("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* create the /sys/devices/system/edac directory */
+	err = sysdev_class_register(&edac_class);
+	if (!err) {
+		/* Init the MC's kobject */
+		memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj));
+		kobject_init(&edac_memctrl_kobj);
+
+		edac_memctrl_kobj.parent = &edac_class.kset.kobj;
+		edac_memctrl_kobj.ktype = &ktype_memctrl;
+
+		/* generate sysfs "..../edac/mc"   */
+		err = kobject_set_name(&edac_memctrl_kobj,"mc");
+		if (!err) {
+			/* FIXME: maybe new sysdev_create_subdir() */
+			err = kobject_register(&edac_memctrl_kobj);
+			if (err) {
+				debugf1("Failed to register '.../edac/mc'\n");
+			} else {
+				debugf1("Registered '.../edac/mc' kobject\n");
+			}
+		}
+	} else {
+		debugf1(KERN_WARNING "__FILE__ %s() error=%d\n", __func__,err);
+	}
+
+	return err;
+}
+
+/*
+ * MC teardown:
+ *	the '..../edac/mc' kobject followed by '..../edac' itself
+ */
+static void edac_sysfs_memctrl_teardown(void)
+{
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* Unregister the MC's kobject */
+	kobject_unregister(&edac_memctrl_kobj);
+
+	/* release the master edac mc kobject */
+	kobject_put(&edac_memctrl_kobj);
+
+	/* Unregister the 'edac' object */
+	sysdev_class_unregister(&edac_class);
+}
+
+/*
+ * /sys/devices/system/edac/pci;
+ * 	data structures and methods
+ */
+
+struct list_control {
+	struct edac_pci_device_list *list;
+	int *count;
+};
+
+/* Output the list as:  vendor_id:device:id<,vendor_id:device_id> */
+static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
+{
+	struct list_control *listctl;
+	struct edac_pci_device_list *list;
+	char *p = buffer;
+	int len=0;
+	int i;
+
+	listctl = ptr;
+	list = listctl->list;
+
+	for (i = 0; i < *(listctl->count); i++, list++ ) {
+		if (len > 0)
+			len += snprintf(p + len, (PAGE_SIZE-len), ",");
+
+		len += snprintf(p + len,
+				(PAGE_SIZE-len),
+				"%x:%x",
+				list->vendor,list->device);
+	}
+
+	len += snprintf(p + len,(PAGE_SIZE-len), "\n");
+
+	return (ssize_t) len;
+}
+
+/**
+ *
+ * Scan string from **s to **e looking for one 'vendor:device' tuple
+ * where each field is a hex value
+ *
+ * return 0 if an entry is NOT found
+ * return 1 if an entry is found
+ *	fill in *vendor_id and *device_id with values found
+ *
+ * In both cases, make sure *s has been moved forward toward *e
+ */
+static int parse_one_device(const char **s,const char **e,
+	unsigned int *vendor_id, unsigned int *device_id)
+{
+	const char *runner, *p;
+
+	/* if null byte, we are done */
+	if (!**s) {
+		(*s)++;	/* keep *s moving */
+		return 0;
+	}
+
+	/* skip over newlines & whitespace */
+	if ((**s == '\n') || isspace(**s)) {
+		(*s)++;
+		return 0;
+	}
+
+	if (!isxdigit(**s)) {
+		(*s)++;
+		return 0;
+	}
+
+	/* parse vendor_id */
+	runner = *s;
+	while (runner < *e) {
+		/* scan for vendor:device delimiter */
+		if (*runner == ':') {
+			*vendor_id = simple_strtol((char*) *s, (char**) &p, 16);
+			runner = p + 1;
+			break;
+		}
+		runner++;
+	}
+
+	if (!isxdigit(*runner)) {
+		*s = ++runner;
+		return 0;
+	}
+
+	/* parse device_id */
+	if (runner < *e) {
+		*device_id = simple_strtol((char*)runner, (char**)&p, 16);
+		runner = p;
+	}
+
+	*s = runner;
+
+	return 1;
+}
+
+static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
+					size_t count)
+{
+	struct list_control *listctl;
+	struct edac_pci_device_list *list;
+	unsigned int vendor_id, device_id;
+	const char *s, *e;
+	int *index;
+
+	s = (char*)buffer;
+	e = s + count;
+
+	listctl = ptr;
+	list = listctl->list;
+	index = listctl->count;
+
+	*index = 0;
+	while (*index < MAX_LISTED_PCI_DEVICES) {
+
+		if (parse_one_device(&s,&e,&vendor_id,&device_id)) {
+			list[ *index ].vendor = vendor_id;
+			list[ *index ].device = device_id;
+			(*index)++;
+		}
+
+		/* check for all data consume */
+		if (s >= e)
+			break;
+	}
+
+	return count;
+}
+
+static ssize_t edac_pci_int_show(void *ptr, char *buffer)
+{
+	int *value = ptr;
+	return sprintf(buffer,"%d\n",*value);
+}
+
+static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count)
+{
+	int *value = ptr;
+
+	if (isdigit(*buffer))
+		*value = simple_strtoul(buffer,NULL,0);
+
+	return count;
+}
+
+struct edac_pci_dev_attribute {
+	struct attribute	attr;
+	void	*value;
+	ssize_t (*show)(void *,char *);
+	ssize_t (*store)(void *, const char *,size_t);
+};
+
+/* Set of show/store abstract level functions for PCI Parity object */
+static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
+				char *buffer)
+{
+	struct edac_pci_dev_attribute *edac_pci_dev;
+	edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
+
+	if (edac_pci_dev->show)
+		return edac_pci_dev->show(edac_pci_dev->value, buffer);
+	return -EIO;
+}
+
+static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr,
+				const char *buffer, size_t count)
+{
+	struct edac_pci_dev_attribute *edac_pci_dev;
+	edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
+
+	if (edac_pci_dev->show)
+		return edac_pci_dev->store(edac_pci_dev->value, buffer, count);
+	return -EIO;
+}
+
+static struct sysfs_ops edac_pci_sysfs_ops = {
+	.show   = edac_pci_dev_show,
+	.store  = edac_pci_dev_store
+};
+
+
+#define EDAC_PCI_ATTR(_name,_mode,_show,_store)			\
+struct edac_pci_dev_attribute edac_pci_attr_##_name = {		\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.value  = &_name,					\
+	.show   = _show,					\
+	.store  = _store,					\
+};
+
+#define EDAC_PCI_STRING_ATTR(_name,_data,_mode,_show,_store)	\
+struct edac_pci_dev_attribute edac_pci_attr_##_name = {		\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.value  = _data,					\
+	.show   = _show,					\
+	.store  = _store,					\
+};
+
+static struct list_control pci_whitelist_control = {
+	.list = pci_whitelist,
+	.count = &pci_whitelist_count
+};
+
+static struct list_control pci_blacklist_control = {
+	.list = pci_blacklist,
+	.count = &pci_blacklist_count
+};
+
+/* whitelist attribute */
+EDAC_PCI_STRING_ATTR(pci_parity_whitelist,
+	&pci_whitelist_control,
+	S_IRUGO|S_IWUSR,
+	edac_pci_list_string_show,
+	edac_pci_list_string_store);
+
+EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
+	&pci_blacklist_control,
+	S_IRUGO|S_IWUSR,
+	edac_pci_list_string_show,
+	edac_pci_list_string_store);
+
+/* PCI Parity control files */
+EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
+EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
+EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL);
+
+/* Base Attributes of the memory ECC object */
+static struct edac_pci_dev_attribute *edac_pci_attr[] = {
+	&edac_pci_attr_check_pci_parity,
+	&edac_pci_attr_panic_on_pci_parity,
+	&edac_pci_attr_pci_parity_count,
+	&edac_pci_attr_pci_parity_whitelist,
+	&edac_pci_attr_pci_parity_blacklist,
+	NULL,
+};
+
+/* No memory to release */
+static void edac_pci_release(struct kobject *kobj)
+{
+	debugf1("EDAC PCI: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_edac_pci = {
+	.release	= edac_pci_release,
+	.sysfs_ops	= &edac_pci_sysfs_ops,
+	.default_attrs	= (struct attribute **) edac_pci_attr,
+};
+
+/**
+ * edac_sysfs_pci_setup()
+ *
+ */
+static int edac_sysfs_pci_setup(void)
+{
+	int err;
+
+	debugf1("MC: " __FILE__ ": %s()\n", __func__);
+
+	memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj));
+
+	kobject_init(&edac_pci_kobj);
+	edac_pci_kobj.parent = &edac_class.kset.kobj;
+	edac_pci_kobj.ktype = &ktype_edac_pci;
+
+	err = kobject_set_name(&edac_pci_kobj, "pci");
+	if (!err) {
+		/* Instanstiate the csrow object */
+		/* FIXME: maybe new sysdev_create_subdir() */
+		err = kobject_register(&edac_pci_kobj);
+		if (err)
+			debugf1("Failed to register '.../edac/pci'\n");
+		else
+			debugf1("Registered '.../edac/pci' kobject\n");
+	}
+	return err;
+}
+
+
+static void edac_sysfs_pci_teardown(void)
+{
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	kobject_unregister(&edac_pci_kobj);
+	kobject_put(&edac_pci_kobj);
+}
+
+/* EDAC sysfs CSROW data structures and methods */
+
+/* Set of more detailed csrow<id> attribute show/store functions */
+static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data)
+{
+	ssize_t size = 0;
+
+	if (csrow->nr_channels > 0) {
+		size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n",
+			csrow->channels[0].label);
+	}
+	return size;
+}
+
+static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data)
+{
+	ssize_t size = 0;
+
+	if (csrow->nr_channels > 0) {
+		size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
+			csrow->channels[1].label);
+	}
+	return size;
+}
+
+static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
+			const char *data, size_t size)
+{
+	ssize_t max_size = 0;
+
+	if (csrow->nr_channels > 0) {
+		max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
+		strncpy(csrow->channels[0].label, data, max_size);
+		csrow->channels[0].label[max_size] = '\0';
+	}
+	return size;
+}
+
+static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
+			const char *data, size_t size)
+{
+	ssize_t max_size = 0;
+
+	if (csrow->nr_channels > 1) {
+		max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
+		strncpy(csrow->channels[1].label, data, max_size);
+		csrow->channels[1].label[max_size] = '\0';
+	}
+	return max_size;
+}
+
+static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data)
+{
+	return sprintf(data,"%u\n", csrow->ue_count);
+}
+
+static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data)
+{
+	return sprintf(data,"%u\n", csrow->ce_count);
+}
+
+static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data)
+{
+	ssize_t size = 0;
+
+	if (csrow->nr_channels > 0) {
+		size = sprintf(data,"%u\n", csrow->channels[0].ce_count);
+	}
+	return size;
+}
+
+static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data)
+{
+	ssize_t size = 0;
+
+	if (csrow->nr_channels > 1) {
+		size = sprintf(data,"%u\n", csrow->channels[1].ce_count);
+	}
+	return size;
+}
+
+static ssize_t csrow_size_show(struct csrow_info *csrow, char *data)
+{
+	return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages));
+}
+
+static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data)
+{
+	return sprintf(data,"%s\n", mem_types[csrow->mtype]);
+}
+
+static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data)
+{
+	return sprintf(data,"%s\n", dev_types[csrow->dtype]);
+}
+
+static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data)
+{
+	return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]);
+}
+
+struct csrowdev_attribute {
+	struct attribute	attr;
+	ssize_t (*show)(struct csrow_info *,char *);
+	ssize_t (*store)(struct csrow_info *, const char *,size_t);
+};
+
+#define to_csrow(k) container_of(k, struct csrow_info, kobj)
+#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr)
+
+/* Set of show/store higher level functions for csrow objects */
+static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr,
+				char *buffer)
+{
+	struct csrow_info *csrow = to_csrow(kobj);
+	struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
+
+	if (csrowdev_attr->show)
+		return csrowdev_attr->show(csrow, buffer);
+	return -EIO;
+}
+
+static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
+				const char *buffer, size_t count)
+{
+	struct csrow_info *csrow = to_csrow(kobj);
+	struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr);
+
+	if (csrowdev_attr->store)
+		return csrowdev_attr->store(csrow, buffer, count);
+	return -EIO;
+}
+
+static struct sysfs_ops csrowfs_ops = {
+	.show   = csrowdev_show,
+	.store  = csrowdev_store
+};
+
+#define CSROWDEV_ATTR(_name,_mode,_show,_store)			\
+struct csrowdev_attribute attr_##_name = {			\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.show   = _show,					\
+	.store  = _store,					\
+};
+
+/* cwrow<id>/attribute files */
+CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL);
+CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL);
+CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL);
+CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL);
+CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL);
+CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL);
+CSROWDEV_ATTR(ch0_ce_count,S_IRUGO,csrow_ch0_ce_count_show,NULL);
+CSROWDEV_ATTR(ch1_ce_count,S_IRUGO,csrow_ch1_ce_count_show,NULL);
+
+/* control/attribute files */
+CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR,
+		csrow_ch0_dimm_label_show,
+		csrow_ch0_dimm_label_store);
+CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
+		csrow_ch1_dimm_label_show,
+		csrow_ch1_dimm_label_store);
+
+
+/* Attributes of the CSROW<id> object */
+static struct csrowdev_attribute *csrow_attr[] = {
+	&attr_dev_type,
+	&attr_mem_type,
+	&attr_edac_mode,
+	&attr_size_mb,
+	&attr_ue_count,
+	&attr_ce_count,
+	&attr_ch0_ce_count,
+	&attr_ch1_ce_count,
+	&attr_ch0_dimm_label,
+	&attr_ch1_dimm_label,
+	NULL,
+};
+
+
+/* No memory to release */
+static void edac_csrow_instance_release(struct kobject *kobj)
+{
+	debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_csrow = {
+	.release	= edac_csrow_instance_release,
+	.sysfs_ops	= &csrowfs_ops,
+	.default_attrs	= (struct attribute **) csrow_attr,
+};
+
+/* Create a CSROW object under specifed edac_mc_device */
+static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
+				struct csrow_info *csrow, int index )
+{
+	int err = 0;
+
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	memset(&csrow->kobj, 0, sizeof(csrow->kobj));
+
+	/* generate ..../edac/mc/mc<id>/csrow<index>   */
+
+	kobject_init(&csrow->kobj);
+	csrow->kobj.parent = edac_mci_kobj;
+	csrow->kobj.ktype = &ktype_csrow;
+
+	/* name this instance of csrow<id> */
+	err = kobject_set_name(&csrow->kobj,"csrow%d",index);
+	if (!err) {
+		/* Instanstiate the csrow object */
+		err = kobject_register(&csrow->kobj);
+		if (err)
+			debugf0("Failed to register CSROW%d\n",index);
+		else
+			debugf0("Registered CSROW%d\n",index);
+	}
+
+	return err;
+}
+
+/* sysfs data structures and methods for the MCI kobjects */
+
+static ssize_t mci_reset_counters_store(struct mem_ctl_info  *mci,
+					const char *data, size_t count )
+{
+	int row, chan;
+
+	mci->ue_noinfo_count = 0;
+	mci->ce_noinfo_count = 0;
+	mci->ue_count = 0;
+	mci->ce_count = 0;
+	for (row = 0; row < mci->nr_csrows; row++) {
+		struct csrow_info *ri = &mci->csrows[row];
+
+		ri->ue_count = 0;
+		ri->ce_count = 0;
+		for (chan = 0; chan < ri->nr_channels; chan++)
+			ri->channels[chan].ce_count = 0;
+	}
+	mci->start_time = jiffies;
+
+	return count;
+}
+
+static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
+{
+	return sprintf(data,"%d\n", mci->ue_count);
+}
+
+static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data)
+{
+	return sprintf(data,"%d\n", mci->ce_count);
+}
+
+static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data)
+{
+	return sprintf(data,"%d\n", mci->ce_noinfo_count);
+}
+
+static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data)
+{
+	return sprintf(data,"%d\n", mci->ue_noinfo_count);
+}
+
+static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data)
+{
+	return sprintf(data,"%ld\n", (jiffies - mci->start_time) / HZ);
+}
+
+static ssize_t mci_mod_name_show(struct mem_ctl_info *mci, char *data)
+{
+	return sprintf(data,"%s %s\n", mci->mod_name, mci->mod_ver);
+}
+
+static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)
+{
+	return sprintf(data,"%s\n", mci->ctl_name);
+}
+
+static int mci_output_edac_cap(char *buf, unsigned long edac_cap)
+{
+	char *p = buf;
+	int bit_idx;
+
+	for (bit_idx = 0; bit_idx < 8 * sizeof(edac_cap); bit_idx++) {
+		if ((edac_cap >> bit_idx) & 0x1)
+			p += sprintf(p, "%s ", edac_caps[bit_idx]);
+	}
+
+	return p - buf;
+}
+
+static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data)
+{
+	char *p = data;
+
+	p += mci_output_edac_cap(p,mci->edac_ctl_cap);
+	p += sprintf(p, "\n");
+
+	return p - data;
+}
+
+static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci,
+						char *data)
+{
+	char *p = data;
+
+	p += mci_output_edac_cap(p,mci->edac_cap);
+	p += sprintf(p, "\n");
+
+	return p - data;
+}
+
+static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap)
+{
+	char *p = buf;
+	int bit_idx;
+
+	for (bit_idx = 0; bit_idx < 8 * sizeof(mtype_cap); bit_idx++) {
+		if ((mtype_cap >> bit_idx) & 0x1)
+			p += sprintf(p, "%s ", mem_types[bit_idx]);
+	}
+
+	return p - buf;
+}
+
+static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data)
+{
+	char *p = data;
+
+	p += mci_output_mtype_cap(p,mci->mtype_cap);
+	p += sprintf(p, "\n");
+
+	return p - data;
+}
+
+static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
+{
+	int total_pages, csrow_idx;
+
+	for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows;
+			csrow_idx++) {
+		struct csrow_info *csrow = &mci->csrows[csrow_idx];
+
+		if (!csrow->nr_pages)
+			continue;
+		total_pages += csrow->nr_pages;
+	}
+
+	return sprintf(data,"%u\n", PAGES_TO_MiB(total_pages));
+}
+
+struct mcidev_attribute {
+	struct attribute	attr;
+	ssize_t (*show)(struct mem_ctl_info *,char *);
+	ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
+};
+
+#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
+#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr)
+
+static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
+			char *buffer)
+{
+	struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
+	struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
+
+	if (mcidev_attr->show)
+		return mcidev_attr->show(mem_ctl_info, buffer);
+	return -EIO;
+}
+
+static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
+				const char *buffer, size_t count)
+{
+	struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
+	struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
+
+	if (mcidev_attr->store)
+		return mcidev_attr->store(mem_ctl_info, buffer, count);
+	return -EIO;
+}
+
+static struct sysfs_ops mci_ops = {
+	.show   = mcidev_show,
+	.store  = mcidev_store
+};
+
+#define MCIDEV_ATTR(_name,_mode,_show,_store)			\
+struct mcidev_attribute mci_attr_##_name = {			\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.show   = _show,					\
+	.store  = _store,					\
+};
+
+/* Control file */
+MCIDEV_ATTR(reset_counters,S_IWUSR,NULL,mci_reset_counters_store);
+
+/* Attribute files */
+MCIDEV_ATTR(mc_name,S_IRUGO,mci_ctl_name_show,NULL);
+MCIDEV_ATTR(module_name,S_IRUGO,mci_mod_name_show,NULL);
+MCIDEV_ATTR(edac_capability,S_IRUGO,mci_edac_capability_show,NULL);
+MCIDEV_ATTR(size_mb,S_IRUGO,mci_size_mb_show,NULL);
+MCIDEV_ATTR(seconds_since_reset,S_IRUGO,mci_seconds_show,NULL);
+MCIDEV_ATTR(ue_noinfo_count,S_IRUGO,mci_ue_noinfo_show,NULL);
+MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL);
+MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
+MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
+MCIDEV_ATTR(edac_current_capability,S_IRUGO,
+	mci_edac_current_capability_show,NULL);
+MCIDEV_ATTR(supported_mem_type,S_IRUGO,
+	mci_supported_mem_type_show,NULL);
+
+
+static struct mcidev_attribute *mci_attr[] = {
+	&mci_attr_reset_counters,
+	&mci_attr_module_name,
+	&mci_attr_mc_name,
+	&mci_attr_edac_capability,
+	&mci_attr_edac_current_capability,
+	&mci_attr_supported_mem_type,
+	&mci_attr_size_mb,
+	&mci_attr_seconds_since_reset,
+	&mci_attr_ue_noinfo_count,
+	&mci_attr_ce_noinfo_count,
+	&mci_attr_ue_count,
+	&mci_attr_ce_count,
+	NULL
+};
+
+
+/*
+ * Release of a MC controlling instance
+ */
+static void edac_mci_instance_release(struct kobject *kobj)
+{
+	struct mem_ctl_info *mci;
+	mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj);
+
+	debugf0("MC: " __FILE__ ": %s() idx=%d calling kfree\n",
+		__func__, mci->mc_idx);
+
+	kfree(mci);
+}
+
+static struct kobj_type ktype_mci = {
+	.release	= edac_mci_instance_release,
+	.sysfs_ops	= &mci_ops,
+	.default_attrs	= (struct attribute **) mci_attr,
+};
+
+#define EDAC_DEVICE_SYMLINK	"device"
+
+/*
+ * Create a new Memory Controller kobject instance,
+ *	mc<id> under the 'mc' directory
+ *
+ * Return:
+ *	0	Success
+ *	!0	Failure
+ */
+static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
+{
+	int i;
+	int err;
+	struct csrow_info *csrow;
+	struct kobject *edac_mci_kobj=&mci->edac_mci_kobj;
+
+	debugf0("MC: " __FILE__ ": %s() idx=%d\n", __func__, mci->mc_idx);
+
+	memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj));
+	kobject_init(edac_mci_kobj);
+
+	/* set the name of the mc<id> object */
+	err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx);
+	if (err)
+		return err;
+
+	/* link to our parent the '..../edac/mc' object */
+	edac_mci_kobj->parent = &edac_memctrl_kobj;
+	edac_mci_kobj->ktype = &ktype_mci;
+
+	/* register the mc<id> kobject */
+	err = kobject_register(edac_mci_kobj);
+	if (err)
+		return err;
+
+	/* create a symlink for the device */
+	err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj,
+				EDAC_DEVICE_SYMLINK);
+	if (err) {
+		kobject_unregister(edac_mci_kobj);
+		return err;
+	}
+
+	/* Make directories for each CSROW object
+	 * under the mc<id> kobject
+	 */
+	for (i = 0; i < mci->nr_csrows; i++) {
+
+		csrow = &mci->csrows[i];
+
+		/* Only expose populated CSROWs */
+		if (csrow->nr_pages > 0) {
+			err = edac_create_csrow_object(edac_mci_kobj,csrow,i);
+			if (err)
+				goto fail;
+		}
+	}
+
+	/* Mark this MCI instance as having sysfs entries */
+	mci->sysfs_active = MCI_SYSFS_ACTIVE;
+
+	return 0;
+
+
+	/* CSROW error: backout what has already been registered,  */
+fail:
+	for ( i--; i >= 0; i--) {
+		if (csrow->nr_pages > 0) {
+			kobject_unregister(&mci->csrows[i].kobj);
+			kobject_put(&mci->csrows[i].kobj);
+		}
+	}
+
+	kobject_unregister(edac_mci_kobj);
+	kobject_put(edac_mci_kobj);
+
+	return err;
+}
+
+/*
+ * remove a Memory Controller instance
+ */
+static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
+{
+	int i;
+
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* remove all csrow kobjects */
+	for (i = 0; i < mci->nr_csrows; i++) {
+		if (mci->csrows[i].nr_pages > 0)  {
+			kobject_unregister(&mci->csrows[i].kobj);
+			kobject_put(&mci->csrows[i].kobj);
+		}
+	}
+
+	sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
+
+	kobject_unregister(&mci->edac_mci_kobj);
+	kobject_put(&mci->edac_mci_kobj);
+}
+
+/* END OF sysfs data and methods */
+
+#ifdef CONFIG_EDAC_DEBUG
+
+EXPORT_SYMBOL(edac_mc_dump_channel);
+
+void edac_mc_dump_channel(struct channel_info *chan)
+{
+	debugf4("\tchannel = %p\n", chan);
+	debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
+	debugf4("\tchannel->ce_count = %d\n", chan->ce_count);
+	debugf4("\tchannel->label = '%s'\n", chan->label);
+	debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
+}
+
+
+EXPORT_SYMBOL(edac_mc_dump_csrow);
+
+void edac_mc_dump_csrow(struct csrow_info *csrow)
+{
+	debugf4("\tcsrow = %p\n", csrow);
+	debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx);
+	debugf4("\tcsrow->first_page = 0x%lx\n",
+		csrow->first_page);
+	debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page);
+	debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask);
+	debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages);
+	debugf4("\tcsrow->nr_channels = %d\n",
+		csrow->nr_channels);
+	debugf4("\tcsrow->channels = %p\n", csrow->channels);
+	debugf4("\tcsrow->mci = %p\n\n", csrow->mci);
+}
+
+
+EXPORT_SYMBOL(edac_mc_dump_mci);
+
+void edac_mc_dump_mci(struct mem_ctl_info *mci)
+{
+	debugf3("\tmci = %p\n", mci);
+	debugf3("\tmci->mtype_cap = %lx\n", mci->mtype_cap);
+	debugf3("\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap);
+	debugf3("\tmci->edac_cap = %lx\n", mci->edac_cap);
+	debugf4("\tmci->edac_check = %p\n", mci->edac_check);
+	debugf3("\tmci->nr_csrows = %d, csrows = %p\n",
+		mci->nr_csrows, mci->csrows);
+	debugf3("\tpdev = %p\n", mci->pdev);
+	debugf3("\tmod_name:ctl_name = %s:%s\n",
+		mci->mod_name, mci->ctl_name);
+	debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
+}
+
+
+#endif				/* CONFIG_EDAC_DEBUG */
+
+/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
+ * Adjust 'ptr' so that its alignment is at least as stringent as what the
+ * compiler would provide for X and return the aligned result.
+ *
+ * If 'size' is a constant, the compiler will optimize this whole function
+ * down to either a no-op or the addition of a constant to the value of 'ptr'.
+ */
+static inline char * align_ptr (void *ptr, unsigned size)
+{
+	unsigned align, r;
+
+	/* Here we assume that the alignment of a "long long" is the most
+	 * stringent alignment that the compiler will ever provide by default.
+	 * As far as I know, this is a reasonable assumption.
+	 */
+	if (size > sizeof(long))
+		align = sizeof(long long);
+	else if (size > sizeof(int))
+		align = sizeof(long);
+	else if (size > sizeof(short))
+		align = sizeof(int);
+	else if (size > sizeof(char))
+		align = sizeof(short);
+	else
+		return (char *) ptr;
+
+	r = size % align;
+
+	if (r == 0)
+		return (char *) ptr;
+
+	return (char *) (((unsigned long) ptr) + align - r);
+}
+
+
+EXPORT_SYMBOL(edac_mc_alloc);
+
+/**
+ * edac_mc_alloc: Allocate a struct mem_ctl_info structure
+ * @size_pvt:	size of private storage needed
+ * @nr_csrows:	Number of CWROWS needed for this MC
+ * @nr_chans:	Number of channels for the MC
+ *
+ * Everything is kmalloc'ed as one big chunk - more efficient.
+ * Only can be used if all structures have the same lifetime - otherwise
+ * you have to allocate and initialize your own structures.
+ *
+ * Use edac_mc_free() to free mc structures allocated by this function.
+ *
+ * Returns:
+ *	NULL allocation failed
+ *	struct mem_ctl_info pointer
+ */
+struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
+					unsigned nr_chans)
+{
+	struct mem_ctl_info *mci;
+	struct csrow_info *csi, *csrow;
+	struct channel_info *chi, *chp, *chan;
+	void *pvt;
+	unsigned size;
+	int row, chn;
+
+	/* Figure out the offsets of the various items from the start of an mc
+	 * structure.  We want the alignment of each item to be at least as
+	 * stringent as what the compiler would provide if we could simply
+	 * hardcode everything into a single struct.
+	 */
+	mci = (struct mem_ctl_info *) 0;
+	csi = (struct csrow_info *)align_ptr(&mci[1], sizeof(*csi));
+	chi = (struct channel_info *)
+			align_ptr(&csi[nr_csrows], sizeof(*chi));
+	pvt = align_ptr(&chi[nr_chans * nr_csrows], sz_pvt);
+	size = ((unsigned long) pvt) + sz_pvt;
+
+	if ((mci = kmalloc(size, GFP_KERNEL)) == NULL)
+		return NULL;
+
+	/* Adjust pointers so they point within the memory we just allocated
+	 * rather than an imaginary chunk of memory located at address 0.
+	 */
+	csi = (struct csrow_info *) (((char *) mci) + ((unsigned long) csi));
+	chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi));
+	pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL;
+
+	memset(mci, 0, size);	/* clear all fields */
+
+	mci->csrows = csi;
+	mci->pvt_info = pvt;
+	mci->nr_csrows = nr_csrows;
+
+	for (row = 0; row < nr_csrows; row++) {
+		csrow = &csi[row];
+		csrow->csrow_idx = row;
+		csrow->mci = mci;
+		csrow->nr_channels = nr_chans;
+		chp = &chi[row * nr_chans];
+		csrow->channels = chp;
+
+		for (chn = 0; chn < nr_chans; chn++) {
+			chan = &chp[chn];
+			chan->chan_idx = chn;
+			chan->csrow = csrow;
+		}
+	}
+
+	return mci;
+}
+
+
+EXPORT_SYMBOL(edac_mc_free);
+
+/**
+ * edac_mc_free:  Free a previously allocated 'mci' structure
+ * @mci: pointer to a struct mem_ctl_info structure
+ *
+ * Free up a previously allocated mci structure
+ * A MCI structure can be in 2 states after being allocated
+ * by edac_mc_alloc().
+ *	1) Allocated in a MC driver's probe, but not yet committed
+ *	2) Allocated and committed, by a call to  edac_mc_add_mc()
+ * edac_mc_add_mc() is the function that adds the sysfs entries
+ * thus, this free function must determine which state the 'mci'
+ * structure is in, then either free it directly or
+ * perform kobject cleanup by calling edac_remove_sysfs_mci_device().
+ *
+ * VOID Return
+ */
+void edac_mc_free(struct mem_ctl_info *mci)
+{
+	/* only if sysfs entries for this mci instance exist
+	 * do we remove them and defer the actual kfree via
+	 * the kobject 'release()' callback.
+ 	 *
+	 * Otherwise, do a straight kfree now.
+	 */
+	if (mci->sysfs_active == MCI_SYSFS_ACTIVE)
+		edac_remove_sysfs_mci_device(mci);
+	else
+		kfree(mci);
+}
+
+
+
+EXPORT_SYMBOL(edac_mc_find_mci_by_pdev);
+
+struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev)
+{
+	struct mem_ctl_info *mci;
+	struct list_head *item;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	list_for_each(item, &mc_devices) {
+		mci = list_entry(item, struct mem_ctl_info, link);
+
+		if (mci->pdev == pdev)
+			return mci;
+	}
+
+	return NULL;
+}
+
+static int add_mc_to_global_list (struct mem_ctl_info *mci)
+{
+	struct list_head *item, *insert_before;
+	struct mem_ctl_info *p;
+	int i;
+
+	if (list_empty(&mc_devices)) {
+		mci->mc_idx = 0;
+		insert_before = &mc_devices;
+	} else {
+		if (edac_mc_find_mci_by_pdev(mci->pdev)) {
+			printk(KERN_WARNING
+				"EDAC MC: %s (%s) %s %s already assigned %d\n",
+				mci->pdev->dev.bus_id, pci_name(mci->pdev),
+				mci->mod_name, mci->ctl_name, mci->mc_idx);
+			return 1;
+		}
+
+		insert_before = NULL;
+		i = 0;
+
+		list_for_each(item, &mc_devices) {
+			p = list_entry(item, struct mem_ctl_info, link);
+
+			if (p->mc_idx != i) {
+				insert_before = item;
+				break;
+			}
+
+			i++;
+		}
+
+		mci->mc_idx = i;
+
+		if (insert_before == NULL)
+			insert_before = &mc_devices;
+	}
+
+	list_add_tail_rcu(&mci->link, insert_before);
+	return 0;
+}
+
+
+
+EXPORT_SYMBOL(edac_mc_add_mc);
+
+/**
+ * edac_mc_add_mc: Insert the 'mci' structure into the mci global list
+ * @mci: pointer to the mci structure to be added to the list
+ *
+ * Return:
+ *	0	Success
+ *	!0	Failure
+ */
+
+/* FIXME - should a warning be printed if no error detection? correction? */
+int edac_mc_add_mc(struct mem_ctl_info *mci)
+{
+	int rc = 1;
+
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+#ifdef CONFIG_EDAC_DEBUG
+	if (edac_debug_level >= 3)
+		edac_mc_dump_mci(mci);
+	if (edac_debug_level >= 4) {
+		int i;
+
+		for (i = 0; i < mci->nr_csrows; i++) {
+			int j;
+			edac_mc_dump_csrow(&mci->csrows[i]);
+			for (j = 0; j < mci->csrows[i].nr_channels; j++)
+				edac_mc_dump_channel(&mci->csrows[i].
+							  channels[j]);
+		}
+	}
+#endif
+	down(&mem_ctls_mutex);
+
+	if (add_mc_to_global_list(mci))
+		goto finish;
+
+	/* set load time so that error rate can be tracked */
+	mci->start_time = jiffies;
+
+        if (edac_create_sysfs_mci_device(mci)) {
+                printk(KERN_WARNING
+                       "EDAC MC%d: failed to create sysfs device\n",
+                       mci->mc_idx);
+		/* FIXME - should there be an error code and unwind? */
+                goto finish;
+        }
+
+	/* Report action taken */
+	printk(KERN_INFO
+	       "EDAC MC%d: Giving out device to %s %s: PCI %s\n",
+	       mci->mc_idx, mci->mod_name, mci->ctl_name,
+	       pci_name(mci->pdev));
+
+
+	rc = 0;
+
+finish:
+	up(&mem_ctls_mutex);
+	return rc;
+}
+
+
+
+static void complete_mc_list_del (struct rcu_head *head)
+{
+	struct mem_ctl_info *mci;
+
+	mci = container_of(head, struct mem_ctl_info, rcu);
+	INIT_LIST_HEAD(&mci->link);
+	complete(&mci->complete);
+}
+
+static void del_mc_from_global_list (struct mem_ctl_info *mci)
+{
+	list_del_rcu(&mci->link);
+	init_completion(&mci->complete);
+	call_rcu(&mci->rcu, complete_mc_list_del);
+	wait_for_completion(&mci->complete);
+}
+
+EXPORT_SYMBOL(edac_mc_del_mc);
+
+/**
+ * edac_mc_del_mc:  Remove the specified mci structure from global list
+ * @mci:	Pointer to struct mem_ctl_info structure
+ *
+ * Returns:
+ *	0	Success
+ *	1 	Failure
+ */
+int edac_mc_del_mc(struct mem_ctl_info *mci)
+{
+	int rc = 1;
+
+	debugf0("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+	down(&mem_ctls_mutex);
+	del_mc_from_global_list(mci);
+	printk(KERN_INFO
+	       "EDAC MC%d: Removed device %d for %s %s: PCI %s\n",
+	       mci->mc_idx, mci->mc_idx, mci->mod_name, mci->ctl_name,
+	       pci_name(mci->pdev));
+	rc = 0;
+	up(&mem_ctls_mutex);
+
+	return rc;
+}
+
+
+EXPORT_SYMBOL(edac_mc_scrub_block);
+
+void edac_mc_scrub_block(unsigned long page, unsigned long offset,
+			      u32 size)
+{
+	struct page *pg;
+	void *virt_addr;
+	unsigned long flags = 0;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* ECC error page was not in our memory. Ignore it. */
+	if(!pfn_valid(page))
+		return;
+
+	/* Find the actual page structure then map it and fix */
+	pg = pfn_to_page(page);
+
+	if (PageHighMem(pg))
+		local_irq_save(flags);
+
+	virt_addr = kmap_atomic(pg, KM_BOUNCE_READ);
+
+	/* Perform architecture specific atomic scrub operation */
+	atomic_scrub(virt_addr + offset, size);
+
+	/* Unmap and complete */
+	kunmap_atomic(virt_addr, KM_BOUNCE_READ);
+
+	if (PageHighMem(pg))
+		local_irq_restore(flags);
+}
+
+
+/* FIXME - should return -1 */
+EXPORT_SYMBOL(edac_mc_find_csrow_by_page);
+
+int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
+				    unsigned long page)
+{
+	struct csrow_info *csrows = mci->csrows;
+	int row, i;
+
+	debugf1("MC%d: " __FILE__ ": %s(): 0x%lx\n", mci->mc_idx, __func__,
+		page);
+	row = -1;
+
+	for (i = 0; i < mci->nr_csrows; i++) {
+		struct csrow_info *csrow = &csrows[i];
+
+		if (csrow->nr_pages == 0)
+			continue;
+
+		debugf3("MC%d: " __FILE__
+			": %s(): first(0x%lx) page(0x%lx)"
+			" last(0x%lx) mask(0x%lx)\n", mci->mc_idx,
+			__func__, csrow->first_page, page,
+			csrow->last_page, csrow->page_mask);
+
+		if ((page >= csrow->first_page) &&
+		    (page <= csrow->last_page) &&
+		    ((page & csrow->page_mask) ==
+		     (csrow->first_page & csrow->page_mask))) {
+			row = i;
+			break;
+		}
+	}
+
+	if (row == -1)
+		printk(KERN_ERR
+		       "EDAC MC%d: could not look up page error address %lx\n",
+		       mci->mc_idx, (unsigned long) page);
+
+	return row;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ce);
+
+/* FIXME - setable log (warning/emerg) levels */
+/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */
+void edac_mc_handle_ce(struct mem_ctl_info *mci,
+			    unsigned long page_frame_number,
+			    unsigned long offset_in_page,
+			    unsigned long syndrome, int row, int channel,
+			    const char *msg)
+{
+	unsigned long remapped_page;
+
+	debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+
+	/* FIXME - maybe make panic on INTERNAL ERROR an option */
+	if (row >= mci->nr_csrows || row < 0) {
+		/* something is wrong */
+		printk(KERN_ERR
+		       "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
+		       mci->mc_idx, row, mci->nr_csrows);
+		edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+	if (channel >= mci->csrows[row].nr_channels || channel < 0) {
+		/* something is wrong */
+		printk(KERN_ERR
+		       "EDAC MC%d: INTERNAL ERROR: channel out of range "
+		       "(%d >= %d)\n",
+		       mci->mc_idx, channel, mci->csrows[row].nr_channels);
+		edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	if (log_ce)
+		/* FIXME - put in DIMM location */
+		printk(KERN_WARNING
+		       "EDAC MC%d: CE page 0x%lx, offset 0x%lx,"
+		       " grain %d, syndrome 0x%lx, row %d, channel %d,"
+		       " label \"%s\": %s\n", mci->mc_idx,
+		       page_frame_number, offset_in_page,
+		       mci->csrows[row].grain, syndrome, row, channel,
+		       mci->csrows[row].channels[channel].label, msg);
+
+	mci->ce_count++;
+	mci->csrows[row].ce_count++;
+	mci->csrows[row].channels[channel].ce_count++;
+
+	if (mci->scrub_mode & SCRUB_SW_SRC) {
+		/*
+		 * Some MC's can remap memory so that it is still available
+		 * at a different address when PCI devices map into memory.
+		 * MC's that can't do this lose the memory where PCI devices
+		 * are mapped.  This mapping is MC dependant and so we call
+		 * back into the MC driver for it to map the MC page to
+		 * a physical (CPU) page which can then be mapped to a virtual
+		 * page - which can then be scrubbed.
+		 */
+		remapped_page = mci->ctl_page_to_phys ?
+		    mci->ctl_page_to_phys(mci, page_frame_number) :
+		    page_frame_number;
+
+		edac_mc_scrub_block(remapped_page, offset_in_page,
+					 mci->csrows[row].grain);
+	}
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ce_no_info);
+
+void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
+				    const char *msg)
+{
+	if (log_ce)
+		printk(KERN_WARNING
+		       "EDAC MC%d: CE - no information available: %s\n",
+		       mci->mc_idx, msg);
+	mci->ce_noinfo_count++;
+	mci->ce_count++;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ue);
+
+void edac_mc_handle_ue(struct mem_ctl_info *mci,
+			    unsigned long page_frame_number,
+			    unsigned long offset_in_page, int row,
+			    const char *msg)
+{
+	int len = EDAC_MC_LABEL_LEN * 4;
+	char labels[len + 1];
+	char *pos = labels;
+	int chan;
+	int chars;
+
+	debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+
+	/* FIXME - maybe make panic on INTERNAL ERROR an option */
+	if (row >= mci->nr_csrows || row < 0) {
+		/* something is wrong */
+		printk(KERN_ERR
+		       "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
+		       mci->mc_idx, row, mci->nr_csrows);
+		edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	chars = snprintf(pos, len + 1, "%s",
+			 mci->csrows[row].channels[0].label);
+	len -= chars;
+	pos += chars;
+	for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0);
+	     chan++) {
+		chars = snprintf(pos, len + 1, ":%s",
+				 mci->csrows[row].channels[chan].label);
+		len -= chars;
+		pos += chars;
+	}
+
+	if (log_ue)
+		printk(KERN_EMERG
+		       "EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
+		       " labels \"%s\": %s\n", mci->mc_idx,
+		       page_frame_number, offset_in_page,
+		       mci->csrows[row].grain, row, labels, msg);
+
+	if (panic_on_ue)
+		panic
+		    ("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
+		     " labels \"%s\": %s\n", mci->mc_idx,
+		     page_frame_number, offset_in_page,
+		     mci->csrows[row].grain, row, labels, msg);
+
+	mci->ue_count++;
+	mci->csrows[row].ue_count++;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ue_no_info);
+
+void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
+				    const char *msg)
+{
+	if (panic_on_ue)
+		panic("EDAC MC%d: Uncorrected Error", mci->mc_idx);
+
+	if (log_ue)
+		printk(KERN_WARNING
+		       "EDAC MC%d: UE - no information available: %s\n",
+		       mci->mc_idx, msg);
+	mci->ue_noinfo_count++;
+	mci->ue_count++;
+}
+
+
+#ifdef CONFIG_PCI
+
+static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
+{
+	int where;
+	u16 status;
+
+	where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
+	pci_read_config_word(dev, where, &status);
+
+	/* If we get back 0xFFFF then we must suspect that the card has been pulled but
+	   the Linux PCI layer has not yet finished cleaning up. We don't want to report
+	   on such devices */
+
+	if (status == 0xFFFF) {
+		u32 sanity;
+		pci_read_config_dword(dev, 0, &sanity);
+		if (sanity == 0xFFFFFFFF)
+			return 0;
+	}
+	status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
+		  PCI_STATUS_PARITY;
+
+	if (status)
+		/* reset only the bits we are interested in */
+		pci_write_config_word(dev, where, status);
+
+	return status;
+}
+
+typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
+
+/* Clear any PCI parity errors logged by this device. */
+static void edac_pci_dev_parity_clear( struct pci_dev *dev )
+{
+	u8 header_type;
+
+	get_pci_parity_status(dev, 0);
+
+	/* read the device TYPE, looking for bridges */
+	pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+	if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE)
+		get_pci_parity_status(dev, 1);
+}
+
+/*
+ *  PCI Parity polling
+ *
+ */
+static void edac_pci_dev_parity_test(struct pci_dev *dev)
+{
+	u16 status;
+	u8  header_type;
+
+	/* read the STATUS register on this device
+	 */
+	status = get_pci_parity_status(dev, 0);
+
+	debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id );
+
+	/* check the status reg for errors */
+	if (status) {
+		if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
+			printk(KERN_CRIT
+			   	"EDAC PCI- "
+				"Signaled System Error on %s\n",
+				pci_name (dev));
+
+		if (status & (PCI_STATUS_PARITY)) {
+			printk(KERN_CRIT
+			   	"EDAC PCI- "
+				"Master Data Parity Error on %s\n",
+				pci_name (dev));
+
+			atomic_inc(&pci_parity_count);
+		}
+
+		if (status & (PCI_STATUS_DETECTED_PARITY)) {
+			printk(KERN_CRIT
+			   	"EDAC PCI- "
+				"Detected Parity Error on %s\n",
+				pci_name (dev));
+
+			atomic_inc(&pci_parity_count);
+		}
+	}
+
+	/* read the device TYPE, looking for bridges */
+	pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+	debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id );
+
+	if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+		/* On bridges, need to examine secondary status register  */
+		status = get_pci_parity_status(dev, 1);
+
+		debugf2("PCI SEC_STATUS= 0x%04x %s\n",
+				status, dev->dev.bus_id );
+
+		/* check the secondary status reg for errors */
+		if (status) {
+			if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
+				printk(KERN_CRIT
+					"EDAC PCI-Bridge- "
+					"Signaled System Error on %s\n",
+					pci_name (dev));
+
+			if (status & (PCI_STATUS_PARITY)) {
+				printk(KERN_CRIT
+					"EDAC PCI-Bridge- "
+					"Master Data Parity Error on %s\n",
+					pci_name (dev));
+
+				atomic_inc(&pci_parity_count);
+			}
+
+			if (status & (PCI_STATUS_DETECTED_PARITY)) {
+				printk(KERN_CRIT
+					"EDAC PCI-Bridge- "
+					"Detected Parity Error on %s\n",
+					pci_name (dev));
+
+				atomic_inc(&pci_parity_count);
+			}
+		}
+	}
+}
+
+/*
+ * check_dev_on_list: Scan for a PCI device on a white/black list
+ * @list:	an EDAC  &edac_pci_device_list  white/black list pointer
+ * @free_index:	index of next free entry on the list
+ * @pci_dev:	PCI Device pointer
+ *
+ * see if list contains the device.
+ *
+ * Returns:  	0 not found
+ *		1 found on list
+ */
+static int check_dev_on_list(struct edac_pci_device_list *list, int free_index,
+				struct pci_dev *dev)
+{
+        int i;
+        int rc = 0;     /* Assume not found */
+        unsigned short vendor=dev->vendor;
+        unsigned short device=dev->device;
+
+        /* Scan the list, looking for a vendor/device match
+         */
+        for (i = 0; i < free_index; i++, list++ ) {
+                if (    (list->vendor == vendor ) &&
+                        (list->device == device )) {
+                        rc = 1;
+                        break;
+                }
+        }
+
+        return rc;
+}
+
+/*
+ * pci_dev parity list iterator
+ * 	Scan the PCI device list for one iteration, looking for SERRORs
+ *	Master Parity ERRORS or Parity ERRORs on primary or secondary devices
+ */
+static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
+{
+	struct pci_dev *dev=NULL;
+
+	/* request for kernel access to the next PCI device, if any,
+	 * and while we are looking at it have its reference count
+	 * bumped until we are done with it
+	 */
+	while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+
+                /* if whitelist exists then it has priority, so only scan those
+                 * devices on the whitelist
+                 */
+                if (pci_whitelist_count > 0 ) {
+                        if (check_dev_on_list(pci_whitelist,
+					pci_whitelist_count, dev))
+				fn(dev);
+                } else {
+			/*
+			 * if no whitelist, then check if this devices is
+			 * blacklisted
+			 */
+                        if (!check_dev_on_list(pci_blacklist,
+					pci_blacklist_count, dev))
+				fn(dev);
+                }
+	}
+}
+
+static void do_pci_parity_check(void)
+{
+	unsigned long flags;
+	int before_count;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	if (!check_pci_parity)
+		return;
+
+	before_count = atomic_read(&pci_parity_count);
+
+	/* scan all PCI devices looking for a Parity Error on devices and
+	 * bridges
+	 */
+	local_irq_save(flags);
+	edac_pci_dev_parity_iterator(edac_pci_dev_parity_test);
+	local_irq_restore(flags);
+
+	/* Only if operator has selected panic on PCI Error */
+	if (panic_on_pci_parity) {
+		/* If the count is different 'after' from 'before' */
+		if (before_count != atomic_read(&pci_parity_count))
+			panic("EDAC: PCI Parity Error");
+	}
+}
+
+
+static inline void clear_pci_parity_errors(void)
+{
+	/* Clear any PCI bus parity errors that devices initially have logged
+	 * in their registers.
+	 */
+	edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
+}
+
+
+#else  /* CONFIG_PCI */
+
+
+static inline void do_pci_parity_check(void)
+{
+	/* no-op */
+}
+
+
+static inline void clear_pci_parity_errors(void)
+{
+	/* no-op */
+}
+
+
+#endif  /* CONFIG_PCI */
+
+/*
+ * Iterate over all MC instances and check for ECC, et al, errors
+ */
+static inline void check_mc_devices (void)
+{
+	unsigned long flags;
+	struct list_head *item;
+	struct mem_ctl_info *mci;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* during poll, have interrupts off */
+	local_irq_save(flags);
+
+	list_for_each(item, &mc_devices) {
+		mci = list_entry(item, struct mem_ctl_info, link);
+
+		if (mci->edac_check != NULL)
+			mci->edac_check(mci);
+	}
+
+	local_irq_restore(flags);
+}
+
+
+/*
+ * Check MC status every poll_msec.
+ * Check PCI status every poll_msec as well.
+ *
+ * This where the work gets done for edac.
+ *
+ * SMP safe, doesn't use NMI, and auto-rate-limits.
+ */
+static void do_edac_check(void)
+{
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	check_mc_devices();
+
+	do_pci_parity_check();
+}
+
+
+/*
+ * EDAC thread state information
+ */
+struct bs_thread_info
+{
+	struct task_struct *task;
+	struct completion *event;
+	char *name;
+	void (*run)(void);
+};
+
+static struct bs_thread_info bs_thread;
+
+/*
+ *  edac_kernel_thread
+ *      This the kernel thread that processes edac operations
+ *      in a normal thread environment
+ */
+static int edac_kernel_thread(void *arg)
+{
+	struct bs_thread_info *thread = (struct bs_thread_info *) arg;
+
+	/* detach thread */
+	daemonize(thread->name);
+
+	current->exit_signal = SIGCHLD;
+	allow_signal(SIGKILL);
+	thread->task = current;
+
+	/* indicate to starting task we have started */
+	complete(thread->event);
+
+	/* loop forever, until we are told to stop */
+	while(thread->run != NULL) {
+		void (*run)(void);
+
+		/* call the function to check the memory controllers */
+		run = thread->run;
+		if (run)
+			run();
+
+		if (signal_pending(current))
+			flush_signals(current);
+
+		/* ensure we are interruptable */
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		/* goto sleep for the interval */
+		schedule_timeout((HZ * poll_msec) / 1000);
+		try_to_freeze();
+	}
+
+	/* notify waiter that we are exiting */
+	complete(thread->event);
+
+	return 0;
+}
+
+/*
+ * edac_mc_init
+ *      module initialization entry point
+ */
+static int __init edac_mc_init(void)
+{
+	int ret;
+	struct completion event;
+
+	printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n");
+
+	/*
+	 * Harvest and clear any boot/initialization PCI parity errors
+	 *
+	 * FIXME: This only clears errors logged by devices present at time of
+	 * 	module initialization.  We should also do an initial clear
+	 *	of each newly hotplugged device.
+	 */
+	clear_pci_parity_errors();
+
+	/* perform check for first time to harvest boot leftovers */
+	do_edac_check();
+
+	/* Create the MC sysfs entires */
+	if (edac_sysfs_memctrl_setup()) {
+		printk(KERN_ERR "EDAC MC: Error initializing sysfs code\n");
+		return -ENODEV;
+	}
+
+	/* Create the PCI parity sysfs entries */
+	if (edac_sysfs_pci_setup()) {
+		edac_sysfs_memctrl_teardown();
+		printk(KERN_ERR "EDAC PCI: Error initializing sysfs code\n");
+		return -ENODEV;
+	}
+
+	/* Create our kernel thread */
+	init_completion(&event);
+	bs_thread.event = &event;
+	bs_thread.name = "kedac";
+	bs_thread.run = do_edac_check;
+
+	/* create our kernel thread */
+	ret = kernel_thread(edac_kernel_thread, &bs_thread, CLONE_KERNEL);
+	if (ret < 0) {
+		/* remove the sysfs entries */
+		edac_sysfs_memctrl_teardown();
+		edac_sysfs_pci_teardown();
+		return -ENOMEM;
+	}
+
+	/* wait for our kernel theard ack that it is up and running */
+	wait_for_completion(&event);
+
+	return 0;
+}
+
+
+/*
+ * edac_mc_exit()
+ *      module exit/termination functioni
+ */
+static void __exit edac_mc_exit(void)
+{
+	struct completion event;
+
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	init_completion(&event);
+	bs_thread.event = &event;
+
+	/* As soon as ->run is set to NULL, the task could disappear,
+	 * so we need to hold tasklist_lock until we have sent the signal
+	 */
+	read_lock(&tasklist_lock);
+	bs_thread.run = NULL;
+	send_sig(SIGKILL, bs_thread.task, 1);
+	read_unlock(&tasklist_lock);
+	wait_for_completion(&event);
+
+        /* tear down the sysfs device */
+	edac_sysfs_memctrl_teardown();
+	edac_sysfs_pci_teardown();
+}
+
+
+
+
+module_init(edac_mc_init);
+module_exit(edac_mc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
+	      "Based on.work by Dan Hollis et al");
+MODULE_DESCRIPTION("Core library routines for MC reporting");
+
+module_param(panic_on_ue, int, 0644);
+MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
+module_param(check_pci_parity, int, 0644);
+MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on");
+module_param(panic_on_pci_parity, int, 0644);
+MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on");
+module_param(log_ue, int, 0644);
+MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on");
+module_param(log_ce, int, 0644);
+MODULE_PARM_DESC(log_ce, "Log correctable error to console: 0=off 1=on");
+module_param(poll_msec, int, 0644);
+MODULE_PARM_DESC(poll_msec, "Polling period in milliseconds");
+#ifdef CONFIG_EDAC_DEBUG
+module_param(edac_debug_level, int, 0644);
+MODULE_PARM_DESC(edac_debug_level, "Debug level");
+#endif
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
new file mode 100644
index 0000000..75ecf48
--- /dev/null
+++ b/drivers/edac/edac_mc.h
@@ -0,0 +1,448 @@
+/*
+ * MC kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ *	http://www.anime.net/~goemon/linux-ecc/
+ *
+ * NMI handling support added by
+ *     Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
+ *
+ * $Id: edac_mc.h,v 1.4.2.10 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#ifndef _EDAC_MC_H_
+#define _EDAC_MC_H_
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/nmi.h>
+#include <linux/rcupdate.h>
+#include <linux/completion.h>
+#include <linux/kobject.h>
+
+
+#define EDAC_MC_LABEL_LEN	31
+#define MC_PROC_NAME_MAX_LEN 7
+
+#if PAGE_SHIFT < 20
+#define PAGES_TO_MiB( pages )	( ( pages ) >> ( 20 - PAGE_SHIFT ) )
+#else				/* PAGE_SHIFT > 20 */
+#define PAGES_TO_MiB( pages )	( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#endif
+
+#ifdef CONFIG_EDAC_DEBUG
+extern int edac_debug_level;
+#define edac_debug_printk(level, fmt, args...) \
+do { if (level <= edac_debug_level) printk(KERN_DEBUG fmt, ##args); } while(0)
+#define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ )
+#define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ )
+#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ )
+#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ )
+#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ )
+#else				/* !CONFIG_EDAC_DEBUG */
+#define debugf0( ... )
+#define debugf1( ... )
+#define debugf2( ... )
+#define debugf3( ... )
+#define debugf4( ... )
+#endif				/* !CONFIG_EDAC_DEBUG */
+
+
+#define bs_xstr(s) bs_str(s)
+#define bs_str(s) #s
+#define BS_MOD_STR bs_xstr(KBUILD_BASENAME)
+
+#define BIT(x) (1 << (x))
+
+#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, PCI_DEVICE_ID_ ## vend ## _ ## dev
+
+/* memory devices */
+enum dev_type {
+	DEV_UNKNOWN = 0,
+	DEV_X1,
+	DEV_X2,
+	DEV_X4,
+	DEV_X8,
+	DEV_X16,
+	DEV_X32,		/* Do these parts exist? */
+	DEV_X64			/* Do these parts exist? */
+};
+
+#define DEV_FLAG_UNKNOWN	BIT(DEV_UNKNOWN)
+#define DEV_FLAG_X1		BIT(DEV_X1)
+#define DEV_FLAG_X2		BIT(DEV_X2)
+#define DEV_FLAG_X4		BIT(DEV_X4)
+#define DEV_FLAG_X8		BIT(DEV_X8)
+#define DEV_FLAG_X16		BIT(DEV_X16)
+#define DEV_FLAG_X32		BIT(DEV_X32)
+#define DEV_FLAG_X64		BIT(DEV_X64)
+
+/* memory types */
+enum mem_type {
+	MEM_EMPTY = 0,		/* Empty csrow */
+	MEM_RESERVED,		/* Reserved csrow type */
+	MEM_UNKNOWN,		/* Unknown csrow type */
+	MEM_FPM,		/* Fast page mode */
+	MEM_EDO,		/* Extended data out */
+	MEM_BEDO,		/* Burst Extended data out */
+	MEM_SDR,		/* Single data rate SDRAM */
+	MEM_RDR,		/* Registered single data rate SDRAM */
+	MEM_DDR,		/* Double data rate SDRAM */
+	MEM_RDDR,		/* Registered Double data rate SDRAM */
+	MEM_RMBS		/* Rambus DRAM */
+};
+
+#define MEM_FLAG_EMPTY		BIT(MEM_EMPTY)
+#define MEM_FLAG_RESERVED	BIT(MEM_RESERVED)
+#define MEM_FLAG_UNKNOWN	BIT(MEM_UNKNOWN)
+#define MEM_FLAG_FPM		BIT(MEM_FPM)
+#define MEM_FLAG_EDO		BIT(MEM_EDO)
+#define MEM_FLAG_BEDO		BIT(MEM_BEDO)
+#define MEM_FLAG_SDR		BIT(MEM_SDR)
+#define MEM_FLAG_RDR		BIT(MEM_RDR)
+#define MEM_FLAG_DDR		BIT(MEM_DDR)
+#define MEM_FLAG_RDDR		BIT(MEM_RDDR)
+#define MEM_FLAG_RMBS		BIT(MEM_RMBS)
+
+
+/* chipset Error Detection and Correction capabilities and mode */
+enum edac_type {
+	EDAC_UNKNOWN = 0,	/* Unknown if ECC is available */
+	EDAC_NONE,		/* Doesnt support ECC */
+	EDAC_RESERVED,		/* Reserved ECC type */
+	EDAC_PARITY,		/* Detects parity errors */
+	EDAC_EC,		/* Error Checking - no correction */
+	EDAC_SECDED,		/* Single bit error correction, Double detection */
+	EDAC_S2ECD2ED,		/* Chipkill x2 devices - do these exist? */
+	EDAC_S4ECD4ED,		/* Chipkill x4 devices */
+	EDAC_S8ECD8ED,		/* Chipkill x8 devices */
+	EDAC_S16ECD16ED,	/* Chipkill x16 devices */
+};
+
+#define EDAC_FLAG_UNKNOWN	BIT(EDAC_UNKNOWN)
+#define EDAC_FLAG_NONE		BIT(EDAC_NONE)
+#define EDAC_FLAG_PARITY	BIT(EDAC_PARITY)
+#define EDAC_FLAG_EC		BIT(EDAC_EC)
+#define EDAC_FLAG_SECDED	BIT(EDAC_SECDED)
+#define EDAC_FLAG_S2ECD2ED	BIT(EDAC_S2ECD2ED)
+#define EDAC_FLAG_S4ECD4ED	BIT(EDAC_S4ECD4ED)
+#define EDAC_FLAG_S8ECD8ED	BIT(EDAC_S8ECD8ED)
+#define EDAC_FLAG_S16ECD16ED	BIT(EDAC_S16ECD16ED)
+
+
+/* scrubbing capabilities */
+enum scrub_type {
+	SCRUB_UNKNOWN = 0,	/* Unknown if scrubber is available */
+	SCRUB_NONE,		/* No scrubber */
+	SCRUB_SW_PROG,		/* SW progressive (sequential) scrubbing */
+	SCRUB_SW_SRC,		/* Software scrub only errors */
+	SCRUB_SW_PROG_SRC,	/* Progressive software scrub from an error */
+	SCRUB_SW_TUNABLE,	/* Software scrub frequency is tunable */
+	SCRUB_HW_PROG,		/* HW progressive (sequential) scrubbing */
+	SCRUB_HW_SRC,		/* Hardware scrub only errors */
+	SCRUB_HW_PROG_SRC,	/* Progressive hardware scrub from an error */
+	SCRUB_HW_TUNABLE	/* Hardware scrub frequency is tunable */
+};
+
+#define SCRUB_FLAG_SW_PROG	BIT(SCRUB_SW_PROG)
+#define SCRUB_FLAG_SW_SRC	BIT(SCRUB_SW_SRC_CORR)
+#define SCRUB_FLAG_SW_PROG_SRC	BIT(SCRUB_SW_PROG_SRC_CORR)
+#define SCRUB_FLAG_SW_TUN	BIT(SCRUB_SW_SCRUB_TUNABLE)
+#define SCRUB_FLAG_HW_PROG	BIT(SCRUB_HW_PROG)
+#define SCRUB_FLAG_HW_SRC	BIT(SCRUB_HW_SRC_CORR)
+#define SCRUB_FLAG_HW_PROG_SRC	BIT(SCRUB_HW_PROG_SRC_CORR)
+#define SCRUB_FLAG_HW_TUN	BIT(SCRUB_HW_TUNABLE)
+
+enum mci_sysfs_status {
+	MCI_SYSFS_INACTIVE = 0,	/* sysfs entries NOT registered */
+	MCI_SYSFS_ACTIVE	/* sysfs entries ARE registered */
+};
+
+/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
+
+/*
+ * There are several things to be aware of that aren't at all obvious:
+ *
+ *
+ * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
+ *
+ * These are some of the many terms that are thrown about that don't always
+ * mean what people think they mean (Inconceivable!).  In the interest of
+ * creating a common ground for discussion, terms and their definitions
+ * will be established.
+ *
+ * Memory devices:	The individual chip on a memory stick.  These devices
+ *			commonly output 4 and 8 bits each.  Grouping several
+ *			of these in parallel provides 64 bits which is common
+ *			for a memory stick.
+ *
+ * Memory Stick:	A printed circuit board that agregates multiple
+ *			memory devices in parallel.  This is the atomic
+ *			memory component that is purchaseable by Joe consumer
+ *			and loaded into a memory socket.
+ *
+ * Socket:		A physical connector on the motherboard that accepts
+ *			a single memory stick.
+ *
+ * Channel:		Set of memory devices on a memory stick that must be
+ *			grouped in parallel with one or more additional
+ *			channels from other memory sticks.  This parallel
+ *			grouping of the output from multiple channels are
+ *			necessary for the smallest granularity of memory access.
+ *			Some memory controllers are capable of single channel -
+ *			which means that memory sticks can be loaded
+ *			individually.  Other memory controllers are only
+ *			capable of dual channel - which means that memory
+ *			sticks must be loaded as pairs (see "socket set").
+ *
+ * Chip-select row:	All of the memory devices that are selected together.
+ *			for a single, minimum grain of memory access.
+ *			This selects all of the parallel memory devices across
+ *			all of the parallel channels.  Common chip-select rows
+ *			for single channel are 64 bits, for dual channel 128
+ *			bits.
+ *
+ * Single-Ranked stick:	A Single-ranked stick has 1 chip-select row of memmory.
+ *			Motherboards commonly drive two chip-select pins to
+ *			a memory stick. A single-ranked stick, will occupy
+ *			only one of those rows. The other will be unused.
+ *
+ * Double-Ranked stick:	A double-ranked stick has two chip-select rows which
+ *			access different sets of memory devices.  The two
+ *			rows cannot be accessed concurrently.
+ *
+ * Double-sided stick:	DEPRECATED TERM, see Double-Ranked stick.
+ *			A double-sided stick has two chip-select rows which
+ *			access different sets of memory devices.  The two
+ *			rows cannot be accessed concurrently.  "Double-sided"
+ *			is irrespective of the memory devices being mounted
+ *			on both sides of the memory stick.
+ *
+ * Socket set:		All of the memory sticks that are required for for
+ *			a single memory access or all of the memory sticks
+ *			spanned by a chip-select row.  A single socket set
+ *			has two chip-select rows and if double-sided sticks
+ *			are used these will occupy those chip-select rows.
+ *
+ * Bank:		This term is avoided because it is unclear when
+ *			needing to distinguish between chip-select rows and
+ *			socket sets.
+ *
+ * Controller pages:
+ *
+ * Physical pages:
+ *
+ * Virtual pages:
+ *
+ *
+ * STRUCTURE ORGANIZATION AND CHOICES
+ *
+ *
+ *
+ * PS - I enjoyed writing all that about as much as you enjoyed reading it.
+ */
+
+
+struct channel_info {
+	int chan_idx;		/* channel index */
+	u32 ce_count;		/* Correctable Errors for this CHANNEL */
+	char label[EDAC_MC_LABEL_LEN + 1];	/* DIMM label on motherboard */
+	struct csrow_info *csrow;	/* the parent */
+};
+
+
+struct csrow_info {
+	unsigned long first_page;	/* first page number in dimm */
+	unsigned long last_page;	/* last page number in dimm */
+	unsigned long page_mask;	/* used for interleaving -
+					   0UL for non intlv */
+	u32 nr_pages;		/* number of pages in csrow */
+	u32 grain;		/* granularity of reported error in bytes */
+	int csrow_idx;		/* the chip-select row */
+	enum dev_type dtype;	/* memory device type */
+	u32 ue_count;		/* Uncorrectable Errors for this csrow */
+	u32 ce_count;		/* Correctable Errors for this csrow */
+	enum mem_type mtype;	/* memory csrow type */
+	enum edac_type edac_mode;	/* EDAC mode for this csrow */
+	struct mem_ctl_info *mci;	/* the parent */
+
+	struct kobject kobj;	/* sysfs kobject for this csrow */
+
+	/* FIXME the number of CHANNELs might need to become dynamic */
+	u32 nr_channels;
+	struct channel_info *channels;
+};
+
+
+struct mem_ctl_info {
+	struct list_head link;  /* for global list of mem_ctl_info structs */
+	unsigned long mtype_cap;	/* memory types supported by mc */
+	unsigned long edac_ctl_cap;	/* Mem controller EDAC capabilities */
+	unsigned long edac_cap;	/* configuration capabilities - this is
+				   closely related to edac_ctl_cap.  The
+				   difference is that the controller
+				   may be capable of s4ecd4ed which would
+				   be listed in edac_ctl_cap, but if
+				   channels aren't capable of s4ecd4ed then the
+				   edac_cap would not have that capability. */
+	unsigned long scrub_cap;	/* chipset scrub capabilities */
+	enum scrub_type scrub_mode;	/* current scrub mode */
+
+	enum mci_sysfs_status sysfs_active;	/* status of sysfs */
+
+	/* pointer to edac checking routine */
+	void (*edac_check) (struct mem_ctl_info * mci);
+	/*
+	 * Remaps memory pages: controller pages to physical pages.
+	 * For most MC's, this will be NULL.
+	 */
+	/* FIXME - why not send the phys page to begin with? */
+	unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
+					   unsigned long page);
+	int mc_idx;
+	int nr_csrows;
+	struct csrow_info *csrows;
+	/*
+	 * FIXME - what about controllers on other busses? - IDs must be
+	 * unique.  pdev pointer should be sufficiently unique, but
+	 * BUS:SLOT.FUNC numbers may not be unique.
+	 */
+	struct pci_dev *pdev;
+	const char *mod_name;
+	const char *mod_ver;
+	const char *ctl_name;
+	char proc_name[MC_PROC_NAME_MAX_LEN + 1];
+	void *pvt_info;
+	u32 ue_noinfo_count;	/* Uncorrectable Errors w/o info */
+	u32 ce_noinfo_count;	/* Correctable Errors w/o info */
+	u32 ue_count;		/* Total Uncorrectable Errors for this MC */
+	u32 ce_count;		/* Total Correctable Errors for this MC */
+	unsigned long start_time;	/* mci load start time (in jiffies) */
+
+	/* this stuff is for safe removal of mc devices from global list while
+	 * NMI handlers may be traversing list
+	 */
+	struct rcu_head rcu;
+	struct completion complete;
+
+	/* edac sysfs device control */
+	struct kobject edac_mci_kobj;
+};
+
+
+
+/* write all or some bits in a byte-register*/
+static inline void pci_write_bits8(struct pci_dev *pdev, int offset,
+				   u8 value, u8 mask)
+{
+	if (mask != 0xff) {
+		u8 buf;
+		pci_read_config_byte(pdev, offset, &buf);
+		value &= mask;
+		buf &= ~mask;
+		value |= buf;
+	}
+	pci_write_config_byte(pdev, offset, value);
+}
+
+
+/* write all or some bits in a word-register*/
+static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
+				    u16 value, u16 mask)
+{
+	if (mask != 0xffff) {
+		u16 buf;
+		pci_read_config_word(pdev, offset, &buf);
+		value &= mask;
+		buf &= ~mask;
+		value |= buf;
+	}
+	pci_write_config_word(pdev, offset, value);
+}
+
+
+/* write all or some bits in a dword-register*/
+static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
+				    u32 value, u32 mask)
+{
+	if (mask != 0xffff) {
+		u32 buf;
+		pci_read_config_dword(pdev, offset, &buf);
+		value &= mask;
+		buf &= ~mask;
+		value |= buf;
+	}
+	pci_write_config_dword(pdev, offset, value);
+}
+
+
+#ifdef CONFIG_EDAC_DEBUG
+void edac_mc_dump_channel(struct channel_info *chan);
+void edac_mc_dump_mci(struct mem_ctl_info *mci);
+void edac_mc_dump_csrow(struct csrow_info *csrow);
+#endif				/* CONFIG_EDAC_DEBUG */
+
+extern int edac_mc_add_mc(struct mem_ctl_info *mci);
+extern int edac_mc_del_mc(struct mem_ctl_info *mci);
+
+extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
+					   unsigned long page);
+
+extern struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev
+							  *pdev);
+
+extern void edac_mc_scrub_block(unsigned long page,
+				     unsigned long offset, u32 size);
+
+/*
+ * The no info errors are used when error overflows are reported.
+ * There are a limited number of error logging registers that can
+ * be exausted.  When all registers are exhausted and an additional
+ * error occurs then an error overflow register records that an
+ * error occured and the type of error, but doesn't have any
+ * further information.  The ce/ue versions make for cleaner
+ * reporting logic and function interface - reduces conditional
+ * statement clutter and extra function arguments.
+ */
+extern void edac_mc_handle_ce(struct mem_ctl_info *mci,
+				   unsigned long page_frame_number,
+				   unsigned long offset_in_page,
+				   unsigned long syndrome,
+				   int row, int channel, const char *msg);
+
+extern void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
+					   const char *msg);
+
+extern void edac_mc_handle_ue(struct mem_ctl_info *mci,
+				   unsigned long page_frame_number,
+				   unsigned long offset_in_page,
+				   int row, const char *msg);
+
+extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
+					   const char *msg);
+
+/*
+ * This kmalloc's and initializes all the structures.
+ * Can't be used if all structures don't have the same lifetime.
+ */
+extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt,
+		unsigned nr_csrows, unsigned nr_chans);
+
+/* Free an mc previously allocated by edac_mc_alloc() */
+extern void edac_mc_free(struct mem_ctl_info *mci);
+
+
+#endif				/* _EDAC_MC_H_ */
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c
new file mode 100644
index 0000000..52596e7
--- /dev/null
+++ b/drivers/edac/i82860_edac.c
@@ -0,0 +1,299 @@
+/*
+ * Intel 82860 Memory Controller kernel module
+ * (C) 2005 Red Hat (http://www.redhat.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Ben Woodard <woodard@redhat.com>
+ * shamelessly copied from and based upon the edac_i82875 driver
+ * by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_82860_0
+#define PCI_DEVICE_ID_INTEL_82860_0	0x2531
+#endif				/* PCI_DEVICE_ID_INTEL_82860_0 */
+
+#define I82860_MCHCFG 0x50
+#define I82860_GBA 0x60
+#define I82860_GBA_MASK 0x7FF
+#define I82860_GBA_SHIFT 24
+#define I82860_ERRSTS 0xC8
+#define I82860_EAP 0xE4
+#define I82860_DERRCTL_STS 0xE2
+
+enum i82860_chips {
+	I82860 = 0,
+};
+
+struct i82860_dev_info {
+	const char *ctl_name;
+};
+
+struct i82860_error_info {
+	u16 errsts;
+	u32 eap;
+	u16 derrsyn;
+	u16 errsts2;
+};
+
+static const struct i82860_dev_info i82860_devs[] = {
+	[I82860] = {
+		    .ctl_name = "i82860"},
+};
+
+static struct pci_dev *mci_pdev = NULL;	/* init dev: in case that AGP code
+					   has already registered driver */
+
+static int i82860_registered = 1;
+
+static void i82860_get_error_info (struct mem_ctl_info *mci,
+		struct i82860_error_info *info)
+{
+	/*
+	 * This is a mess because there is no atomic way to read all the
+	 * registers at once and the registers can transition from CE being
+	 * overwritten by UE.
+	 */
+	pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts);
+	pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
+	pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, &info->derrsyn);
+	pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts2);
+
+	pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
+
+	/*
+	 * If the error is the same for both reads then the first set of reads
+	 * is valid.  If there is a change then there is a CE no info and the
+	 * second set of reads is valid and should be UE info.
+	 */
+	if (!(info->errsts2 & 0x0003))
+		return;
+	if ((info->errsts ^ info->errsts2) & 0x0003) {
+		pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
+		pci_read_config_word(mci->pdev, I82860_DERRCTL_STS,
+		    &info->derrsyn);
+	}
+}
+
+static int i82860_process_error_info (struct mem_ctl_info *mci,
+		struct i82860_error_info *info, int handle_errors)
+{
+	int row;
+
+	if (!(info->errsts2 & 0x0003))
+		return 0;
+
+	if (!handle_errors)
+		return 1;
+
+	if ((info->errsts ^ info->errsts2) & 0x0003) {
+		edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
+		info->errsts = info->errsts2;
+	}
+
+	info->eap >>= PAGE_SHIFT;
+	row = edac_mc_find_csrow_by_page(mci, info->eap);
+
+	if (info->errsts & 0x0002)
+		edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
+	else
+		edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+				       0, "i82860 UE");
+
+	return 1;
+}
+
+static void i82860_check(struct mem_ctl_info *mci)
+{
+	struct i82860_error_info info;
+
+	debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+	i82860_get_error_info(mci, &info);
+	i82860_process_error_info(mci, &info, 1);
+}
+
+static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
+{
+	int rc = -ENODEV;
+	int index;
+	struct mem_ctl_info *mci = NULL;
+	unsigned long last_cumul_size;
+
+	u16 mchcfg_ddim;	/* DRAM Data Integrity Mode 0=none,2=edac */
+
+	/* RDRAM has channels but these don't map onto the abstractions that
+	   edac uses.
+	   The device groups from the GRA registers seem to map reasonably
+	   well onto the notion of a chip select row.
+	   There are 16 GRA registers and since the name is associated with
+	   the channel and the GRA registers map to physical devices so we are
+	   going to make 1 channel for group.
+	 */
+	mci = edac_mc_alloc(0, 16, 1);
+	if (!mci)
+		return -ENOMEM;
+
+	debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+	mci->pdev = pdev;
+	mci->mtype_cap = MEM_FLAG_DDR;
+
+
+	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+	/* I"m not sure about this but I think that all RDRAM is SECDED */
+	mci->edac_cap = EDAC_FLAG_SECDED;
+	/* adjust FLAGS */
+
+	mci->mod_name = BS_MOD_STR;
+	mci->mod_ver = "$Revision: 1.1.2.6 $";
+	mci->ctl_name = i82860_devs[dev_idx].ctl_name;
+	mci->edac_check = i82860_check;
+	mci->ctl_page_to_phys = NULL;
+
+	pci_read_config_word(mci->pdev, I82860_MCHCFG, &mchcfg_ddim);
+	mchcfg_ddim = mchcfg_ddim & 0x180;
+
+	/*
+	 * The group row boundary (GRA) reg values are boundary address
+	 * for each DRAM row with a granularity of 16MB.  GRA regs are
+	 * cumulative; therefore GRA15 will contain the total memory contained
+	 * in all eight rows.
+	 */
+	for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+		u16 value;
+		u32 cumul_size;
+		struct csrow_info *csrow = &mci->csrows[index];
+
+		pci_read_config_word(mci->pdev, I82860_GBA + index * 2,
+				     &value);
+
+		cumul_size = (value & I82860_GBA_MASK) <<
+		    (I82860_GBA_SHIFT - PAGE_SHIFT);
+		debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+			__func__, index, cumul_size);
+		if (cumul_size == last_cumul_size)
+			continue;	/* not populated */
+
+		csrow->first_page = last_cumul_size;
+		csrow->last_page = cumul_size - 1;
+		csrow->nr_pages = cumul_size - last_cumul_size;
+		last_cumul_size = cumul_size;
+		csrow->grain = 1 << 12;	/* I82860_EAP has 4KiB reolution */
+		csrow->mtype = MEM_RMBS;
+		csrow->dtype = DEV_UNKNOWN;
+		csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
+	}
+
+	/* clear counters */
+	pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
+
+	if (edac_mc_add_mc(mci)) {
+		debugf3("MC: " __FILE__
+			": %s(): failed edac_mc_add_mc()\n",
+			__func__);
+		edac_mc_free(mci);
+	} else {
+		/* get this far and it's successful */
+		debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+		rc = 0;
+	}
+	return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit i82860_init_one(struct pci_dev *pdev,
+				     const struct pci_device_id *ent)
+{
+	int rc;
+
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	printk(KERN_INFO "i82860 init one\n");
+	if(pci_enable_device(pdev) < 0)
+		return -EIO;
+	rc = i82860_probe1(pdev, ent->driver_data);
+	if(rc == 0)
+		mci_pdev = pci_dev_get(pdev);
+	return rc;
+}
+
+static void __devexit i82860_remove_one(struct pci_dev *pdev)
+{
+	struct mem_ctl_info *mci;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+
+	mci = edac_mc_find_mci_by_pdev(pdev);
+	if ((mci != NULL) && (edac_mc_del_mc(mci) == 0))
+		edac_mc_free(mci);
+}
+
+static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
+	{PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 I82860},
+	{0,}			/* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
+
+static struct pci_driver i82860_driver = {
+	.name = BS_MOD_STR,
+	.probe = i82860_init_one,
+	.remove = __devexit_p(i82860_remove_one),
+	.id_table = i82860_pci_tbl,
+};
+
+static int __init i82860_init(void)
+{
+	int pci_rc;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
+		return pci_rc;
+
+	if (!mci_pdev) {
+		i82860_registered = 0;
+		mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+					  PCI_DEVICE_ID_INTEL_82860_0, NULL);
+		if (mci_pdev == NULL) {
+			debugf0("860 pci_get_device fail\n");
+			return -ENODEV;
+		}
+		pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
+		if (pci_rc < 0) {
+			debugf0("860 init fail\n");
+			pci_dev_put(mci_pdev);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+static void __exit i82860_exit(void)
+{
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	pci_unregister_driver(&i82860_driver);
+	if (!i82860_registered) {
+		i82860_remove_one(mci_pdev);
+		pci_dev_put(mci_pdev);
+	}
+}
+
+module_init(i82860_init);
+module_exit(i82860_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR
+    ("Red Hat Inc. (http://www.redhat.com.com) Ben Woodard <woodard@redhat.com>");
+MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
new file mode 100644
index 0000000..1991f94
--- /dev/null
+++ b/drivers/edac/i82875p_edac.c
@@ -0,0 +1,532 @@
+/*
+ * Intel D82875P Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Contributors:
+ *	Wang Zhenyu at intel.com
+ *
+ * $Id: edac_i82875p.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_82875_0
+#define PCI_DEVICE_ID_INTEL_82875_0	0x2578
+#endif				/* PCI_DEVICE_ID_INTEL_82875_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_82875_6
+#define PCI_DEVICE_ID_INTEL_82875_6	0x257e
+#endif				/* PCI_DEVICE_ID_INTEL_82875_6 */
+
+
+/* four csrows in dual channel, eight in single channel */
+#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans))
+
+
+/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */
+#define I82875P_EAP		0x58	/* Error Address Pointer (32b)
+					 *
+					 * 31:12 block address
+					 * 11:0  reserved
+					 */
+
+#define I82875P_DERRSYN		0x5c	/* DRAM Error Syndrome (8b)
+					 *
+					 *  7:0  DRAM ECC Syndrome
+					 */
+
+#define I82875P_DES		0x5d	/* DRAM Error Status (8b)
+					 *
+					 *  7:1  reserved
+					 *  0    Error channel 0/1
+					 */
+
+#define I82875P_ERRSTS		0xc8	/* Error Status Register (16b)
+					 *
+					 * 15:10 reserved
+					 *  9    non-DRAM lock error (ndlock)
+					 *  8    Sftwr Generated SMI
+					 *  7    ECC UE
+					 *  6    reserved
+					 *  5    MCH detects unimplemented cycle
+					 *  4    AGP access outside GA
+					 *  3    Invalid AGP access
+					 *  2    Invalid GA translation table
+					 *  1    Unsupported AGP command
+					 *  0    ECC CE
+					 */
+
+#define I82875P_ERRCMD		0xca	/* Error Command (16b)
+					 *
+					 * 15:10 reserved
+					 *  9    SERR on non-DRAM lock
+					 *  8    SERR on ECC UE
+					 *  7    SERR on ECC CE
+					 *  6    target abort on high exception
+					 *  5    detect unimplemented cyc
+					 *  4    AGP access outside of GA
+					 *  3    SERR on invalid AGP access
+					 *  2    invalid translation table
+					 *  1    SERR on unsupported AGP command
+					 *  0    reserved
+					 */
+
+
+/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */
+#define I82875P_PCICMD6		0x04	/* PCI Command Register (16b)
+					 *
+					 * 15:10 reserved
+					 *  9    fast back-to-back - ro 0
+					 *  8    SERR enable - ro 0
+					 *  7    addr/data stepping - ro 0
+					 *  6    parity err enable - ro 0
+					 *  5    VGA palette snoop - ro 0
+					 *  4    mem wr & invalidate - ro 0
+					 *  3    special cycle - ro 0
+					 *  2    bus master - ro 0
+					 *  1    mem access dev6 - 0(dis),1(en)
+					 *  0    IO access dev3 - 0(dis),1(en)
+					 */
+
+#define I82875P_BAR6		0x10	/* Mem Delays Base ADDR Reg (32b)
+					 *
+					 * 31:12 mem base addr [31:12]
+					 * 11:4  address mask - ro 0
+					 *  3    prefetchable - ro 0(non),1(pre)
+					 *  2:1  mem type - ro 0
+					 *  0    mem space - ro 0
+					 */
+
+/* Intel 82875p MMIO register space - device 0 function 0 - MMR space */
+
+#define I82875P_DRB_SHIFT 26	/* 64MiB grain */
+#define I82875P_DRB		0x00	/* DRAM Row Boundary (8b x 8)
+					 *
+					 *  7    reserved
+					 *  6:0  64MiB row boundary addr
+					 */
+
+#define I82875P_DRA		0x10	/* DRAM Row Attribute (4b x 8)
+					 *
+					 *  7    reserved
+					 *  6:4  row attr row 1
+					 *  3    reserved
+					 *  2:0  row attr row 0
+					 *
+					 * 000 =  4KiB
+					 * 001 =  8KiB
+					 * 010 = 16KiB
+					 * 011 = 32KiB
+					 */
+
+#define I82875P_DRC		0x68	/* DRAM Controller Mode (32b)
+					 *
+					 * 31:30 reserved
+					 * 29    init complete
+					 * 28:23 reserved
+					 * 22:21 nr chan 00=1,01=2
+					 * 20    reserved
+					 * 19:18 Data Integ Mode 00=none,01=ecc
+					 * 17:11 reserved
+					 * 10:8  refresh mode
+					 *  7    reserved
+					 *  6:4  mode select
+					 *  3:2  reserved
+					 *  1:0  DRAM type 01=DDR
+					 */
+
+
+enum i82875p_chips {
+	I82875P = 0,
+};
+
+
+struct i82875p_pvt {
+	struct pci_dev *ovrfl_pdev;
+	void __iomem *ovrfl_window;
+};
+
+
+struct i82875p_dev_info {
+	const char *ctl_name;
+};
+
+
+struct i82875p_error_info {
+	u16 errsts;
+	u32 eap;
+	u8 des;
+	u8 derrsyn;
+	u16 errsts2;
+};
+
+
+static const struct i82875p_dev_info i82875p_devs[] = {
+	[I82875P] = {
+		     .ctl_name = "i82875p"},
+};
+
+static struct pci_dev *mci_pdev = NULL;	/* init dev: in case that AGP code
+					   has already registered driver */
+static int i82875p_registered = 1;
+
+static void i82875p_get_error_info (struct mem_ctl_info *mci,
+		struct i82875p_error_info *info)
+{
+	/*
+	 * This is a mess because there is no atomic way to read all the
+	 * registers at once and the registers can transition from CE being
+	 * overwritten by UE.
+	 */
+	pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts);
+	pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
+	pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
+	pci_read_config_byte(mci->pdev, I82875P_DERRSYN, &info->derrsyn);
+	pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts2);
+
+	pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081);
+
+	/*
+	 * If the error is the same then we can for both reads then
+	 * the first set of reads is valid.  If there is a change then
+	 * there is a CE no info and the second set of reads is valid
+	 * and should be UE info.
+	 */
+	if (!(info->errsts2 & 0x0081))
+		return;
+	if ((info->errsts ^ info->errsts2) & 0x0081) {
+		pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
+		pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
+		pci_read_config_byte(mci->pdev, I82875P_DERRSYN,
+		    &info->derrsyn);
+	}
+}
+
+static int i82875p_process_error_info (struct mem_ctl_info *mci,
+		struct i82875p_error_info *info, int handle_errors)
+{
+	int row, multi_chan;
+
+	multi_chan = mci->csrows[0].nr_channels - 1;
+
+	if (!(info->errsts2 & 0x0081))
+		return 0;
+
+	if (!handle_errors)
+		return 1;
+
+	if ((info->errsts ^ info->errsts2) & 0x0081) {
+		edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
+		info->errsts = info->errsts2;
+	}
+
+	info->eap >>= PAGE_SHIFT;
+	row = edac_mc_find_csrow_by_page(mci, info->eap);
+
+	if (info->errsts & 0x0080)
+		edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE");
+	else
+		edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+				       multi_chan ? (info->des & 0x1) : 0,
+				       "i82875p CE");
+
+	return 1;
+}
+
+
+static void i82875p_check(struct mem_ctl_info *mci)
+{
+	struct i82875p_error_info info;
+
+	debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+	i82875p_get_error_info(mci, &info);
+	i82875p_process_error_info(mci, &info, 1);
+}
+
+
+#ifdef CONFIG_PROC_FS
+extern int pci_proc_attach_device(struct pci_dev *);
+#endif
+
+static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
+{
+	int rc = -ENODEV;
+	int index;
+	struct mem_ctl_info *mci = NULL;
+	struct i82875p_pvt *pvt = NULL;
+	unsigned long last_cumul_size;
+	struct pci_dev *ovrfl_pdev;
+	void __iomem *ovrfl_window = NULL;
+
+	u32 drc;
+	u32 drc_chan;		/* Number of channels 0=1chan,1=2chan */
+	u32 nr_chans;
+	u32 drc_ddim;		/* DRAM Data Integrity Mode 0=none,2=edac */
+
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	ovrfl_pdev = pci_find_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
+
+	if (!ovrfl_pdev) {
+		/*
+		 * Intel tells BIOS developers to hide device 6 which
+		 * configures the overflow device access containing
+		 * the DRBs - this is where we expose device 6.
+		 * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
+		 */
+		pci_write_bits8(pdev, 0xf4, 0x2, 0x2);
+		ovrfl_pdev =
+		    pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
+		if (!ovrfl_pdev)
+			goto fail;
+	}
+#ifdef CONFIG_PROC_FS
+	if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) {
+		printk(KERN_ERR "MC: " __FILE__
+		       ": %s(): Failed to attach overflow device\n",
+		       __func__);
+		goto fail;
+	}
+#endif				/* CONFIG_PROC_FS */
+	if (pci_enable_device(ovrfl_pdev)) {
+		printk(KERN_ERR "MC: " __FILE__
+		       ": %s(): Failed to enable overflow device\n",
+		       __func__);
+		goto fail;
+	}
+
+	if (pci_request_regions(ovrfl_pdev, pci_name(ovrfl_pdev))) {
+#ifdef CORRECT_BIOS
+		goto fail;
+#endif
+	}
+	/* cache is irrelevant for PCI bus reads/writes */
+	ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0),
+				       pci_resource_len(ovrfl_pdev, 0));
+
+	if (!ovrfl_window) {
+		printk(KERN_ERR "MC: " __FILE__
+		       ": %s(): Failed to ioremap bar6\n", __func__);
+		goto fail;
+	}
+
+	/* need to find out the number of channels */
+	drc = readl(ovrfl_window + I82875P_DRC);
+	drc_chan = ((drc >> 21) & 0x1);
+	nr_chans = drc_chan + 1;
+	drc_ddim = (drc >> 18) & 0x1;
+
+	mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans),
+				 nr_chans);
+
+	if (!mci) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+	mci->pdev = pdev;
+	mci->mtype_cap = MEM_FLAG_DDR;
+
+	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+	mci->edac_cap = EDAC_FLAG_UNKNOWN;
+	/* adjust FLAGS */
+
+	mci->mod_name = BS_MOD_STR;
+	mci->mod_ver = "$Revision: 1.5.2.11 $";
+	mci->ctl_name = i82875p_devs[dev_idx].ctl_name;
+	mci->edac_check = i82875p_check;
+	mci->ctl_page_to_phys = NULL;
+
+	debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+
+	pvt = (struct i82875p_pvt *) mci->pvt_info;
+	pvt->ovrfl_pdev = ovrfl_pdev;
+	pvt->ovrfl_window = ovrfl_window;
+
+	/*
+	 * The dram row boundary (DRB) reg values are boundary address
+	 * for each DRAM row with a granularity of 32 or 64MB (single/dual
+	 * channel operation).  DRB regs are cumulative; therefore DRB7 will
+	 * contain the total memory contained in all eight rows.
+	 */
+	for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+		u8 value;
+		u32 cumul_size;
+		struct csrow_info *csrow = &mci->csrows[index];
+
+		value = readb(ovrfl_window + I82875P_DRB + index);
+		cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT);
+		debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+			__func__, index, cumul_size);
+		if (cumul_size == last_cumul_size)
+			continue;	/* not populated */
+
+		csrow->first_page = last_cumul_size;
+		csrow->last_page = cumul_size - 1;
+		csrow->nr_pages = cumul_size - last_cumul_size;
+		last_cumul_size = cumul_size;
+		csrow->grain = 1 << 12;	/* I82875P_EAP has 4KiB reolution */
+		csrow->mtype = MEM_DDR;
+		csrow->dtype = DEV_UNKNOWN;
+		csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
+	}
+
+	/* clear counters */
+	pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081);
+
+	if (edac_mc_add_mc(mci)) {
+		debugf3("MC: " __FILE__
+			": %s(): failed edac_mc_add_mc()\n", __func__);
+		goto fail;
+	}
+
+	/* get this far and it's successful */
+	debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+	return 0;
+
+      fail:
+	if (mci)
+		edac_mc_free(mci);
+
+	if (ovrfl_window)
+		iounmap(ovrfl_window);
+
+	if (ovrfl_pdev) {
+		pci_release_regions(ovrfl_pdev);
+		pci_disable_device(ovrfl_pdev);
+	}
+
+	/* NOTE: the ovrfl proc entry and pci_dev are intentionally left */
+	return rc;
+}
+
+
+/* returns count (>= 0), or negative on error */
+static int __devinit i82875p_init_one(struct pci_dev *pdev,
+				      const struct pci_device_id *ent)
+{
+	int rc;
+
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	printk(KERN_INFO "i82875p init one\n");
+	if(pci_enable_device(pdev) < 0)
+		return -EIO;
+	rc = i82875p_probe1(pdev, ent->driver_data);
+	if (mci_pdev == NULL)
+		mci_pdev = pci_dev_get(pdev);
+	return rc;
+}
+
+
+static void __devexit i82875p_remove_one(struct pci_dev *pdev)
+{
+	struct mem_ctl_info *mci;
+	struct i82875p_pvt *pvt = NULL;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+
+	if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+		return;
+
+	pvt = (struct i82875p_pvt *) mci->pvt_info;
+	if (pvt->ovrfl_window)
+		iounmap(pvt->ovrfl_window);
+
+	if (pvt->ovrfl_pdev) {
+#ifdef CORRECT_BIOS
+		pci_release_regions(pvt->ovrfl_pdev);
+#endif				/*CORRECT_BIOS */
+		pci_disable_device(pvt->ovrfl_pdev);
+		pci_dev_put(pvt->ovrfl_pdev);
+	}
+
+	if (edac_mc_del_mc(mci))
+		return;
+
+	edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = {
+	{PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 I82875P},
+	{0,}			/* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl);
+
+
+static struct pci_driver i82875p_driver = {
+	.name = BS_MOD_STR,
+	.probe = i82875p_init_one,
+	.remove = __devexit_p(i82875p_remove_one),
+	.id_table = i82875p_pci_tbl,
+};
+
+
+static int __init i82875p_init(void)
+{
+	int pci_rc;
+
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+	pci_rc = pci_register_driver(&i82875p_driver);
+	if (pci_rc < 0)
+		return pci_rc;
+	if (mci_pdev == NULL) {
+		i82875p_registered = 0;
+		mci_pdev =
+		    pci_get_device(PCI_VENDOR_ID_INTEL,
+				   PCI_DEVICE_ID_INTEL_82875_0, NULL);
+		if (!mci_pdev) {
+			debugf0("875p pci_get_device fail\n");
+			return -ENODEV;
+		}
+		pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl);
+		if (pci_rc < 0) {
+			debugf0("875p init fail\n");
+			pci_dev_put(mci_pdev);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+
+static void __exit i82875p_exit(void)
+{
+	debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+	pci_unregister_driver(&i82875p_driver);
+	if (!i82875p_registered) {
+		i82875p_remove_one(mci_pdev);
+		pci_dev_put(mci_pdev);
+	}
+}
+
+
+module_init(i82875p_init);
+module_exit(i82875p_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers");
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c
new file mode 100644
index 0000000..e908928
--- /dev/null
+++ b/drivers/edac/r82600_edac.c
@@ -0,0 +1,407 @@
+/*
+ * Radisys 82600 Embedded chipset Memory Controller kernel module
+ * (C) 2005 EADS Astrium
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Tim Small <tim@buttersideup.com>, based on work by Thayne
+ * Harbaugh, Dan Hollis <goemon at anime dot net> and others.
+ *
+ * $Id: edac_r82600.c,v 1.1.2.6 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ * Written with reference to 82600 High Integration Dual PCI System
+ * Controller Data Book:
+ * http://www.radisys.com/files/support_downloads/007-01277-0002.82600DataBook.pdf
+ * references to this document given in []
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+/* Radisys say "The 82600 integrates a main memory SDRAM controller that
+ * supports up to four banks of memory. The four banks can support a mix of
+ * sizes of 64 bit wide (72 bits with ECC) Synchronous DRAM (SDRAM) DIMMs,
+ * each of which can be any size from 16MB to 512MB. Both registered (control
+ * signals buffered) and unbuffered DIMM types are supported. Mixing of
+ * registered and unbuffered DIMMs as well as mixing of ECC and non-ECC DIMMs
+ * is not allowed. The 82600 SDRAM interface operates at the same frequency as
+ * the CPU bus, 66MHz, 100MHz or 133MHz."
+ */
+
+#define R82600_NR_CSROWS 4
+#define R82600_NR_CHANS  1
+#define R82600_NR_DIMMS  4
+
+#define R82600_BRIDGE_ID  0x8200
+
+/* Radisys 82600 register addresses - device 0 function 0 - PCI bridge */
+#define R82600_DRAMC	0x57	/* Various SDRAM related control bits
+				 * all bits are R/W
+				 *
+				 * 7    SDRAM ISA Hole Enable
+				 * 6    Flash Page Mode Enable
+				 * 5    ECC Enable: 1=ECC 0=noECC
+				 * 4    DRAM DIMM Type: 1=
+				 * 3    BIOS Alias Disable
+				 * 2    SDRAM BIOS Flash Write Enable
+				 * 1:0  SDRAM Refresh Rate: 00=Disabled
+				 *          01=7.8usec (256Mbit SDRAMs)
+				 *          10=15.6us 11=125usec
+				 */
+
+#define R82600_SDRAMC	0x76	/* "SDRAM Control Register"
+				 * More SDRAM related control bits
+				 * all bits are R/W
+				 *
+				 * 15:8 Reserved.
+				 *
+				 * 7:5  Special SDRAM Mode Select
+				 *
+				 * 4    Force ECC
+				 *
+				 *        1=Drive ECC bits to 0 during
+				 *          write cycles (i.e. ECC test mode)
+				 *
+				 *        0=Normal ECC functioning
+				 *
+				 * 3    Enhanced Paging Enable
+				 *
+				 * 2    CAS# Latency 0=3clks 1=2clks
+				 *
+				 * 1    RAS# to CAS# Delay 0=3 1=2
+				 *
+				 * 0    RAS# Precharge     0=3 1=2
+				 */
+
+#define R82600_EAP	0x80	/* ECC Error Address Pointer Register
+				 *
+				 * 31    Disable Hardware Scrubbing (RW)
+				 *        0=Scrub on corrected read
+				 *        1=Don't scrub on corrected read
+				 *
+				 * 30:12 Error Address Pointer (RO)
+				 *        Upper 19 bits of error address
+				 *
+				 * 11:4  Syndrome Bits (RO)
+				 *
+				 * 3     BSERR# on multibit error (RW)
+				 *        1=enable 0=disable
+				 *
+				 * 2     NMI on Single Bit Eror (RW)
+				 *        1=NMI triggered by SBE n.b. other
+				 *          prerequeists
+				 *        0=NMI not triggered
+				 *
+				 * 1     MBE (R/WC)
+				 *        read 1=MBE at EAP (see above)
+				 *        read 0=no MBE, or SBE occurred first
+				 *        write 1=Clear MBE status (must also
+				 *          clear SBE)
+				 *        write 0=NOP
+				 *
+				 * 1     SBE (R/WC)
+				 *        read 1=SBE at EAP (see above)
+				 *        read 0=no SBE, or MBE occurred first
+				 *        write 1=Clear SBE status (must also
+				 *          clear MBE)
+				 *        write 0=NOP
+				 */
+
+#define R82600_DRBA	0x60	/* + 0x60..0x63 SDRAM Row Boundry Address
+				 *  Registers
+				 *
+				 * 7:0  Address lines 30:24 - upper limit of
+				 * each row [p57]
+				 */
+
+struct r82600_error_info {
+	u32 eapr;
+};
+
+
+static unsigned int disable_hardware_scrub = 0;
+
+
+static void r82600_get_error_info (struct mem_ctl_info *mci,
+		struct r82600_error_info *info)
+{
+	pci_read_config_dword(mci->pdev, R82600_EAP, &info->eapr);
+
+	if (info->eapr & BIT(0))
+		/* Clear error to allow next error to be reported [p.62] */
+		pci_write_bits32(mci->pdev, R82600_EAP,
+				   ((u32) BIT(0) & (u32) BIT(1)),
+				   ((u32) BIT(0) & (u32) BIT(1)));
+
+	if (info->eapr & BIT(1))
+		/* Clear error to allow next error to be reported [p.62] */
+		pci_write_bits32(mci->pdev, R82600_EAP,
+				   ((u32) BIT(0) & (u32) BIT(1)),
+				   ((u32) BIT(0) & (u32) BIT(1)));
+}
+
+
+static int r82600_process_error_info (struct mem_ctl_info *mci,
+		struct r82600_error_info *info, int handle_errors)
+{
+	int error_found;
+	u32 eapaddr, page;
+	u32 syndrome;
+
+	error_found = 0;
+
+	/* bits 30:12 store the upper 19 bits of the 32 bit error address */
+	eapaddr = ((info->eapr >> 12) & 0x7FFF) << 13;
+	/* Syndrome in bits 11:4 [p.62]       */
+	syndrome = (info->eapr >> 4) & 0xFF;
+
+	/* the R82600 reports at less than page *
+	 * granularity (upper 19 bits only)     */
+	page = eapaddr >> PAGE_SHIFT;
+
+	if (info->eapr & BIT(0)) { 	/* CE? */
+		error_found = 1;
+
+		if (handle_errors)
+			edac_mc_handle_ce(
+			    mci, page, 0,	/* not avail */
+			    syndrome,
+			    edac_mc_find_csrow_by_page(mci, page),
+			    0,	/* channel */
+			    mci->ctl_name);
+	}
+
+	if (info->eapr & BIT(1)) { 	/* UE? */
+		error_found = 1;
+
+		if (handle_errors)
+			/* 82600 doesn't give enough info */
+			edac_mc_handle_ue(mci, page, 0,
+			    edac_mc_find_csrow_by_page(mci, page),
+			    mci->ctl_name);
+	}
+
+	return error_found;
+}
+
+static void r82600_check(struct mem_ctl_info *mci)
+{
+	struct r82600_error_info info;
+
+	debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+	r82600_get_error_info(mci, &info);
+	r82600_process_error_info(mci, &info, 1);
+}
+
+static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
+{
+	int rc = -ENODEV;
+	int index;
+	struct mem_ctl_info *mci = NULL;
+	u8 dramcr;
+	u32 ecc_on;
+	u32 reg_sdram;
+	u32 eapr;
+	u32 scrub_disabled;
+	u32 sdram_refresh_rate;
+	u32 row_high_limit_last = 0;
+	u32 eap_init_bits;
+
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+
+	pci_read_config_byte(pdev, R82600_DRAMC, &dramcr);
+	pci_read_config_dword(pdev, R82600_EAP, &eapr);
+
+	ecc_on = dramcr & BIT(5);
+	reg_sdram = dramcr & BIT(4);
+	scrub_disabled = eapr & BIT(31);
+	sdram_refresh_rate = dramcr & (BIT(0) | BIT(1));
+
+	debugf2("MC: " __FILE__ ": %s(): sdram refresh rate = %#0x\n",
+		__func__, sdram_refresh_rate);
+
+	debugf2("MC: " __FILE__ ": %s(): DRAMC register = %#0x\n", __func__,
+		dramcr);
+
+	mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS);
+
+	if (mci == NULL) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+	mci->pdev = pdev;
+	mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
+
+	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+	/* FIXME try to work out if the chip leads have been                 *
+	 * used for COM2 instead on this board? [MA6?]       MAYBE:          */
+
+	/* On the R82600, the pins for memory bits 72:65 - i.e. the   *
+	 * EC bits are shared with the pins for COM2 (!), so if COM2  *
+	 * is enabled, we assume COM2 is wired up, and thus no EDAC   *
+	 * is possible.                                               */
+	mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+	if (ecc_on) {
+		if (scrub_disabled)
+			debugf3("MC: " __FILE__ ": %s(): mci = %p - "
+				"Scrubbing disabled! EAP: %#0x\n", __func__,
+				mci, eapr);
+	} else
+		mci->edac_cap = EDAC_FLAG_NONE;
+
+	mci->mod_name = BS_MOD_STR;
+	mci->mod_ver = "$Revision: 1.1.2.6 $";
+	mci->ctl_name = "R82600";
+	mci->edac_check = r82600_check;
+	mci->ctl_page_to_phys = NULL;
+
+	for (index = 0; index < mci->nr_csrows; index++) {
+		struct csrow_info *csrow = &mci->csrows[index];
+		u8 drbar;	/* sDram Row Boundry Address Register */
+		u32 row_high_limit;
+		u32 row_base;
+
+		/* find the DRAM Chip Select Base address and mask */
+		pci_read_config_byte(mci->pdev, R82600_DRBA + index, &drbar);
+
+		debugf1("MC%d: " __FILE__ ": %s() Row=%d DRBA = %#0x\n",
+			mci->mc_idx, __func__, index, drbar);
+
+		row_high_limit = ((u32) drbar << 24);
+/*		row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */
+
+		debugf1("MC%d: " __FILE__ ": %s() Row=%d, "
+			"Boundry Address=%#0x, Last = %#0x \n",
+			mci->mc_idx, __func__, index, row_high_limit,
+			row_high_limit_last);
+
+		/* Empty row [p.57] */
+		if (row_high_limit == row_high_limit_last)
+			continue;
+
+		row_base = row_high_limit_last;
+
+		csrow->first_page = row_base >> PAGE_SHIFT;
+		csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
+		csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
+		/* Error address is top 19 bits - so granularity is      *
+		 * 14 bits                                               */
+		csrow->grain = 1 << 14;
+		csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
+		/* FIXME - check that this is unknowable with this chipset */
+		csrow->dtype = DEV_UNKNOWN;
+
+		/* Mode is global on 82600 */
+		csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
+		row_high_limit_last = row_high_limit;
+	}
+
+	/* clear counters */
+	/* FIXME should we? */
+
+	if (edac_mc_add_mc(mci)) {
+		debugf3("MC: " __FILE__
+			": %s(): failed edac_mc_add_mc()\n", __func__);
+		goto fail;
+	}
+
+	/* get this far and it's successful */
+
+	/* Clear error flags to allow next error to be reported [p.62] */
+	/* Test systems seem to always have the UE flag raised on boot */
+
+	eap_init_bits = BIT(0) & BIT(1);
+	if (disable_hardware_scrub) {
+		eap_init_bits |= BIT(31);
+		debugf3("MC: " __FILE__ ": %s(): Disabling Hardware Scrub "
+			"(scrub on error)\n", __func__);
+	}
+
+	pci_write_bits32(mci->pdev, R82600_EAP, eap_init_bits,
+			 eap_init_bits);
+
+	debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+	return 0;
+
+fail:
+	if (mci)
+		edac_mc_free(mci);
+
+	return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit r82600_init_one(struct pci_dev *pdev,
+				     const struct pci_device_id *ent)
+{
+	debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* don't need to call pci_device_enable() */
+	return r82600_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit r82600_remove_one(struct pci_dev *pdev)
+{
+	struct mem_ctl_info *mci;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+
+	if (((mci = edac_mc_find_mci_by_pdev(pdev)) != NULL) &&
+	    !edac_mc_del_mc(mci))
+		edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id r82600_pci_tbl[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)},
+	{0,}			/* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
+
+
+static struct pci_driver r82600_driver = {
+	.name = BS_MOD_STR,
+	.probe = r82600_init_one,
+	.remove = __devexit_p(r82600_remove_one),
+	.id_table = r82600_pci_tbl,
+};
+
+
+static int __init r82600_init(void)
+{
+	return pci_register_driver(&r82600_driver);
+}
+
+
+static void __exit r82600_exit(void)
+{
+	pci_unregister_driver(&r82600_driver);
+}
+
+
+module_init(r82600_init);
+module_exit(r82600_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
+	      "on behalf of EADS Astrium");
+MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
+
+module_param(disable_hardware_scrub, bool, 0644);
+MODULE_PARM_DESC(disable_hardware_scrub,
+		 "If set, disable the chipset's automatic scrub for CEs");
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c582959..7230d4e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -113,6 +113,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1621.
 
+config SENSORS_F71805F
+	tristate "Fintek F71805F/FG"
+	depends on HWMON && EXPERIMENTAL
+	help
+	  If you say yes here you get support for hardware monitoring
+	  features of the Fintek F71805F/FG chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called f71805f.
+
 config SENSORS_FSCHER
 	tristate "FSC Hermes"
 	depends on HWMON && I2C && EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 06d4a1d..fbdb8d9 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -18,6 +18,7 @@
 obj-$(CONFIG_SENSORS_ADM9240)	+= adm9240.o
 obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
+obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_FSCHER)	+= fscher.o
 obj-$(CONFIG_SENSORS_FSCPOS)	+= fscpos.o
 obj-$(CONFIG_SENSORS_GL518SM)	+= gl518sm.o
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
new file mode 100644
index 0000000..e029e0a
--- /dev/null
+++ b/drivers/hwmon/f71805f.c
@@ -0,0 +1,908 @@
+/*
+ * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
+ *             hardware monitoring features
+ * Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+ *
+ * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
+ * complete hardware monitoring features: voltage, fan and temperature
+ * sensors, and manual and automatic fan speed control.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <asm/io.h>
+
+static struct platform_device *pdev;
+
+#define DRVNAME "f71805f"
+
+/*
+ * Super-I/O constants and functions
+ */
+
+#define F71805F_LD_HWM		0x04
+
+#define SIO_REG_LDSEL		0x07	/* Logical device select */
+#define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
+#define SIO_REG_DEVREV		0x22	/* Device revision */
+#define SIO_REG_MANID		0x23	/* Fintek ID (2 bytes) */
+#define SIO_REG_ENABLE		0x30	/* Logical device enable */
+#define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
+
+#define SIO_FINTEK_ID		0x1934
+#define SIO_F71805F_ID		0x0406
+
+static inline int
+superio_inb(int base, int reg)
+{
+	outb(reg, base);
+	return inb(base + 1);
+}
+
+static int
+superio_inw(int base, int reg)
+{
+	int val;
+	outb(reg++, base);
+	val = inb(base + 1) << 8;
+	outb(reg, base);
+	val |= inb(base + 1);
+	return val;
+}
+
+static inline void
+superio_select(int base, int ld)
+{
+	outb(SIO_REG_LDSEL, base);
+	outb(ld, base + 1);
+}
+
+static inline void
+superio_enter(int base)
+{
+	outb(0x87, base);
+	outb(0x87, base);
+}
+
+static inline void
+superio_exit(int base)
+{
+	outb(0xaa, base);
+}
+
+/*
+ * ISA constants
+ */
+
+#define REGION_LENGTH		2
+#define ADDR_REG_OFFSET		0
+#define DATA_REG_OFFSET		1
+
+static struct resource f71805f_resource __initdata = {
+	.flags	= IORESOURCE_IO,
+};
+
+/*
+ * Registers
+ */
+
+/* in nr from 0 to 8 (8-bit values) */
+#define F71805F_REG_IN(nr)		(0x10 + (nr))
+#define F71805F_REG_IN_HIGH(nr)		(0x40 + 2 * (nr))
+#define F71805F_REG_IN_LOW(nr)		(0x41 + 2 * (nr))
+/* fan nr from 0 to 2 (12-bit values, two registers) */
+#define F71805F_REG_FAN(nr)		(0x20 + 2 * (nr))
+#define F71805F_REG_FAN_LOW(nr)		(0x28 + 2 * (nr))
+#define F71805F_REG_FAN_CTRL(nr)	(0x60 + 16 * (nr))
+/* temp nr from 0 to 2 (8-bit values) */
+#define F71805F_REG_TEMP(nr)		(0x1B + (nr))
+#define F71805F_REG_TEMP_HIGH(nr)	(0x54 + 2 * (nr))
+#define F71805F_REG_TEMP_HYST(nr)	(0x55 + 2 * (nr))
+#define F71805F_REG_TEMP_MODE		0x01
+
+#define F71805F_REG_START		0x00
+/* status nr from 0 to 2 */
+#define F71805F_REG_STATUS(nr)		(0x36 + (nr))
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct f71805f_data {
+	unsigned short addr;
+	const char *name;
+	struct semaphore lock;
+	struct class_device *class_dev;
+
+	struct semaphore update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+	unsigned long last_limits;	/* In jiffies */
+
+	/* Register values */
+	u8 in[9];
+	u8 in_high[9];
+	u8 in_low[9];
+	u16 fan[3];
+	u16 fan_low[3];
+	u8 fan_enabled;		/* Read once at init time */
+	u8 temp[3];
+	u8 temp_high[3];
+	u8 temp_hyst[3];
+	u8 temp_mode;
+	u8 alarms[3];
+};
+
+static inline long in_from_reg(u8 reg)
+{
+	return (reg * 8);
+}
+
+/* The 2 least significant bits are not used */
+static inline u8 in_to_reg(long val)
+{
+	if (val <= 0)
+		return 0;
+	if (val >= 2016)
+		return 0xfc;
+	return (((val + 16) / 32) << 2);
+}
+
+/* in0 is downscaled by a factor 2 internally */
+static inline long in0_from_reg(u8 reg)
+{
+	return (reg * 16);
+}
+
+static inline u8 in0_to_reg(long val)
+{
+	if (val <= 0)
+		return 0;
+	if (val >= 4032)
+		return 0xfc;
+	return (((val + 32) / 64) << 2);
+}
+
+/* The 4 most significant bits are not used */
+static inline long fan_from_reg(u16 reg)
+{
+	reg &= 0xfff;
+	if (!reg || reg == 0xfff)
+		return 0;
+	return (1500000 / reg);
+}
+
+static inline u16 fan_to_reg(long rpm)
+{
+	/* If the low limit is set below what the chip can measure,
+	   store the largest possible 12-bit value in the registers,
+	   so that no alarm will ever trigger. */
+	if (rpm < 367)
+		return 0xfff;
+	return (1500000 / rpm);
+}
+
+static inline long temp_from_reg(u8 reg)
+{
+	return (reg * 1000);
+}
+
+static inline u8 temp_to_reg(long val)
+{
+	if (val < 0)
+		val = 0;
+	else if (val > 1000 * 0xff)
+		val = 0xff;
+	return ((val + 500) / 1000);
+}
+
+/*
+ * Device I/O access
+ */
+
+static u8 f71805f_read8(struct f71805f_data *data, u8 reg)
+{
+	u8 val;
+
+	down(&data->lock);
+	outb(reg, data->addr + ADDR_REG_OFFSET);
+	val = inb(data->addr + DATA_REG_OFFSET);
+	up(&data->lock);
+
+	return val;
+}
+
+static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
+{
+	down(&data->lock);
+	outb(reg, data->addr + ADDR_REG_OFFSET);
+	outb(val, data->addr + DATA_REG_OFFSET);
+	up(&data->lock);
+}
+
+/* It is important to read the MSB first, because doing so latches the
+   value of the LSB, so we are sure both bytes belong to the same value. */
+static u16 f71805f_read16(struct f71805f_data *data, u8 reg)
+{
+	u16 val;
+
+	down(&data->lock);
+	outb(reg, data->addr + ADDR_REG_OFFSET);
+	val = inb(data->addr + DATA_REG_OFFSET) << 8;
+	outb(++reg, data->addr + ADDR_REG_OFFSET);
+	val |= inb(data->addr + DATA_REG_OFFSET);
+	up(&data->lock);
+
+	return val;
+}
+
+static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
+{
+	down(&data->lock);
+	outb(reg, data->addr + ADDR_REG_OFFSET);
+	outb(val >> 8, data->addr + DATA_REG_OFFSET);
+	outb(++reg, data->addr + ADDR_REG_OFFSET);
+	outb(val & 0xff, data->addr + DATA_REG_OFFSET);
+	up(&data->lock);
+}
+
+static struct f71805f_data *f71805f_update_device(struct device *dev)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	int nr;
+
+	down(&data->update_lock);
+
+	/* Limit registers cache is refreshed after 60 seconds */
+	if (time_after(jiffies, data->last_updated + 60 * HZ)
+	 || !data->valid) {
+		for (nr = 0; nr < 9; nr++) {
+			data->in_high[nr] = f71805f_read8(data,
+					    F71805F_REG_IN_HIGH(nr));
+			data->in_low[nr] = f71805f_read8(data,
+					   F71805F_REG_IN_LOW(nr));
+		}
+		for (nr = 0; nr < 3; nr++) {
+			if (data->fan_enabled & (1 << nr))
+				data->fan_low[nr] = f71805f_read16(data,
+						    F71805F_REG_FAN_LOW(nr));
+		}
+		for (nr = 0; nr < 3; nr++) {
+			data->temp_high[nr] = f71805f_read8(data,
+					      F71805F_REG_TEMP_HIGH(nr));
+			data->temp_hyst[nr] = f71805f_read8(data,
+					      F71805F_REG_TEMP_HYST(nr));
+		}
+		data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE);
+
+		data->last_limits = jiffies;
+	}
+
+	/* Measurement registers cache is refreshed after 1 second */
+	if (time_after(jiffies, data->last_updated + HZ)
+	 || !data->valid) {
+		for (nr = 0; nr < 9; nr++) {
+			data->in[nr] = f71805f_read8(data,
+				       F71805F_REG_IN(nr));
+		}
+		for (nr = 0; nr < 3; nr++) {
+			if (data->fan_enabled & (1 << nr))
+				data->fan[nr] = f71805f_read16(data,
+						F71805F_REG_FAN(nr));
+		}
+		for (nr = 0; nr < 3; nr++) {
+			data->temp[nr] = f71805f_read8(data,
+					 F71805F_REG_TEMP(nr));
+		}
+		for (nr = 0; nr < 3; nr++) {
+			data->alarms[nr] = f71805f_read8(data,
+					   F71805F_REG_STATUS(nr));
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+
+	return data;
+}
+
+/*
+ * Sysfs interface
+ */
+
+static ssize_t show_in0(struct device *dev, struct device_attribute *devattr,
+			char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+
+	return sprintf(buf, "%ld\n", in0_from_reg(data->in[0]));
+}
+
+static ssize_t show_in0_max(struct device *dev, struct device_attribute
+			    *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+
+	return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0]));
+}
+
+static ssize_t show_in0_min(struct device *dev, struct device_attribute
+			    *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+
+	return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0]));
+}
+
+static ssize_t set_in0_max(struct device *dev, struct device_attribute
+			   *devattr, const char *buf, size_t count)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_high[0] = in0_to_reg(val);
+	f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]);
+	up(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t set_in0_min(struct device *dev, struct device_attribute
+			   *devattr, const char *buf, size_t count)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_low[0] = in0_to_reg(val);
+	f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]);
+	up(&data->update_lock);
+
+	return count;
+}
+
+static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
+static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
+static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
+
+static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
+		       char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", in_from_reg(data->in[nr]));
+}
+
+static ssize_t show_in_max(struct device *dev, struct device_attribute
+			   *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr]));
+}
+
+static ssize_t show_in_min(struct device *dev, struct device_attribute
+			   *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr]));
+}
+
+static ssize_t set_in_max(struct device *dev, struct device_attribute
+			  *devattr, const char *buf, size_t count)
+{
+	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);
+
+	down(&data->update_lock);
+	data->in_high[nr] = in_to_reg(val);
+	f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
+	up(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t set_in_min(struct device *dev, struct device_attribute
+			  *devattr, const char *buf, size_t count)
+{
+	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);
+
+	down(&data->update_lock);
+	data->in_low[nr] = in_to_reg(val);
+	f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
+	up(&data->update_lock);
+
+	return count;
+}
+
+#define sysfs_in(offset)					\
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
+		show_in, NULL, offset);				\
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_in_max, set_in_max, offset);		\
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_in_min, set_in_min, offset)
+
+sysfs_in(1);
+sysfs_in(2);
+sysfs_in(3);
+sysfs_in(4);
+sysfs_in(5);
+sysfs_in(6);
+sysfs_in(7);
+sysfs_in(8);
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
+			char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr]));
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute
+			    *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
+}
+
+static ssize_t set_fan_min(struct device *dev, struct device_attribute
+			   *devattr, const char *buf, size_t count)
+{
+	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);
+
+	down(&data->update_lock);
+	data->fan_low[nr] = fan_to_reg(val);
+	f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]);
+	up(&data->update_lock);
+
+	return count;
+}
+
+#define sysfs_fan(offset)					\
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,		\
+		show_fan, NULL, offset - 1);			\
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_fan_min, set_fan_min, offset - 1)
+
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+			 char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute
+			     *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr]));
+}
+
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute
+			      *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr]));
+}
+
+static ssize_t show_temp_type(struct device *dev, struct device_attribute
+			      *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	/* 3 is diode, 4 is thermistor */
+	return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4);
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute
+			    *devattr, const char *buf, size_t count)
+{
+	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);
+
+	down(&data->update_lock);
+	data->temp_high[nr] = temp_to_reg(val);
+	f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]);
+	up(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute
+			     *devattr, const char *buf, size_t count)
+{
+	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);
+
+	down(&data->update_lock);
+	data->temp_hyst[nr] = temp_to_reg(val);
+	f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
+	up(&data->update_lock);
+
+	return count;
+}
+
+#define sysfs_temp(offset)						\
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
+		show_temp, NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_temp_max, set_temp_max, offset - 1);		\
+static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR,	\
+		show_temp_hyst, set_temp_hyst, offset - 1);		\
+static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO,			\
+		show_temp_type, NULL, offset - 1)
+
+sysfs_temp(1);
+sysfs_temp(2);
+sysfs_temp(3);
+
+static ssize_t show_alarms_in(struct device *dev, struct device_attribute
+			      *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+
+	return sprintf(buf, "%d\n", data->alarms[0] |
+				    ((data->alarms[1] & 0x01) << 8));
+}
+
+static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
+			       *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+
+	return sprintf(buf, "%d\n", data->alarms[2] & 0x07);
+}
+
+static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
+				*devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+
+	return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07);
+}
+
+static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
+static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
+static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+			 *devattr, char *buf)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->name);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+/*
+ * Device registration and initialization
+ */
+
+static void __devinit f71805f_init_device(struct f71805f_data *data)
+{
+	u8 reg;
+	int i;
+
+	reg = f71805f_read8(data, F71805F_REG_START);
+	if ((reg & 0x41) != 0x01) {
+		printk(KERN_DEBUG DRVNAME ": Starting monitoring "
+		       "operations\n");
+		f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);
+	}
+
+	/* Fan monitoring can be disabled. If it is, we won't be polling
+	   the register values, and won't create the related sysfs files. */
+	for (i = 0; i < 3; i++) {
+		reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i));
+		if (!(reg & 0x80))
+			data->fan_enabled |= (1 << i);
+	}
+}
+
+static int __devinit f71805f_probe(struct platform_device *pdev)
+{
+	struct f71805f_data *data;
+	struct resource *res;
+	int err;
+
+	if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Out of memory\n");
+		goto exit;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	data->addr = res->start;
+	init_MUTEX(&data->lock);
+	data->name = "f71805f";
+	init_MUTEX(&data->update_lock);
+
+	platform_set_drvdata(pdev, data);
+
+	data->class_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
+		goto exit_free;
+	}
+
+	/* Initialize the F71805F chip */
+	f71805f_init_device(data);
+
+	/* Register sysfs interface files */
+	device_create_file(&pdev->dev, &dev_attr_in0_input);
+	device_create_file(&pdev->dev, &dev_attr_in0_max);
+	device_create_file(&pdev->dev, &dev_attr_in0_min);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr);
+	if (data->fan_enabled & (1 << 0)) {
+		device_create_file(&pdev->dev,
+				   &sensor_dev_attr_fan1_input.dev_attr);
+		device_create_file(&pdev->dev,
+				   &sensor_dev_attr_fan1_min.dev_attr);
+	}
+	if (data->fan_enabled & (1 << 1)) {
+		device_create_file(&pdev->dev,
+				   &sensor_dev_attr_fan2_input.dev_attr);
+		device_create_file(&pdev->dev,
+				   &sensor_dev_attr_fan2_min.dev_attr);
+	}
+	if (data->fan_enabled & (1 << 2)) {
+		device_create_file(&pdev->dev,
+				   &sensor_dev_attr_fan3_input.dev_attr);
+		device_create_file(&pdev->dev,
+				   &sensor_dev_attr_fan3_min.dev_attr);
+	}
+	device_create_file(&pdev->dev,
+			   &sensor_dev_attr_temp1_input.dev_attr);
+	device_create_file(&pdev->dev,
+			   &sensor_dev_attr_temp2_input.dev_attr);
+	device_create_file(&pdev->dev,
+			   &sensor_dev_attr_temp3_input.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr);
+	device_create_file(&pdev->dev,
+			   &sensor_dev_attr_temp1_max_hyst.dev_attr);
+	device_create_file(&pdev->dev,
+			   &sensor_dev_attr_temp2_max_hyst.dev_attr);
+	device_create_file(&pdev->dev,
+			   &sensor_dev_attr_temp3_max_hyst.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr);
+	device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr);
+	device_create_file(&pdev->dev, &dev_attr_alarms_in);
+	device_create_file(&pdev->dev, &dev_attr_alarms_fan);
+	device_create_file(&pdev->dev, &dev_attr_alarms_temp);
+	device_create_file(&pdev->dev, &dev_attr_name);
+
+	return 0;
+
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int __devexit f71805f_remove(struct platform_device *pdev)
+{
+	struct f71805f_data *data = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	hwmon_device_unregister(data->class_dev);
+	kfree(data);
+
+	return 0;
+}
+
+static struct platform_driver f71805f_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.probe		= f71805f_probe,
+	.remove		= __devexit_p(f71805f_remove),
+};
+
+static int __init f71805f_device_add(unsigned short address)
+{
+	int err;
+
+	pdev = platform_device_alloc(DRVNAME, address);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		goto exit;
+	}
+
+	f71805f_resource.start = address;
+	f71805f_resource.end = address + REGION_LENGTH - 1;
+	f71805f_resource.name = pdev->name;
+	err = platform_device_add_resources(pdev, &f71805f_resource, 1);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device resource addition failed "
+		       "(%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+		       err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit:
+	return err;
+}
+
+static int __init f71805f_find(int sioaddr, unsigned short *address)
+{
+	int err = -ENODEV;
+	u16 devid;
+
+	superio_enter(sioaddr);
+
+	devid = superio_inw(sioaddr, SIO_REG_MANID);
+	if (devid != SIO_FINTEK_ID)
+		goto exit;
+
+	devid = superio_inw(sioaddr, SIO_REG_DEVID);
+	if (devid != SIO_F71805F_ID) {
+		printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
+		       "skipping\n");
+		goto exit;
+	}
+
+	superio_select(sioaddr, F71805F_LD_HWM);
+	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+		printk(KERN_WARNING DRVNAME ": Device not activated, "
+		       "skipping\n");
+		goto exit;
+	}
+
+	*address = superio_inw(sioaddr, SIO_REG_ADDR);
+	if (*address == 0) {
+		printk(KERN_WARNING DRVNAME ": Base address not set, "
+		       "skipping\n");
+		goto exit;
+	}
+
+	err = 0;
+	printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
+	       *address, superio_inb(sioaddr, SIO_REG_DEVREV));
+
+exit:
+	superio_exit(sioaddr);
+	return err;
+}
+
+static int __init f71805f_init(void)
+{
+	int err;
+	unsigned short address;
+
+	if (f71805f_find(0x2e, &address)
+	 && f71805f_find(0x4e, &address))
+		return -ENODEV;
+
+	err = platform_driver_register(&f71805f_driver);
+	if (err)
+		goto exit;
+
+	/* Sets global pdev as a side effect */
+	err = f71805f_device_add(address);
+	if (err)
+		goto exit_driver;
+
+	return 0;
+
+exit_driver:
+	platform_driver_unregister(&f71805f_driver);
+exit:
+	return err;
+}
+
+static void __exit f71805f_exit(void)
+{
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&f71805f_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("F71805F hardware monitoring driver");
+
+module_init(f71805f_init);
+module_exit(f71805f_exit);
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 0da7c9c..e87d52c 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -45,8 +45,7 @@
 
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
-					0x2e, 0x2f, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
 static unsigned short isa_address;
 
 /* Insmod parameters */
@@ -830,6 +829,11 @@
 	if ((err = i2c_attach_client(new_client)))
 		goto ERROR2;
 
+	if (!is_isa)
+		dev_info(&new_client->dev, "The I2C interface to IT87xxF "
+			 "hardware monitoring chips is deprecated. Please "
+			 "report if you still rely on it.\n");
+
 	/* Check PWM configuration */
 	enable_pwm_interface = it87_check_pwm(new_client);
 
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index a2f420d..df9e02a 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -87,15 +87,15 @@
 
 /* In the temperature registers, the low 3 bits are not part of the
    temperature values; they are the status bits. */
-static inline u16 LM77_TEMP_TO_REG(int temp)
+static inline s16 LM77_TEMP_TO_REG(int temp)
 {
 	int ntemp = SENSORS_LIMIT(temp, LM77_TEMP_MIN, LM77_TEMP_MAX);
-	return (u16)((ntemp / 500) * 8);
+	return (ntemp / 500) * 8;
 }
 
-static inline int LM77_TEMP_FROM_REG(u16 reg)
+static inline int LM77_TEMP_FROM_REG(s16 reg)
 {
-	return ((int)reg / 8) * 500;
+	return (reg / 8) * 500;
 }
 
 /* sysfs stuff */
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index b176bf0..a2f6bb6 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -303,10 +303,6 @@
 static int w83792d_attach_adapter(struct i2c_adapter *adapter);
 static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind);
 static int w83792d_detach_client(struct i2c_client *client);
-
-static int w83792d_read_value(struct i2c_client *client, u8 register);
-static int w83792d_write_value(struct i2c_client *client, u8 register,
-				u8 value);
 static struct w83792d_data *w83792d_update_device(struct device *dev);
 
 #ifdef DEBUG
@@ -329,6 +325,20 @@
 	return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03));
 }
 
+/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
+   but the driver only accesses registers in bank 0, so we don't have
+   to switch banks and lock access between switches. */
+static inline int w83792d_read_value(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static inline int
+w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
 /* following are the sysfs callback functions */
 static ssize_t show_in(struct device *dev, struct device_attribute *attr,
 			char *buf)
@@ -1386,19 +1396,6 @@
 	return 0;
 }
 
-/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
-   but the driver only accesses registers in bank 0, so we don't have
-   to switch banks and lock access between switches. */
-static int w83792d_read_value(struct i2c_client *client, u8 reg)
-{
-	return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
-{
-	return i2c_smbus_write_byte_data(client, reg, value);
-}
-
 static void
 w83792d_init_client(struct i2c_client *client)
 {
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index 938848a..3df3f09 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -202,7 +202,7 @@
 #ifdef MODULE
 MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
 MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
-MODULE_PARM(bit_scan, "i");
+module_param(bit_scan, int, 0);
 MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 08d5b8f..ff92735 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -124,6 +124,7 @@
 	    ICH6
 	    ICH7
 	    ESB2
+	    ICH8
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-i801.
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 1c752dd..8e0f315 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -32,6 +32,7 @@
     ICH6		266A
     ICH7		27DA
     ESB2		269B
+    ICH8		283E
     This driver supports several versions of Intel's I/O Controller Hubs (ICH).
     For SMBus support, they are similar to the PIIX4 and are part
     of Intel's '810' and other chipsets.
@@ -527,6 +528,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
 	{ 0, }
 };
 
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index 3e5eba9..c63025a 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -121,14 +121,11 @@
 
 static int __init i2c_parport_init(void)
 {
-	int type_count;
-
-	type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm);
-	if (type < 0 || type >= type_count) {
+	if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
 		printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
 		type = 0;
 	}
-	
+
 	if (base == 0) {
 		printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE);
 		base = DEFAULT_BASE;
@@ -152,7 +149,7 @@
 		release_region(base, 3);
 		return -ENODEV;
 	}
-	
+
 	return 0;
 }
 
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 2854d85..7e2e8cd 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -241,14 +241,11 @@
 
 static int __init i2c_parport_init(void)
 {
-	int type_count;
-
-	type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm);
-	if (type < 0 || type >= type_count) {
+	if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
 		printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
 		type = 0;
 	}
-	
+
 	return parport_register_driver(&i2c_parport_driver);
 }
 
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 86e2234..7579f4b 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -861,7 +861,7 @@
 		decode_ISR(isr);
 	}
 
-	if (i2c->irqlogidx < sizeof(i2c->isrlog)/sizeof(u32))
+	if (i2c->irqlogidx < ARRAY_SIZE(i2c->isrlog))
 		i2c->isrlog[i2c->irqlogidx++] = isr;
 
 	show_state(i2c);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 0ce58b5..1a2c9ab 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -946,6 +946,20 @@
 	}
 }
 
+s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
+				   u8 length, u8 *values)
+{
+	union i2c_smbus_data data;
+
+	if (length > I2C_SMBUS_BLOCK_MAX)
+		length = I2C_SMBUS_BLOCK_MAX;
+	data.block[0] = length;
+	memcpy(data.block + 1, values, length);
+	return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+			      I2C_SMBUS_WRITE, command,
+			      I2C_SMBUS_I2C_BLOCK_DATA, &data);
+}
+
 /* Simulate a SMBus command using the i2c protocol 
    No checking of parameters is done!  */
 static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, 
@@ -1150,6 +1164,7 @@
 EXPORT_SYMBOL(i2c_smbus_write_word_data);
 EXPORT_SYMBOL(i2c_smbus_write_block_data);
 EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
+EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
 
 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus main module");
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 1c81174..d633081 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -52,9 +52,9 @@
 
 if IDE
 
-config IDE_MAX_HWIFS 
+config IDE_MAX_HWIFS
 	int "Max IDE interfaces"
-	depends on ALPHA || SUPERH
+	depends on ALPHA || SUPERH || IA64
 	default 4
 	help
 	  This is the maximum number of IDE hardware interfaces that will
@@ -162,8 +162,8 @@
 	tristate "PCMCIA IDE support"
 	depends on PCMCIA
 	help
-	  Support for outboard IDE disks, tape drives, and CD-ROM drives
-	  connected through a  PCMCIA card.
+	  Support for Compact Flash cards, outboard IDE disks, tape drives,
+	  and CD-ROM drives connected through a PCMCIA card.
 
 config BLK_DEV_IDECD
 	tristate "Include IDE/ATAPI CDROM support"
@@ -267,7 +267,7 @@
 	help
 	  This is a direct raw access to the media.  It is a complex but
 	  elegant solution to test and validate the domain of the hardware and
-	  perform below the driver data recover if needed.  This is the most
+	  perform below the driver data recovery if needed.  This is the most
 	  basic form of media-forensics.
 
 	  If you are unsure, say N here.
@@ -525,7 +525,7 @@
 	tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 	help
-	  Include support for PIO tuning an virtual DMA on the Cyrix MediaGX 
+	  Include support for PIO tuning and virtual DMA on the Cyrix MediaGX
 	  5510/5520 chipset. This will automatically be detected and
 	  configured if found.
 
@@ -662,7 +662,7 @@
 
 	  It was originally designed for the PDC20246/Ultra33, whose BIOS will
 	  only setup UDMA on the first two PDC20246 cards.  It has also been
-	  used succesfully on a PDC20265/Ultra100, allowing use of UDMA modes
+	  used successfully on a PDC20265/Ultra100, allowing use of UDMA modes
 	  when the PDC20265 BIOS has been disabled (for faster boot up).
 
 	  Please read the comments at the top of
@@ -673,13 +673,6 @@
 config BLK_DEV_PDC202XX_NEW
 	tristate "PROMISE PDC202{68|69|70|71|75|76|77} support"
 
-# FIXME - probably wants to be one for old and for new
-config PDC202XX_FORCE
-	bool "Enable controller even if disabled by BIOS"
-	depends on BLK_DEV_PDC202XX_NEW
-	help
-	  Enable the PDC202xx controller even if it has been disabled in the BIOS setup.
-
 config BLK_DEV_SVWKS
 	tristate "ServerWorks OSB4/CSB5/CSB6 chipsets support"
 	help
@@ -722,7 +715,7 @@
 config BLK_DEV_SLC90E66
 	tristate "SLC90E66 chipset support"
 	help
-	  This driver ensures (U)DMA support for Victroy66 SouthBridges for
+	  This driver ensures (U)DMA support for Victory66 SouthBridges for
 	  SMsC with Intel NorthBridges.  This is an Ultra66 based chipset.
 	  The nice thing about it is that you can mix Ultra/DMA/PIO devices
 	  and it will handle timing cycles.  Since this is an improved
@@ -1060,7 +1053,7 @@
 	  in that mode with an 80c ribbon.
 
 	  If you are experiencing compatibility or performance problems, you
-	  MAY try to answering Y here. However, it does not necessarily solve
+	  MAY try to answer Y here. However, it does not necessarily solve
 	  any of your problems, it could even cause more of them.
 
 	  It is normally safe to answer Y; however, the default is N.
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index ca25f9e..09086b8 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -190,7 +190,8 @@
 		if (lba48) {
 			task_ioreg_t tasklets[10];
 
-			pr_debug("%s: LBA=0x%012llx\n", drive->name, block);
+			pr_debug("%s: LBA=0x%012llx\n", drive->name,
+					(unsigned long long)block);
 
 			tasklets[0] = 0;
 			tasklets[1] = 0;
@@ -317,7 +318,8 @@
 
 	pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
 		 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
-		 block, rq->nr_sectors, (unsigned long)rq->buffer);
+		 (unsigned long long)block, rq->nr_sectors,
+		 (unsigned long)rq->buffer);
 
 	if (hwif->rw_disk)
 		hwif->rw_disk(drive, rq);
@@ -776,7 +778,7 @@
 			 ide_id_has_flush_cache_ext(id));
 
 		printk(KERN_INFO "%s: cache flushes %ssupported\n",
-		       drive->name, barrier ? "" : "not");
+		       drive->name, barrier ? "" : "not ");
 
 		if (barrier) {
 			ordered = QUEUE_ORDERED_DRAIN_FLUSH;
@@ -889,11 +891,7 @@
 	if (drive->id_read == 0)
 		return;
 
-	/*
-	 * CompactFlash cards and their brethern look just like hard drives
-	 * to us, but they are removable and don't have a doorlock mechanism.
-	 */
-	if (drive->removable && !(drive->is_flash)) {
+	if (drive->removable) {
 		/*
 		 * Removable disks (eg. SYQUEST); ignore 'WD' drives 
 		 */
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 8d50df4..c01615d 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -55,8 +55,8 @@
 #include <asm/io.h>
 #include <asm/bitops.h>
 
-int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
-		      int nr_sectors)
+static int __ide_end_request(ide_drive_t *drive, struct request *rq,
+			     int uptodate, int nr_sectors)
 {
 	int ret = 1;
 
@@ -91,7 +91,6 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(__ide_end_request);
 
 /**
  *	ide_end_request		-	complete an IDE I/O
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index af7af95..b72dde7 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -1243,6 +1243,7 @@
 		 */
 		if (stat == 0xff)
 			return -ENODEV;
+		touch_softlockup_watchdog();
 	}
 	return -EBUSY;
 }
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index e742554..427d1c2 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -125,45 +125,6 @@
 }
 
 /**
- *	drive_is_flashcard	-	check for compact flash
- *	@drive: drive to check
- *
- *	CompactFlash cards and their brethern pretend to be removable
- *	hard disks, except:
- * 		(1) they never have a slave unit, and
- *		(2) they don't have doorlock mechanisms.
- *	This test catches them, and is invoked elsewhere when setting
- *	appropriate config bits.
- *
- *	FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD)
- *	devices, so in linux 2.3.x we should change this to just treat all
- *	PCMCIA  drives this way, and get rid of the model-name tests below
- *	(too big of an interface change for 2.4.x).
- *	At that time, we might also consider parameterizing the timeouts and
- *	retries, since these are MUCH faster than mechanical drives. -M.Lord
- */
- 
-static inline int drive_is_flashcard (ide_drive_t *drive)
-{
-	struct hd_driveid *id = drive->id;
-
-	if (drive->removable) {
-		if (id->config == 0x848a) return 1;	/* CompactFlash */
-		if (!strncmp(id->model, "KODAK ATA_FLASH", 15)	/* Kodak */
-		 || !strncmp(id->model, "Hitachi CV", 10)	/* Hitachi */
-		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* old SanDisk */
-		 || !strncmp(id->model, "SanDisk SDCFB", 13)	/* SanDisk */
-		 || !strncmp(id->model, "HAGIWARA HPC", 12)	/* Hagiwara */
-		 || !strncmp(id->model, "LEXAR ATA_FLASH", 15)	/* Lexar */
-		 || !strncmp(id->model, "ATA_FLASH", 9))	/* Simple Tech */
-		{
-			return 1;	/* yes, it is a flash memory card */
-		}
-	}
-	return 0;	/* no, it is not a flash memory card */
-}
-
-/**
  *	do_identify	-	identify a drive
  *	@drive: drive to identify 
  *	@cmd: command used
@@ -278,13 +239,17 @@
 	/*
 	 * Not an ATAPI device: looks like a "regular" hard disk
 	 */
-	if (id->config & (1<<7))
+
+	/*
+	 * 0x848a = CompactFlash device
+	 * These are *not* removable in Linux definition of the term
+	 */
+
+	if ((id->config != 0x848a) && (id->config & (1<<7)))
 		drive->removable = 1;
 
-	if (drive_is_flashcard(drive))
-		drive->is_flash = 1;
 	drive->media = ide_disk;
-	printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" );
+	printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
 	QUIRK_LIST(drive);
 	return;
 
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index afeb02b..b2cc437 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -242,7 +242,6 @@
 		drive->name[2]			= 'a' + (index * MAX_DRIVES) + unit;
 		drive->max_failures		= IDE_DEFAULT_MAX_FAILURES;
 		drive->using_dma		= 0;
-		drive->is_flash			= 0;
 		drive->vdma			= 0;
 		INIT_LIST_HEAD(&drive->list);
 		init_completion(&drive->gendev_rel_comp);
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index a21b1e1..c743e68 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -262,6 +262,21 @@
 	else
 		pci_set_drvdata(dev, (void *) aec6xxx_34_base);
 
+	/* These are necessary to get AEC6280 Macintosh cards to work */
+	if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
+	    (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) {
+		u8 reg49h = 0, reg4ah = 0;
+		/* Clear reset and test bits.  */
+		pci_read_config_byte(dev, 0x49, &reg49h);
+		pci_write_config_byte(dev, 0x49, reg49h & ~0x30);
+		/* Enable chip interrupt output.  */
+		pci_read_config_byte(dev, 0x4a, &reg4ah);
+		pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01);
+		/* Enable burst mode. */
+		pci_read_config_byte(dev, 0x4a, &reg4ah);
+		pci_write_config_byte(dev, 0x4a, reg4ah | 0x80);
+	}
+
 	return dev->irq;
 }
 
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 7b589d9..940bdd4 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1288,6 +1288,10 @@
 				goto init_hpt37X_done;
 			}
 		}
+		if (!pci_get_drvdata(dev)) {
+			printk("No Clock Stabilization!!!\n");
+			return;
+		}
 pll_recal:
 		if (adjust & 1)
 			pll -= (adjust >> 1);
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 108fda8..38f41b3 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -733,7 +733,7 @@
 
 	pci_write_config_dword(dev,0x4C, 0x02040204);
 	pci_write_config_byte(dev, 0x42, 0x36);
-	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
 }
 
 static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name)
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index fe06ebb..acd6317 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -420,9 +420,6 @@
 		.init_hwif	= init_hwif_pdc202new,
 		.channels	= 2,
 		.autodma	= AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
 		.bootable	= OFF_BOARD,
 	},{	/* 3 */
 		.name		= "PDC20271",
@@ -447,9 +444,6 @@
 		.init_hwif	= init_hwif_pdc202new,
 		.channels	= 2,
 		.autodma	= AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
 		.bootable	= OFF_BOARD,
 	},{	/* 6 */
 		.name		= "PDC20277",
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index ad9d9581..6f8f864 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -786,9 +786,6 @@
 		.init_dma	= init_dma_pdc202xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
 		.bootable	= OFF_BOARD,
 		.extra		= 16,
 	},{	/* 1 */
@@ -799,9 +796,6 @@
 		.init_dma	= init_dma_pdc202xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
 		.bootable	= OFF_BOARD,
 		.extra		= 48,
 		.flags		= IDEPCI_FLAG_FORCE_PDC,
@@ -813,9 +807,6 @@
 		.init_dma	= init_dma_pdc202xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
 		.bootable	= OFF_BOARD,
 		.extra		= 48,
 	},{	/* 3 */
@@ -826,9 +817,6 @@
 		.init_dma	= init_dma_pdc202xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
 		.bootable	= OFF_BOARD,
 		.extra		= 48,
 		.flags		= IDEPCI_FLAG_FORCE_PDC,
@@ -840,9 +828,6 @@
 		.init_dma	= init_dma_pdc202xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
 		.bootable	= OFF_BOARD,
 		.extra		= 48,
 	}
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index b3e77df..e9b83e1 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -135,6 +135,7 @@
 		case PCI_DEVICE_ID_INTEL_ICH6_19:
 		case PCI_DEVICE_ID_INTEL_ICH7_21:
 		case PCI_DEVICE_ID_INTEL_ESB2_18:
+		case PCI_DEVICE_ID_INTEL_ICH8_6:
 			mode = 3;
 			break;
 		/* UDMA 66 capable */
@@ -449,6 +450,7 @@
 		case PCI_DEVICE_ID_INTEL_ICH6_19:
 		case PCI_DEVICE_ID_INTEL_ICH7_21:
 		case PCI_DEVICE_ID_INTEL_ESB2_18:
+		case PCI_DEVICE_ID_INTEL_ICH8_6:
 		{
 			unsigned int extra = 0;
 			pci_read_config_dword(dev, 0x54, &extra);
@@ -575,6 +577,7 @@
 	/* 21 */ DECLARE_PIIX_DEV("ICH7"),
 	/* 22 */ DECLARE_PIIX_DEV("ICH4"),
 	/* 23 */ DECLARE_PIIX_DEV("ESB2"),
+	/* 24 */ DECLARE_PIIX_DEV("ICH8M"),
 };
 
 /**
@@ -651,6 +654,7 @@
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 23},
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 24},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 4ee597d..2b286e8 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2003-2006 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -510,7 +510,7 @@
 				       drive->name);
 				goto use_pio_instead;
 			} else {
-				u32 xcount, bcount =
+				u32 bcount =
 				    0x10000 - (cur_addr & 0xffff);
 
 				if (bcount > cur_len)
@@ -525,8 +525,7 @@
 				*table = 0x0;
 				table++;
 
-				xcount = bcount & 0xffff;
-				*table = cpu_to_be32(xcount);
+				*table = cpu_to_be32(bcount);
 				table++;
 
 				cur_addr += bcount;
@@ -680,7 +679,7 @@
 		return -EIO;
 
 	/* Create /proc/ide entries */
-	create_proc_ide_interfaces(); 
+	create_proc_ide_interfaces();
 
 	return 0;
 }
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index acda7d6..501cc05 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -956,6 +956,8 @@
 
 	ib_unregister_event_handler(&sa_dev->event_handler);
 
+	flush_scheduled_work();
+
 	for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
 		ib_unregister_mad_agent(sa_dev->port[i].agent);
 		kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index e95c429..f6a0596 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1319,15 +1319,6 @@
 	.release = ib_ucm_release_class_dev
 };
 
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
-	struct ib_ucm_device *dev;
-	
-	dev = container_of(class_dev, struct ib_ucm_device, class_dev);
-	return print_dev_t(buf, dev->dev.dev);
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
 static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
 {
 	struct ib_ucm_device *dev;
@@ -1364,15 +1355,13 @@
 
 	ucm_dev->class_dev.class = &ucm_class;
 	ucm_dev->class_dev.dev = device->dma_device;
+	ucm_dev->class_dev.devt = ucm_dev->dev.dev;
 	snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
 		 ucm_dev->devnum);
 	if (class_device_register(&ucm_dev->class_dev))
 		goto err_cdev;
 
 	if (class_device_create_file(&ucm_dev->class_dev,
-				     &class_device_attr_dev))
-		goto err_class;
-	if (class_device_create_file(&ucm_dev->class_dev,
 				     &class_device_attr_ibdev))
 		goto err_class;
 
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 96ea79b..903f85a 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -902,6 +902,7 @@
 	unregister_filesystem(&uverbs_event_fs);
 	class_destroy(uverbs_class);
 	unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+	flush_scheduled_work();
 	idr_destroy(&ib_uverbs_pd_idr);
 	idr_destroy(&ib_uverbs_mr_idr);
 	idr_destroy(&ib_uverbs_mw_idr);
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index a14eed0..a19e0ed 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -184,7 +184,7 @@
 			ah->av->sl_tclass_flowlabel & cpu_to_be32(0xfffff);
 		ib_get_cached_gid(&dev->ib_dev,
 				  be32_to_cpu(ah->av->port_pd) >> 24,
-				  ah->av->gid_index,
+				  ah->av->gid_index % dev->limits.gid_table_len,
 				  &header->grh.source_gid);
 		memcpy(header->grh.destination_gid.raw,
 		       ah->av->dgid, 16);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index be1791b..f9b9b93 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -199,8 +199,7 @@
 {
 	int err = 0;
 
-	if (down_interruptible(&dev->cmd.hcr_sem))
-		return -EINTR;
+	mutex_lock(&dev->cmd.hcr_mutex);
 
 	if (event) {
 		unsigned long end = jiffies + GO_BIT_TIMEOUT;
@@ -238,7 +237,7 @@
 					       op),                       dev->hcr + 6 * 4);
 
 out:
-	up(&dev->cmd.hcr_sem);
+	mutex_unlock(&dev->cmd.hcr_mutex);
 	return err;
 }
 
@@ -255,8 +254,7 @@
 	int err = 0;
 	unsigned long end;
 
-	if (down_interruptible(&dev->cmd.poll_sem))
-		return -EINTR;
+	down(&dev->cmd.poll_sem);
 
 	err = mthca_cmd_post(dev, in_param,
 			     out_param ? *out_param : 0,
@@ -333,8 +331,7 @@
 	int err = 0;
 	struct mthca_cmd_context *context;
 
-	if (down_interruptible(&dev->cmd.event_sem))
-		return -EINTR;
+	down(&dev->cmd.event_sem);
 
 	spin_lock(&dev->cmd.context_lock);
 	BUG_ON(dev->cmd.free_head < 0);
@@ -438,7 +435,7 @@
 
 int mthca_cmd_init(struct mthca_dev *dev)
 {
-	sema_init(&dev->cmd.hcr_sem, 1);
+	mutex_init(&dev->cmd.hcr_mutex);
 	sema_init(&dev->cmd.poll_sem, 1);
 	dev->cmd.use_events = 0;
 
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index a104ab0..2a165fd 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -44,6 +44,8 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/timer.h>
+#include <linux/mutex.h>
+
 #include <asm/semaphore.h>
 
 #include "mthca_provider.h"
@@ -111,7 +113,7 @@
 struct mthca_cmd {
 	struct pci_pool          *pool;
 	int                       use_events;
-	struct semaphore          hcr_sem;
+	struct mutex              hcr_mutex;
 	struct semaphore 	  poll_sem;
 	struct semaphore 	  event_sem;
 	int              	  max_cmds;
@@ -256,7 +258,7 @@
 };
 
 struct mthca_mcg_table {
-	struct semaphore   	sem;
+	struct mutex		mutex;
 	struct mthca_alloc 	alloc;
 	struct mthca_icm_table *table;
 };
@@ -301,7 +303,7 @@
 	u64              ddr_end;
 
 	MTHCA_DECLARE_DOORBELL_LOCK(doorbell_lock)
-	struct semaphore cap_mask_mutex;
+	struct mutex cap_mask_mutex;
 
 	void __iomem    *hcr;
 	void __iomem    *kar;
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 8b00d9a..9c849d2 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -155,6 +155,13 @@
 		return -ENODEV;
 	}
 
+	if (dev_lim->uar_size > pci_resource_len(mdev->pdev, 2)) {
+		mthca_err(mdev, "HCA reported UAR size of 0x%x bigger than "
+			  "PCI resource 2 size of 0x%lx, aborting.\n",
+			  dev_lim->uar_size, pci_resource_len(mdev->pdev, 2));
+		return -ENODEV;
+	}
+
 	mdev->limits.num_ports      	= dev_lim->num_ports;
 	mdev->limits.vl_cap             = dev_lim->max_vl;
 	mdev->limits.mtu_cap            = dev_lim->max_mtu;
@@ -976,8 +983,7 @@
 		err = -ENODEV;
 		goto err_disable_pdev;
 	}
-	if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM) ||
-	    pci_resource_len(pdev, 2) != 1 << 23) {
+	if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
 		dev_err(&pdev->dev, "Missing UAR, aborting.\n");
 		err = -ENODEV;
 		goto err_disable_pdev;
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 77bc6c7..321f11e 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -154,10 +154,7 @@
 		return PTR_ERR(mailbox);
 	mgm = mailbox->buf;
 
-	if (down_interruptible(&dev->mcg_table.sem)) {
-		err = -EINTR;
-		goto err_sem;
-	}
+	mutex_lock(&dev->mcg_table.mutex);
 
 	err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
 	if (err)
@@ -241,8 +238,8 @@
 		BUG_ON(index < dev->limits.num_mgms);
 		mthca_free(&dev->mcg_table.alloc, index);
 	}
-	up(&dev->mcg_table.sem);
- err_sem:
+	mutex_unlock(&dev->mcg_table.mutex);
+
 	mthca_free_mailbox(dev, mailbox);
 	return err;
 }
@@ -263,10 +260,7 @@
 		return PTR_ERR(mailbox);
 	mgm = mailbox->buf;
 
-	if (down_interruptible(&dev->mcg_table.sem)) {
-		err = -EINTR;
-		goto err_sem;
-	}
+	mutex_lock(&dev->mcg_table.mutex);
 
 	err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
 	if (err)
@@ -371,8 +365,8 @@
 	}
 
  out:
-	up(&dev->mcg_table.sem);
- err_sem:
+	mutex_unlock(&dev->mcg_table.mutex);
+
 	mthca_free_mailbox(dev, mailbox);
 	return err;
 }
@@ -389,7 +383,7 @@
 	if (err)
 		return err;
 
-	init_MUTEX(&dev->mcg_table.sem);
+	mutex_init(&dev->mcg_table.mutex);
 
 	return 0;
 }
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 9fb985a..d709cb1 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -50,7 +50,7 @@
 };
 
 struct mthca_user_db_table {
-	struct semaphore mutex;
+	struct mutex mutex;
 	struct {
 		u64                uvirt;
 		struct scatterlist mem;
@@ -158,7 +158,7 @@
 	int ret = 0;
 	u8 status;
 
-	down(&table->mutex);
+	mutex_lock(&table->mutex);
 
 	if (table->icm[i]) {
 		++table->icm[i]->refcount;
@@ -184,7 +184,7 @@
 	++table->icm[i]->refcount;
 
 out:
-	up(&table->mutex);
+	mutex_unlock(&table->mutex);
 	return ret;
 }
 
@@ -198,7 +198,7 @@
 
 	i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
 
-	down(&table->mutex);
+	mutex_lock(&table->mutex);
 
 	if (--table->icm[i]->refcount == 0) {
 		mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
@@ -207,7 +207,7 @@
 		table->icm[i] = NULL;
 	}
 
-	up(&table->mutex);
+	mutex_unlock(&table->mutex);
 }
 
 void *mthca_table_find(struct mthca_icm_table *table, int obj)
@@ -220,7 +220,7 @@
 	if (!table->lowmem)
 		return NULL;
 
-	down(&table->mutex);
+	mutex_lock(&table->mutex);
 
 	idx = (obj & (table->num_obj - 1)) * table->obj_size;
 	icm = table->icm[idx / MTHCA_TABLE_CHUNK_SIZE];
@@ -240,7 +240,7 @@
 	}
 
 out:
-	up(&table->mutex);
+	mutex_unlock(&table->mutex);
 	return page ? lowmem_page_address(page) + offset : NULL;
 }
 
@@ -301,7 +301,7 @@
 	table->num_obj  = nobj;
 	table->obj_size = obj_size;
 	table->lowmem   = use_lowmem;
-	init_MUTEX(&table->mutex);
+	mutex_init(&table->mutex);
 
 	for (i = 0; i < num_icm; ++i)
 		table->icm[i] = NULL;
@@ -380,7 +380,7 @@
 	if (index < 0 || index > dev->uar_table.uarc_size / 8)
 		return -EINVAL;
 
-	down(&db_tab->mutex);
+	mutex_lock(&db_tab->mutex);
 
 	i = index / MTHCA_DB_REC_PER_PAGE;
 
@@ -424,7 +424,7 @@
 	db_tab->page[i].refcount = 1;
 
 out:
-	up(&db_tab->mutex);
+	mutex_unlock(&db_tab->mutex);
 	return ret;
 }
 
@@ -439,11 +439,11 @@
 	 * pages until we clean up the whole db table.
 	 */
 
-	down(&db_tab->mutex);
+	mutex_lock(&db_tab->mutex);
 
 	--db_tab->page[index / MTHCA_DB_REC_PER_PAGE].refcount;
 
-	up(&db_tab->mutex);
+	mutex_unlock(&db_tab->mutex);
 }
 
 struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev)
@@ -460,7 +460,7 @@
 	if (!db_tab)
 		return ERR_PTR(-ENOMEM);
 
-	init_MUTEX(&db_tab->mutex);
+	mutex_init(&db_tab->mutex);
 	for (i = 0; i < npages; ++i) {
 		db_tab->page[i].refcount = 0;
 		db_tab->page[i].uvirt    = 0;
@@ -499,7 +499,7 @@
 	int ret = 0;
 	u8 status;
 
-	down(&dev->db_tab->mutex);
+	mutex_lock(&dev->db_tab->mutex);
 
 	switch (type) {
 	case MTHCA_DB_TYPE_CQ_ARM:
@@ -585,7 +585,7 @@
 	*db = (__be32 *) &page->db_rec[j];
 
 out:
-	up(&dev->db_tab->mutex);
+	mutex_unlock(&dev->db_tab->mutex);
 
 	return ret;
 }
@@ -601,7 +601,7 @@
 
 	page = dev->db_tab->page + i;
 
-	down(&dev->db_tab->mutex);
+	mutex_lock(&dev->db_tab->mutex);
 
 	page->db_rec[j] = 0;
 	if (i >= dev->db_tab->min_group2)
@@ -624,7 +624,7 @@
 			++dev->db_tab->min_group2;
 	}
 
-	up(&dev->db_tab->mutex);
+	mutex_unlock(&dev->db_tab->mutex);
 }
 
 int mthca_init_db_tab(struct mthca_dev *dev)
@@ -638,7 +638,7 @@
 	if (!dev->db_tab)
 		return -ENOMEM;
 
-	init_MUTEX(&dev->db_tab->mutex);
+	mutex_init(&dev->db_tab->mutex);
 
 	dev->db_tab->npages     = dev->uar_table.uarc_size / 4096;
 	dev->db_tab->max_group1 = 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index 4fdca26..36f1141 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -39,8 +39,7 @@
 
 #include <linux/list.h>
 #include <linux/pci.h>
-
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 #define MTHCA_ICM_CHUNK_LEN \
 	((256 - sizeof (struct list_head) - 2 * sizeof (int)) /		\
@@ -64,7 +63,7 @@
 	int               num_obj;
 	int               obj_size;
 	int               lowmem;
-	struct semaphore  mutex;
+	struct mutex      mutex;
 	struct mthca_icm *icm[0];
 };
 
@@ -147,7 +146,7 @@
 	int 	       	      max_group1;
 	int 	       	      min_group2;
 	struct mthca_db_page *page;
-	struct semaphore      mutex;
+	struct mutex          mutex;
 };
 
 enum mthca_db_type {
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 484a7e6..e88e39a 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -185,7 +185,7 @@
 	int err;
 	u8 status;
 
-	if (down_interruptible(&to_mdev(ibdev)->cap_mask_mutex))
+	if (mutex_lock_interruptible(&to_mdev(ibdev)->cap_mask_mutex))
 		return -ERESTARTSYS;
 
 	err = mthca_query_port(ibdev, port, &attr);
@@ -207,7 +207,7 @@
 	}
 
 out:
-	up(&to_mdev(ibdev)->cap_mask_mutex);
+	mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex);
 	return err;
 }
 
@@ -1185,7 +1185,7 @@
 		dev->ib_dev.post_recv     = mthca_tavor_post_receive;
 	}
 
-	init_MUTEX(&dev->cap_mask_mutex);
+	mutex_init(&dev->cap_mask_mutex);
 
 	ret = ib_register_device(&dev->ib_dev);
 	if (ret)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index fd3f5c8..c3b5f79 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -505,7 +505,7 @@
 
 	list_add_tail(&neigh->list, &path->neigh_list);
 
-	if (path->pathrec.dlid) {
+	if (path->ah) {
 		kref_get(&path->ah->ref);
 		neigh->ah = path->ah;
 
@@ -591,7 +591,7 @@
 		return;
 	}
 
-	if (path->pathrec.dlid) {
+	if (path->ah) {
 		ipoib_dbg(priv, "Send unicast ARP to %04x\n",
 			  be16_to_cpu(path->pathrec.dlid));
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 98039da..ccaa0c3 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -97,6 +97,7 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_neigh *neigh, *tmp;
 	unsigned long flags;
+	int tx_dropped = 0;
 
 	ipoib_dbg_mcast(netdev_priv(dev),
 			"deleting multicast group " IPOIB_GID_FMT "\n",
@@ -123,8 +124,14 @@
 	if (mcast->ah)
 		ipoib_put_ah(mcast->ah);
 
-	while (!skb_queue_empty(&mcast->pkt_queue))
+	while (!skb_queue_empty(&mcast->pkt_queue)) {
+		++tx_dropped;
 		dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
+	}
+
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	priv->stats.tx_dropped += tx_dropped;
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
 
 	kfree(mcast);
 }
@@ -276,8 +283,10 @@
 	}
 
 	/* actually send any queued packets */
+	spin_lock_irq(&priv->tx_lock);
 	while (!skb_queue_empty(&mcast->pkt_queue)) {
 		struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
+		spin_unlock_irq(&priv->tx_lock);
 
 		skb->dev = dev;
 
@@ -288,7 +297,9 @@
 
 		if (dev_queue_xmit(skb))
 			ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
+		spin_lock_irq(&priv->tx_lock);
 	}
+	spin_unlock_irq(&priv->tx_lock);
 
 	return 0;
 }
@@ -300,6 +311,7 @@
 {
 	struct ipoib_mcast *mcast = mcast_ptr;
 	struct net_device *dev = mcast->dev;
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
 	if (!status)
 		ipoib_mcast_join_finish(mcast, mcmember);
@@ -310,8 +322,12 @@
 					IPOIB_GID_ARG(mcast->mcmember.mgid), status);
 
 		/* Flush out any queued packets */
-		while (!skb_queue_empty(&mcast->pkt_queue))
+		spin_lock_irq(&priv->tx_lock);
+		while (!skb_queue_empty(&mcast->pkt_queue)) {
+			++priv->stats.tx_dropped;
 			dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
+		}
+		spin_unlock_irq(&priv->tx_lock);
 
 		/* Clear the busy flag so we try again */
 		clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
@@ -687,6 +703,7 @@
 		if (!mcast) {
 			ipoib_warn(priv, "unable to allocate memory for "
 				   "multicast structure\n");
+			++priv->stats.tx_dropped;
 			dev_kfree_skb_any(skb);
 			goto out;
 		}
@@ -700,8 +717,10 @@
 	if (!mcast->ah) {
 		if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE)
 			skb_queue_tail(&mcast->pkt_queue, skb);
-		else
+		else {
+			++priv->stats.tx_dropped;
 			dev_kfree_skb_any(skb);
+		}
 
 		if (mcast->query)
 			ipoib_dbg_mcast(priv, "no address vector, "
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 31207e66..2d2d4ac 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -357,9 +357,9 @@
 	target->state = SRP_TARGET_REMOVED;
 	spin_unlock_irq(target->scsi_host->host_lock);
 
-	down(&target->srp_host->target_mutex);
+	mutex_lock(&target->srp_host->target_mutex);
 	list_del(&target->list);
-	up(&target->srp_host->target_mutex);
+	mutex_unlock(&target->srp_host->target_mutex);
 
 	scsi_remove_host(target->scsi_host);
 	ib_destroy_cm_id(target->cm_id);
@@ -1254,9 +1254,9 @@
 	if (scsi_add_host(target->scsi_host, host->dev->dma_device))
 		return -ENODEV;
 
-	down(&host->target_mutex);
+	mutex_lock(&host->target_mutex);
 	list_add_tail(&target->list, &host->target_list);
-	up(&host->target_mutex);
+	mutex_unlock(&host->target_mutex);
 
 	target->state = SRP_TARGET_LIVE;
 
@@ -1525,7 +1525,7 @@
 		return NULL;
 
 	INIT_LIST_HEAD(&host->target_list);
-	init_MUTEX(&host->target_mutex);
+	mutex_init(&host->target_mutex);
 	init_completion(&host->released);
 	host->dev  = device;
 	host->port = port;
@@ -1626,7 +1626,7 @@
 		 * Mark all target ports as removed, so we stop queueing
 		 * commands and don't try to reconnect.
 		 */
-		down(&host->target_mutex);
+		mutex_lock(&host->target_mutex);
 		list_for_each_entry_safe(target, tmp_target,
 					 &host->target_list, list) {
 			spin_lock_irqsave(target->scsi_host->host_lock, flags);
@@ -1634,7 +1634,7 @@
 				target->state = SRP_TARGET_REMOVED;
 			spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
 		}
-		up(&host->target_mutex);
+		mutex_unlock(&host->target_mutex);
 
 		/*
 		 * Wait for any reconnection tasks that may have
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index b564f18..4e7727d 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -37,8 +37,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
@@ -85,7 +84,7 @@
 	struct ib_mr	       *mr;
 	struct class_device	class_dev;
 	struct list_head	target_list;
-	struct semaphore        target_mutex;
+	struct mutex            target_mutex;
 	struct completion	released;
 	struct list_head	list;
 };
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index 4571ea3..4612d13 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -57,7 +57,7 @@
 struct a3d {
 	struct gameport *gameport;
 	struct gameport *adc;
-	struct input_dev dev;
+	struct input_dev *dev;
 	int axes[4];
 	int buttons;
 	int mode;
@@ -115,7 +115,7 @@
 
 static void a3d_read(struct a3d *a3d, unsigned char *data)
 {
-	struct input_dev *dev = &a3d->dev;
+	struct input_dev *dev = a3d->dev;
 
 	switch (a3d->mode) {
 
@@ -265,14 +265,20 @@
 static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct a3d *a3d;
+	struct input_dev *input_dev;
 	struct gameport *adc;
 	unsigned char data[A3D_MAX_LENGTH];
 	int i;
 	int err;
 
-	if (!(a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL)))
-		return -ENOMEM;
+	a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!a3d || !input_dev) {
+		err = -ENOMEM;
+		goto fail1;
+	}
 
+	a3d->dev = input_dev;
 	a3d->gameport = gameport;
 
 	gameport_set_drvdata(gameport, a3d);
@@ -302,42 +308,48 @@
 
 	sprintf(a3d->phys, "%s/input0", gameport->phys);
 
+	input_dev->name = a3d_names[a3d->mode];
+	input_dev->phys = a3d->phys;
+	input_dev->id.bustype = BUS_GAMEPORT;
+	input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
+	input_dev->id.product = a3d->mode;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &gameport->dev;
+	input_dev->private = a3d;
+	input_dev->open = a3d_open;
+	input_dev->close = a3d_close;
+
 	if (a3d->mode == A3D_MODE_PXL) {
 
 		int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
 
 		a3d->length = 33;
 
-		init_input_dev(&a3d->dev);
-
-		a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
-		a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
-		a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
-				   | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
-
-		a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
-						 | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-
-		a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE);
+		input_dev->evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
+		input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y);
+		input_dev->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
+					| BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
+		input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
+							| BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+		input_dev->keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP)
+							| BIT(BTN_PINKIE);
 
 		a3d_read(a3d, data);
 
 		for (i = 0; i < 4; i++) {
 			if (i < 2)
-				input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8);
+				input_set_abs_params(input_dev, axes[i], 48, input_dev->abs[axes[i]] * 2 - 48, 0, 8);
 			else
-				input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0);
-			input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0);
+				input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0);
+			input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
 		}
 
 	} else {
 		a3d->length = 29;
 
-		init_input_dev(&a3d->dev);
-
-		a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
-		a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
-		a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
+		input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
+		input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y);
+		input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
 
 		a3d_read(a3d, data);
 
@@ -358,24 +370,17 @@
 		}
 	}
 
-	a3d->dev.private = a3d;
-	a3d->dev.open = a3d_open;
-	a3d->dev.close = a3d_close;
-
-	a3d->dev.name = a3d_names[a3d->mode];
-	a3d->dev.phys = a3d->phys;
-	a3d->dev.id.bustype = BUS_GAMEPORT;
-	a3d->dev.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
-	a3d->dev.id.product = a3d->mode;
-	a3d->dev.id.version = 0x0100;
-
-	input_register_device(&a3d->dev);
-	printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);
+	err = input_register_device(a3d->dev);
+	if (err)
+		goto fail3;
 
 	return 0;
 
-fail2:	gameport_close(gameport);
-fail1:  gameport_set_drvdata(gameport, NULL);
+ fail3:	if (a3d->adc)
+		gameport_unregister_port(a3d->adc);
+ fail2:	gameport_close(gameport);
+ fail1:	gameport_set_drvdata(gameport, NULL);
+	input_free_device(input_dev);
 	kfree(a3d);
 	return err;
 }
@@ -384,11 +389,9 @@
 {
 	struct a3d *a3d = gameport_get_drvdata(gameport);
 
-	input_unregister_device(&a3d->dev);
-	if (a3d->adc) {
+	input_unregister_device(a3d->dev);
+	if (a3d->adc)
 		gameport_unregister_port(a3d->adc);
-		a3d->adc = NULL;
-	}
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	kfree(a3d);
@@ -397,6 +400,7 @@
 static struct gameport_driver a3d_drv = {
 	.driver		= {
 		.name	= "adc",
+		.owner	= THIS_MODULE,
 	},
 	.description	= DRIVER_DESC,
 	.connect	= a3d_connect,
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 499344c..dcffc34 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -275,68 +275,70 @@
 /*
  * db9_saturn_report() analyzes packet and reports.
  */
-static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *dev, int n, int max_pads)
+static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *devs[], int n, int max_pads)
 {
+	struct input_dev *dev;
 	int tmp, i, j;
 
 	tmp = (id == 0x41) ? 60 : 10;
-	for (j = 0; (j < tmp) && (n < max_pads); j += 10, n++) {
+	for (j = 0; j < tmp && n < max_pads; j += 10, n++) {
+		dev = devs[n];
 		switch (data[j]) {
 		case 0x16: /* multi controller (analog 4 axis) */
-			input_report_abs(dev + n, db9_abs[5], data[j + 6]);
+			input_report_abs(dev, db9_abs[5], data[j + 6]);
 		case 0x15: /* mission stick (analog 3 axis) */
-			input_report_abs(dev + n, db9_abs[3], data[j + 4]);
-			input_report_abs(dev + n, db9_abs[4], data[j + 5]);
+			input_report_abs(dev, db9_abs[3], data[j + 4]);
+			input_report_abs(dev, db9_abs[4], data[j + 5]);
 		case 0x13: /* racing controller (analog 1 axis) */
-			input_report_abs(dev + n, db9_abs[2], data[j + 3]);
+			input_report_abs(dev, db9_abs[2], data[j + 3]);
 		case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
 		case 0x02: /* digital pad (digital 2 axis + buttons) */
-			input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
-			input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
+			input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
+			input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
 			for (i = 0; i < 9; i++)
-				input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
+				input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
 			break;
 		case 0x19: /* mission stick x2 (analog 6 axis + buttons) */
-			input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
-			input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
+			input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
+			input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
 			for (i = 0; i < 9; i++)
-				input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
-			input_report_abs(dev + n, db9_abs[2], data[j + 3]);
-			input_report_abs(dev + n, db9_abs[3], data[j + 4]);
-			input_report_abs(dev + n, db9_abs[4], data[j + 5]);
+				input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
+			input_report_abs(dev, db9_abs[2], data[j + 3]);
+			input_report_abs(dev, db9_abs[3], data[j + 4]);
+			input_report_abs(dev, db9_abs[4], data[j + 5]);
 			/*
-			input_report_abs(dev + n, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
-			input_report_abs(dev + n, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
+			input_report_abs(dev, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
+			input_report_abs(dev, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
 			*/
-			input_report_abs(dev + n, db9_abs[6], data[j + 7]);
-			input_report_abs(dev + n, db9_abs[7], data[j + 8]);
-			input_report_abs(dev + n, db9_abs[5], data[j + 9]);
+			input_report_abs(dev, db9_abs[6], data[j + 7]);
+			input_report_abs(dev, db9_abs[7], data[j + 8]);
+			input_report_abs(dev, db9_abs[5], data[j + 9]);
 			break;
 		case 0xd3: /* sankyo ff (analog 1 axis + stop btn) */
-			input_report_key(dev + n, BTN_A, data[j + 3] & 0x80);
-			input_report_abs(dev + n, db9_abs[2], data[j + 3] & 0x7f);
+			input_report_key(dev, BTN_A, data[j + 3] & 0x80);
+			input_report_abs(dev, db9_abs[2], data[j + 3] & 0x7f);
 			break;
 		case 0xe3: /* shuttle mouse (analog 2 axis + buttons. signed value) */
-			input_report_key(dev + n, BTN_START, data[j + 1] & 0x08);
-			input_report_key(dev + n, BTN_A, data[j + 1] & 0x04);
-			input_report_key(dev + n, BTN_C, data[j + 1] & 0x02);
-			input_report_key(dev + n, BTN_B, data[j + 1] & 0x01);
-			input_report_abs(dev + n, db9_abs[2], data[j + 2] ^ 0x80);
-			input_report_abs(dev + n, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */
+			input_report_key(dev, BTN_START, data[j + 1] & 0x08);
+			input_report_key(dev, BTN_A, data[j + 1] & 0x04);
+			input_report_key(dev, BTN_C, data[j + 1] & 0x02);
+			input_report_key(dev, BTN_B, data[j + 1] & 0x01);
+			input_report_abs(dev, db9_abs[2], data[j + 2] ^ 0x80);
+			input_report_abs(dev, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */
 			break;
 		case 0xff:
 		default: /* no pad */
-			input_report_abs(dev + n, db9_abs[0], 0);
-			input_report_abs(dev + n, db9_abs[1], 0);
+			input_report_abs(dev, db9_abs[0], 0);
+			input_report_abs(dev, db9_abs[1], 0);
 			for (i = 0; i < 9; i++)
-				input_report_key(dev + n, db9_cd32_btn[i], 0);
+				input_report_key(dev, db9_cd32_btn[i], 0);
 			break;
 		}
 	}
 	return n;
 }
 
-static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
+static int db9_saturn(int mode, struct parport *port, struct input_dev *devs[])
 {
 	unsigned char id, data[60];
 	int type, n, max_pads;
@@ -361,7 +363,7 @@
 	max_pads = min(db9_modes[mode].n_pads, DB9_MAX_DEVICES);
 	for (tmp = 0, i = 0; i < n; i++) {
 		id = db9_saturn_read_packet(port, data, type + i, 1);
-		tmp = db9_saturn_report(id, data, dev, tmp, max_pads);
+		tmp = db9_saturn_report(id, data, devs, tmp, max_pads);
 	}
 	return 0;
 }
@@ -489,7 +491,7 @@
 		case DB9_SATURN_DPP:
 		case DB9_SATURN_DPP_2:
 
-			db9_saturn(db9->mode, port, dev);
+			db9_saturn(db9->mode, port, db9->dev);
 			break;
 
 		case DB9_CD32_PAD:
@@ -614,7 +616,7 @@
 		if (!input_dev) {
 			printk(KERN_ERR "db9.c: Not enough memory for input device\n");
 			err = -ENOMEM;
-			goto err_free_devs;
+			goto err_unreg_devs;
 		}
 
 		sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
@@ -640,13 +642,17 @@
 				input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
 		}
 
-		input_register_device(input_dev);
+		err = input_register_device(input_dev);
+		if (err)
+			goto err_free_dev;
 	}
 
 	parport_put_port(pp);
 	return db9;
 
- err_free_devs:
+ err_free_dev:
+	input_free_device(db9->dev[i]);
+ err_unreg_devs:
 	while (--i >= 0)
 		input_unregister_device(db9->dev[i]);
 	kfree(db9);
@@ -658,7 +664,7 @@
 	return ERR_PTR(err);
 }
 
-static void __exit db9_remove(struct db9 *db9)
+static void db9_remove(struct db9 *db9)
 {
 	int i;
 
@@ -696,7 +702,8 @@
 
 	if (err) {
 		while (--i >= 0)
-			db9_remove(db9_base[i]);
+			if (db9_base[i])
+				db9_remove(db9_base[i]);
 		return err;
 	}
 
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 7df2d82..900587a 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -159,6 +159,48 @@
 
 }
 
+static void gc_n64_process_packet(struct gc *gc)
+{
+	unsigned char data[GC_N64_LENGTH];
+	signed char axes[2];
+	struct input_dev *dev;
+	int i, j, s;
+
+	gc_n64_read_packet(gc, data);
+
+	for (i = 0; i < GC_MAX_DEVICES; i++) {
+
+		dev = gc->dev[i];
+		if (!dev)
+			continue;
+
+		s = gc_status_bit[i];
+
+		if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {
+
+			axes[0] = axes[1] = 0;
+
+			for (j = 0; j < 8; j++) {
+				if (data[23 - j] & s)
+					axes[0] |= 1 << j;
+				if (data[31 - j] & s)
+					axes[1] |= 1 << j;
+			}
+
+			input_report_abs(dev, ABS_X,  axes[0]);
+			input_report_abs(dev, ABS_Y, -axes[1]);
+
+			input_report_abs(dev, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
+			input_report_abs(dev, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
+
+			for (j = 0; j < 10; j++)
+				input_report_key(dev, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
+
+			input_sync(dev);
+		}
+	}
+}
+
 /*
  * NES/SNES support.
  */
@@ -198,6 +240,39 @@
 	}
 }
 
+static void gc_nes_process_packet(struct gc *gc)
+{
+	unsigned char data[GC_SNES_LENGTH];
+	struct input_dev *dev;
+	int i, j, s;
+
+	gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
+
+	for (i = 0; i < GC_MAX_DEVICES; i++) {
+
+		dev = gc->dev[i];
+		if (!dev)
+			continue;
+
+		s = gc_status_bit[i];
+
+		if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
+			input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7]));
+			input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5]));
+		}
+
+		if (s & gc->pads[GC_NES])
+			for (j = 0; j < 4; j++)
+				input_report_key(dev, gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
+
+		if (s & gc->pads[GC_SNES])
+			for (j = 0; j < 8; j++)
+				input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
+
+		input_sync(dev);
+	}
+}
+
 /*
  * Multisystem joystick support
  */
@@ -219,6 +294,35 @@
 	}
 }
 
+static void gc_multi_process_packet(struct gc *gc)
+{
+	unsigned char data[GC_MULTI2_LENGTH];
+	struct input_dev *dev;
+	int i, s;
+
+	gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);
+
+	for (i = 0; i < GC_MAX_DEVICES; i++) {
+
+		dev = gc->dev[i];
+		if (!dev)
+			continue;
+
+		s = gc_status_bit[i];
+
+		if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
+			input_report_abs(dev, ABS_X,  !(s & data[2]) - !(s & data[3]));
+			input_report_abs(dev, ABS_Y,  !(s & data[0]) - !(s & data[1]));
+			input_report_key(dev, BTN_TRIGGER, s & data[4]);
+		}
+
+		if (s & gc->pads[GC_MULTI2])
+			input_report_key(dev, BTN_THUMB, s & data[5]);
+
+		input_sync(dev);
+	}
+}
+
 /*
  * PSX support
  *
@@ -263,10 +367,11 @@
  * the psx pad.
  */
 
-static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
+static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_MAX_DEVICES])
 {
 	int i, j, cmd, read;
-	for (i = 0; i < 5; i++)
+
+	for (i = 0; i < GC_MAX_DEVICES; i++)
 		data[i] = 0;
 
 	for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) {
@@ -274,7 +379,7 @@
 		parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
 		udelay(gc_psx_delay);
 		read = parport_read_status(gc->pd->port) ^ 0x80;
-		for (j = 0; j < 5; j++)
+		for (j = 0; j < GC_MAX_DEVICES; j++)
 			data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
 		udelay(gc_psx_delay);
@@ -286,11 +391,12 @@
  * device identifier code.
  */
 
-static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5])
+static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES],
+			       unsigned char id[GC_MAX_DEVICES])
 {
 	int i, j, max_len = 0;
 	unsigned long flags;
-	unsigned char data2[5];
+	unsigned char data2[GC_MAX_DEVICES];
 
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);	/* Select pad */
 	udelay(gc_psx_delay);
@@ -303,7 +409,7 @@
 	gc_psx_command(gc, 0x42, id);							/* Get device ids */
 	gc_psx_command(gc, 0, data2);							/* Dump status */
 
-	for (i =0; i < 5; i++)								/* Find the longest pad */
+	for (i =0; i < GC_MAX_DEVICES; i++)								/* Find the longest pad */
 		if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR]))
 			&& (GC_PSX_LEN(id[i]) > max_len)
 			&& (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES))
@@ -311,7 +417,7 @@
 
 	for (i = 0; i < max_len; i++) {						/* Read in all the data */
 		gc_psx_command(gc, 0, data2);
-		for (j = 0; j < 5; j++)
+		for (j = 0; j < GC_MAX_DEVICES; j++)
 			data[j][i] = data2[j];
 	}
 
@@ -319,185 +425,124 @@
 
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
 
-	for(i = 0; i < 5; i++)								/* Set id's to the real value */
+	for(i = 0; i < GC_MAX_DEVICES; i++)								/* Set id's to the real value */
 		id[i] = GC_PSX_ID(id[i]);
 }
 
-/*
- * gc_timer() reads and analyzes console pads data.
- */
+static void gc_psx_process_packet(struct gc *gc)
+{
+	unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES];
+	unsigned char id[GC_MAX_DEVICES];
+	struct input_dev *dev;
+	int i, j;
 
-#define GC_MAX_LENGTH GC_N64_LENGTH
+	gc_psx_read_packet(gc, data, id);
+
+	for (i = 0; i < GC_MAX_DEVICES; i++) {
+
+		dev = gc->dev[i];
+		if (!dev)
+			continue;
+
+		switch (id[i]) {
+
+			case GC_PSX_RUMBLE:
+
+				input_report_key(dev, BTN_THUMBL, ~data[i][0] & 0x04);
+				input_report_key(dev, BTN_THUMBR, ~data[i][0] & 0x02);
+
+			case GC_PSX_NEGCON:
+			case GC_PSX_ANALOG:
+
+				if (gc->pads[GC_DDR] & gc_status_bit[i]) {
+					for(j = 0; j < 4; j++)
+						input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j));
+				} else {
+					for (j = 0; j < 4; j++)
+						input_report_abs(dev, gc_psx_abs[j + 2], data[i][j + 2]);
+
+					input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128);
+					input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128);
+				}
+
+				for (j = 0; j < 8; j++)
+					input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j));
+
+				input_report_key(dev, BTN_START,  ~data[i][0] & 0x08);
+				input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01);
+
+				input_sync(dev);
+
+				break;
+
+			case GC_PSX_NORMAL:
+				if (gc->pads[GC_DDR] & gc_status_bit[i]) {
+					for(j = 0; j < 4; j++)
+						input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j));
+				} else {
+					input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128);
+					input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128);
+
+					/* for some reason if the extra axes are left unset they drift */
+					/* for (j = 0; j < 4; j++)
+						input_report_abs(dev, gc_psx_abs[j + 2], 128);
+					 * This needs to be debugged properly,
+					 * maybe fuzz processing needs to be done in input_sync()
+					 *				 --vojtech
+					 */
+				}
+
+				for (j = 0; j < 8; j++)
+					input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j));
+
+				input_report_key(dev, BTN_START,  ~data[i][0] & 0x08);
+				input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01);
+
+				input_sync(dev);
+
+				break;
+
+			case 0: /* not a pad, ignore */
+				break;
+		}
+	}
+}
+
+/*
+ * gc_timer() initiates reads of console pads data.
+ */
 
 static void gc_timer(unsigned long private)
 {
 	struct gc *gc = (void *) private;
-	unsigned char data[GC_MAX_LENGTH];
-	unsigned char data_psx[5][GC_PSX_BYTES];
-	int i, j, s;
 
 /*
  * N64 pads - must be read first, any read confuses them for 200 us
  */
 
-	if (gc->pads[GC_N64]) {
-
-		gc_n64_read_packet(gc, data);
-
-		for (i = 0; i < 5; i++) {
-
-			s = gc_status_bit[i];
-
-			if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {
-
-				signed char axes[2];
-				axes[0] = axes[1] = 0;
-
-				for (j = 0; j < 8; j++) {
-					if (data[23 - j] & s) axes[0] |= 1 << j;
-					if (data[31 - j] & s) axes[1] |= 1 << j;
-				}
-
-				input_report_abs(gc->dev[i], ABS_X,  axes[0]);
-				input_report_abs(gc->dev[i], ABS_Y, -axes[1]);
-
-				input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
-				input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
-
-				for (j = 0; j < 10; j++)
-					input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
-
-				input_sync(gc->dev[i]);
-			}
-		}
-	}
+	if (gc->pads[GC_N64])
+		gc_n64_process_packet(gc);
 
 /*
  * NES and SNES pads
  */
 
-	if (gc->pads[GC_NES] || gc->pads[GC_SNES]) {
-
-		gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
-
-		for (i = 0; i < 5; i++) {
-
-			s = gc_status_bit[i];
-
-			if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
-				input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7]));
-				input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5]));
-			}
-
-			if (s & gc->pads[GC_NES])
-				for (j = 0; j < 4; j++)
-					input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
-
-			if (s & gc->pads[GC_SNES])
-				for (j = 0; j < 8; j++)
-					input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
-
-			input_sync(gc->dev[i]);
-		}
-	}
+	if (gc->pads[GC_NES] || gc->pads[GC_SNES])
+		gc_nes_process_packet(gc);
 
 /*
  * Multi and Multi2 joysticks
  */
 
-	if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) {
-
-		gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);
-
-		for (i = 0; i < 5; i++) {
-
-			s = gc_status_bit[i];
-
-			if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
-				input_report_abs(gc->dev[i], ABS_X,  !(s & data[2]) - !(s & data[3]));
-				input_report_abs(gc->dev[i], ABS_Y,  !(s & data[0]) - !(s & data[1]));
-				input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]);
-			}
-
-			if (s & gc->pads[GC_MULTI2])
-				input_report_key(gc->dev[i], BTN_THUMB, s & data[5]);
-
-			input_sync(gc->dev[i]);
-		}
-	}
+	if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2])
+		gc_multi_process_packet(gc);
 
 /*
  * PSX controllers
  */
 
-	if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {
-
-		gc_psx_read_packet(gc, data_psx, data);
-
-		for (i = 0; i < 5; i++) {
-			switch (data[i]) {
-
-				case GC_PSX_RUMBLE:
-
-					input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04);
-					input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02);
-
-				case GC_PSX_NEGCON:
-				case GC_PSX_ANALOG:
-
-					if (gc->pads[GC_DDR] & gc_status_bit[i]) {
-						for(j = 0; j < 4; j++)
-							input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
-					} else {
-						for (j = 0; j < 4; j++)
-							input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]);
-
-						input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
-						input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
-					}
-
-					for (j = 0; j < 8; j++)
-						input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
-
-					input_report_key(gc->dev[i], BTN_START,  ~data_psx[i][0] & 0x08);
-					input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
-
-					input_sync(gc->dev[i]);
-
-					break;
-
-				case GC_PSX_NORMAL:
-					if (gc->pads[GC_DDR] & gc_status_bit[i]) {
-						for(j = 0; j < 4; j++)
-							input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
-					} else {
-						input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
-						input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
-
-						/* for some reason if the extra axes are left unset they drift */
-						/* for (j = 0; j < 4; j++)
-							input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128);
-						 * This needs to be debugged properly,
-						 * maybe fuzz processing needs to be done in input_sync()
-						 *				 --vojtech
-						 */
-					}
-
-					for (j = 0; j < 8; j++)
-						input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
-
-					input_report_key(gc->dev[i], BTN_START,  ~data_psx[i][0] & 0x08);
-					input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
-
-					input_sync(gc->dev[i]);
-
-					break;
-
-				case 0: /* not a pad, ignore */
-					break;
-			}
-		}
-	}
+	if (gc->pads[GC_PSX] || gc->pads[GC_DDR])
+		gc_psx_process_packet(gc);
 
 	mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
 }
@@ -654,16 +699,18 @@
 	gc->timer.data = (long) gc;
 	gc->timer.function = gc_timer;
 
-	for (i = 0; i < n_pads; i++) {
+	for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) {
 		if (!pads[i])
 			continue;
 
 		sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
 		err = gc_setup_pad(gc, i, pads[i]);
 		if (err)
-			goto err_free_devs;
+			goto err_unreg_devs;
 
-		input_register_device(gc->dev[i]);
+		err = input_register_device(gc->dev[i]);
+		if (err)
+			goto err_free_dev;
 	}
 
 	if (!gc->pads[0]) {
@@ -675,9 +722,12 @@
 	parport_put_port(pp);
 	return gc;
 
- err_free_devs:
+ err_free_dev:
+	input_free_device(gc->dev[i]);
+ err_unreg_devs:
 	while (--i >= 0)
-		input_unregister_device(gc->dev[i]);
+		if (gc->dev[i])
+			input_unregister_device(gc->dev[i]);
  err_free_gc:
 	kfree(gc);
  err_unreg_pardev:
@@ -688,7 +738,7 @@
 	return ERR_PTR(err);
 }
 
-static void __exit gc_remove(struct gc *gc)
+static void gc_remove(struct gc *gc)
 {
 	int i;
 
@@ -726,7 +776,8 @@
 
 	if (err) {
 		while (--i >= 0)
-			gc_remove(gc_base[i]);
+			if (gc_base[i])
+				gc_remove(gc_base[i]);
 		return err;
 	}
 
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index a936e7a..20cb98a 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -192,6 +192,9 @@
 	for (i = 0; i < 2; i++) {
 
 		dev = grip->dev[i];
+		if (!dev)
+			continue;
+
 		grip->reads++;
 
 		switch (grip->mode[i]) {
@@ -381,12 +384,15 @@
 			if (t > 0)
 				set_bit(t, input_dev->keybit);
 
-		input_register_device(grip->dev[i]);
+		err = input_register_device(grip->dev[i]);
+		if (err)
+			goto fail4;
 	}
 
 	return 0;
 
- fail3: for (i = 0; i < 2; i++)
+ fail4:	input_free_device(grip->dev[i]);
+ fail3:	while (--i >= 0)
 		if (grip->dev[i])
 			input_unregister_device(grip->dev[i]);
  fail2:	gameport_close(gameport);
@@ -411,6 +417,7 @@
 static struct gameport_driver grip_drv = {
 	.driver		= {
 		.name	= "grip",
+		.owner	= THIS_MODULE,
 	},
 	.description	= DRIVER_DESC,
 	.connect	= grip_connect,
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 64b9c31..b6bc049 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -345,7 +345,7 @@
 	int i;
 
 	input_dev = input_allocate_device();
-	if (input_dev)
+	if (!input_dev)
 		return -ENOMEM;
 
 	init_waitqueue_head(&iforce->wait);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 4a26292..76cb1f8 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -167,9 +167,9 @@
 		iforce->expect_packet = 0;
 		iforce->ecmd = cmd;
 		memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
-		wake_up(&iforce->wait);
 	}
 #endif
+	wake_up(&iforce->wait);
 
 	if (!iforce->type) {
 		being_used--;
@@ -264,7 +264,7 @@
 		wait_event_interruptible_timeout(iforce->wait,
 			iforce->ctrl->status != -EINPROGRESS, HZ);
 
-		if (iforce->ctrl->status != -EINPROGRESS) {
+		if (iforce->ctrl->status) {
 			usb_unlink_urb(iforce->ctrl);
 			return -1;
 		}
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index bc2fce6..fe79d15 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -95,7 +95,6 @@
 		goto exit;
 	}
 
-	wake_up(&iforce->wait);
 	iforce_process_packet(iforce,
 		(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
 
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 78dd163..2b2ec10 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -736,7 +736,7 @@
 		sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
 		sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
 
-		input_dev = input_allocate_device();
+		sw->dev[i] = input_dev = input_allocate_device();
 		if (!input_dev) {
 			err = -ENOMEM;
 			goto fail3;
@@ -771,12 +771,15 @@
 
 		dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);
 
-		input_register_device(sw->dev[i]);
+		err = input_register_device(sw->dev[i]);
+		if (err)
+			goto fail4;
 	}
 
 	return 0;
 
- fail3: while (--i >= 0)
+ fail4:	input_free_device(sw->dev[i]);
+ fail3:	while (--i >= 0)
 		input_unregister_device(sw->dev[i]);
  fail2:	gameport_close(gameport);
  fail1:	gameport_set_drvdata(gameport, NULL);
@@ -801,6 +804,7 @@
 static struct gameport_driver sw_drv = {
 	.driver		= {
 		.name	= "sidewinder",
+		.owner	= THIS_MODULE,
 	},
 	.description	= DRIVER_DESC,
 	.connect	= sw_connect,
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 60e2aac..bb23ed2 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -284,13 +284,13 @@
 	struct tmdc_port *port;
 	struct input_dev *input_dev;
 	int i, j, b = 0;
+	int err;
 
 	tmdc->port[idx] = port = kzalloc(sizeof (struct tmdc_port), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!port || !input_dev) {
-		kfree(port);
-		input_free_device(input_dev);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto fail;
 	}
 
 	port->mode = data[TMDC_BYTE_ID];
@@ -347,9 +347,15 @@
 		b += port->btnc[i];
 	}
 
-	input_register_device(port->dev);
+	err = input_register_device(port->dev);
+	if (err)
+		goto fail;
 
 	return 0;
+
+ fail:	input_free_device(input_dev);
+	kfree(port);
+	return err;
 }
 
 /*
@@ -424,6 +430,7 @@
 static struct gameport_driver tmdc_drv = {
 	.driver		= {
 		.name	= "tmdc",
+		.owner	= THIS_MODULE,
 	},
 	.description	= DRIVER_DESC,
 	.connect	= tmdc_connect,
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 7e97649..b154938 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -204,14 +204,14 @@
 		if (n_buttons[i] > 6) {
 			printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
 			err = -EINVAL;
-			goto err_free_devs;
+			goto err_unreg_devs;
 		}
 
 		tgfx->dev[i] = input_dev = input_allocate_device();
 		if (!input_dev) {
 			printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
 			err = -ENOMEM;
-			goto err_free_devs;
+			goto err_unreg_devs;
 		}
 
 		tgfx->sticks |= (1 << i);
@@ -238,7 +238,9 @@
 		for (j = 0; j < n_buttons[i]; j++)
 			set_bit(tgfx_buttons[j], input_dev->keybit);
 
-		input_register_device(tgfx->dev[i]);
+		err = input_register_device(tgfx->dev[i]);
+		if (err)
+			goto err_free_dev;
 	}
 
         if (!tgfx->sticks) {
@@ -249,9 +251,12 @@
 
 	return tgfx;
 
- err_free_devs:
+ err_free_dev:
+	input_free_device(tgfx->dev[i]);
+ err_unreg_devs:
 	while (--i >= 0)
-		input_unregister_device(tgfx->dev[i]);
+		if (tgfx->dev[i])
+			input_unregister_device(tgfx->dev[i]);
  err_free_tgfx:
 	kfree(tgfx);
  err_unreg_pardev:
@@ -262,7 +267,7 @@
 	return ERR_PTR(err);
 }
 
-static void __exit tgfx_remove(struct tgfx *tgfx)
+static void tgfx_remove(struct tgfx *tgfx)
 {
 	int i;
 
@@ -300,7 +305,8 @@
 
 	if (err) {
 		while (--i >= 0)
-			tgfx_remove(tgfx_base[i]);
+			if (tgfx_base[i])
+				tgfx_remove(tgfx_base[i]);
 		return err;
 	}
 
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index cd3a1e7..7f8b009 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -265,13 +265,13 @@
  * The functions for inserting/removing us as a module.
  */
 
-int __init twidjoy_init(void)
+static int __init twidjoy_init(void)
 {
 	serio_register_driver(&twidjoy_drv);
 	return 0;
 }
 
-void __exit twidjoy_exit(void)
+static void __exit twidjoy_exit(void)
 {
 	serio_unregister_driver(&twidjoy_drv);
 }
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index e08dbe0..4bad588 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -50,6 +50,18 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called wistron_btns.
 
+config INPUT_IXP4XX_BEEPER
+	tristate "IXP4XX Beeper support"
+	depends on ARCH_IXP4XX
+	help
+	  If you say yes here, you can connect a beeper to the
+	  ixp4xx gpio pins. This is used by the LinkSys NSLU2.
+
+	  If unsure, say Y.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ixp4xx-beeper.
+
 config INPUT_UINPUT
 	tristate "User level driver support"
 	help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index ce44cce..184c412 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -11,3 +11,4 @@
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
+obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
new file mode 100644
index 0000000..d448bb5
--- /dev/null
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -0,0 +1,183 @@
+/*
+ * Generic IXP4xx beeper driver
+ *
+ * Copyright (C) 2005 Tower Technologies
+ *
+ * based on nslu2-io.c
+ *  Copyright (C) 2004 Karen Spearel
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("ixp4xx beeper driver");
+MODULE_LICENSE("GPL");
+
+static DEFINE_SPINLOCK(beep_lock);
+
+static void ixp4xx_spkr_control(unsigned int pin, unsigned int count)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&beep_lock, flags);
+
+	 if (count) {
+		gpio_line_config(pin, IXP4XX_GPIO_OUT);
+		gpio_line_set(pin, IXP4XX_GPIO_LOW);
+
+		*IXP4XX_OSRT2 = (count & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;
+	} else {
+		gpio_line_config(pin, IXP4XX_GPIO_IN);
+		gpio_line_set(pin, IXP4XX_GPIO_HIGH);
+
+		*IXP4XX_OSRT2 = 0;
+	}
+
+	spin_unlock_irqrestore(&beep_lock, flags);
+}
+
+static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+	unsigned int pin = (unsigned int) dev->private;
+	unsigned int count = 0;
+
+	if (type != EV_SND)
+		return -1;
+
+	switch (code) {
+		case SND_BELL:
+			if (value)
+				value = 1000;
+		case SND_TONE:
+			break;
+		default:
+			return -1;
+	}
+
+	if (value > 20 && value < 32767)
+#ifndef FREQ
+		count = (ixp4xx_get_board_tick_rate() / (value * 4)) - 1;
+#else
+		count = (FREQ / (value * 4)) - 1;
+#endif
+
+	ixp4xx_spkr_control(pin, count);
+
+	return 0;
+}
+
+static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* clear interrupt */
+	*IXP4XX_OSST = IXP4XX_OSST_TIMER_2_PEND;
+
+	/* flip the beeper output */
+	*IXP4XX_GPIO_GPOUTR ^= (1 << (unsigned int) dev_id);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
+{
+	struct input_dev *input_dev;
+	int err;
+
+	input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
+
+	input_dev->private = (void *) dev->id;
+	input_dev->name = "ixp4xx beeper",
+	input_dev->phys = "ixp4xx/gpio";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor  = 0x001f;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &dev->dev;
+
+	input_dev->evbit[0] = BIT(EV_SND);
+	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+	input_dev->event = ixp4xx_spkr_event;
+
+	err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
+			  SA_INTERRUPT | SA_TIMER, "ixp4xx-beeper", (void *) dev->id);
+	if (err)
+		goto err_free_device;
+
+	err = input_register_device(input_dev);
+	if (err)
+		goto err_free_irq;
+
+	platform_set_drvdata(dev, input_dev);
+
+	return 0;
+
+ err_free_irq:
+	free_irq(IRQ_IXP4XX_TIMER2, dev);
+ err_free_device:
+	input_free_device(input_dev);
+
+	return err;
+}
+
+static int __devexit ixp4xx_spkr_remove(struct platform_device *dev)
+{
+	struct input_dev *input_dev = platform_get_drvdata(dev);
+	unsigned int pin = (unsigned int) input_dev->private;
+
+	input_unregister_device(input_dev);
+	platform_set_drvdata(dev, NULL);
+
+	/* turn the speaker off */
+	disable_irq(IRQ_IXP4XX_TIMER2);
+	ixp4xx_spkr_control(pin, 0);
+
+	free_irq(IRQ_IXP4XX_TIMER2, dev);
+
+	return 0;
+}
+
+static void ixp4xx_spkr_shutdown(struct platform_device *dev)
+{
+	struct input_dev *input_dev = platform_get_drvdata(dev);
+	unsigned int pin = (unsigned int) input_dev->private;
+
+	/* turn off the speaker */
+	disable_irq(IRQ_IXP4XX_TIMER2);
+	ixp4xx_spkr_control(pin, 0);
+}
+
+static struct platform_driver ixp4xx_spkr_platform_driver = {
+	.driver		= {
+		.name	= "ixp4xx-beeper",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ixp4xx_spkr_probe,
+	.remove		= __devexit_p(ixp4xx_spkr_remove),
+	.shutdown	= ixp4xx_spkr_shutdown,
+};
+
+static int __init ixp4xx_spkr_init(void)
+{
+	return platform_driver_register(&ixp4xx_spkr_platform_driver);
+}
+
+static void __exit ixp4xx_spkr_exit(void)
+{
+	platform_driver_unregister(&ixp4xx_spkr_platform_driver);
+}
+
+module_init(ixp4xx_spkr_init);
+module_exit(ixp4xx_spkr_exit);
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 7665fd9..19b1b01 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -403,6 +403,7 @@
 		set_bit(REL_WHEEL, psmouse->dev->relbit);
 
 		psmouse->vendor = "Genius";
+		psmouse->name = "Mouse";
 		psmouse->pktsize = 4;
 	}
 
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 81fd7a9..9abed18 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -356,7 +356,7 @@
 	kfree(mousedev);
 }
 
-static int mixdev_release(void)
+static void mixdev_release(void)
 {
 	struct input_handle *handle;
 
@@ -370,8 +370,6 @@
 				mousedev_free(mousedev);
 		}
 	}
-
-	return 0;
 }
 
 static int mousedev_release(struct inode * inode, struct file * file)
@@ -384,9 +382,8 @@
 
 	if (!--list->mousedev->open) {
 		if (list->mousedev->minor == MOUSEDEV_MIX)
-			return mixdev_release();
-
-		if (!mousedev_mix.open) {
+			mixdev_release();
+		else if (!mousedev_mix.open) {
 			if (list->mousedev->exist)
 				input_close_device(&list->mousedev->handle);
 			else
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index dd8c6a9..b45a45c 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -29,9 +29,6 @@
 #ifdef	CONFIG_ARCH_OMAP
 #include <asm/arch/gpio.h>
 #endif
-
-#else
-#define	set_irq_type(irq,type)	do{}while(0)
 #endif
 
 
@@ -509,14 +506,14 @@
 	ts->msg.complete = ads7846_rx;
 	ts->msg.context = ts;
 
-	if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM,
-				spi->dev.bus_id, ts)) {
+	if (request_irq(spi->irq, ads7846_irq,
+			SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
+			spi->dev.bus_id, ts)) {
 		dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
 		input_unregister_device(&ts->input);
 		kfree(ts);
 		return -EBUSY;
 	}
-	set_irq_type(spi->irq, IRQT_FALLING);
 
 	dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
 
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
index 4844d25..3226830 100644
--- a/drivers/input/touchscreen/mk712.c
+++ b/drivers/input/touchscreen/mk712.c
@@ -154,7 +154,7 @@
 	spin_unlock_irqrestore(&mk712_lock, flags);
 }
 
-int __init mk712_init(void)
+static int __init mk712_init(void)
 {
 	int err;
 
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index 0ef5601..6dfc941 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -351,7 +351,7 @@
 
 config HISAX_AMD7930
 	bool "Am7930 (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && SPARC
+	depends on EXPERIMENTAL && SPARC && BROKEN
 	help
 	  This enables HiSax support for the AMD7930 chips on some SPARCs.
 	  This code is not finished yet.
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 1b85ce1..11fe537 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -216,7 +216,7 @@
 #define GROUP_TEI	127
 #define TEI_SAPI	63
 #define CTRL_SAPI	0
-#define PACKET_NOACK	250
+#define PACKET_NOACK	7
 
 /* Layer2 Flags */
 
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
index 3314a5a..94c9afb 100644
--- a/drivers/isdn/sc/ioctl.c
+++ b/drivers/isdn/sc/ioctl.c
@@ -71,14 +71,14 @@
 		/*
 		 * Get the SRec from user space
 		 */
-		if (copy_from_user(srec, data->dataptr, sizeof(srec))) {
+		if (copy_from_user(srec, data->dataptr, SCIOC_SRECSIZE)) {
 			kfree(rcvmsg);
 			kfree(srec);
 			return -EFAULT;
 		}
 
 		status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc,
-				0, sizeof(srec), srec, rcvmsg, SAR_TIMEOUT);
+				0, SCIOC_SRECSIZE, srec, rcvmsg, SAR_TIMEOUT);
 		kfree(rcvmsg);
 		kfree(srec);
 
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 7d4a0ac..12ad462 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -187,6 +187,14 @@
 	  This driver provides thermal control for the PowerMac9,1
           which is the recent (SMU based) single CPU desktop G5
 
+config WINDFARM_PM112
+	tristate "Support for thermal management on PowerMac11,2"
+	depends on WINDFARM && I2C && PMAC_SMU
+	select I2C_POWERMAC
+	help
+	  This driver provides thermal control for the PowerMac11,2
+	  which are the recent dual and quad G5 machines using the
+	  970MP dual-core processor.
 
 config ANSLCD
 	tristate "Support for ANS LCD display"
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index f4657aa..6081acd 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -35,3 +35,8 @@
 				   windfarm_smu_sensors.o \
 				   windfarm_lm75_sensor.o windfarm_pid.o \
 				   windfarm_cpufreq_clamp.o windfarm_pm91.o
+obj-$(CONFIG_WINDFARM_PM112)	+= windfarm_pm112.o windfarm_smu_sat.o \
+				   windfarm_smu_controls.o \
+				   windfarm_smu_sensors.o \
+				   windfarm_max6690_sensor.o \
+				   windfarm_lm75_sensor.o windfarm_pid.o
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index ed6d317..69596f6 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -140,10 +140,9 @@
 {
 	struct macio_dev * macio_dev;
 	struct of_device * of;
-	char *scratch, *compat;
+	char *scratch, *compat, *compat2;
 	int i = 0;
-	int length = 0;
-	int cplen, seen = 0;
+	int length, cplen, cplen2, seen = 0;
 
 	if (!dev)
 		return -ENODEV;
@@ -153,23 +152,22 @@
 		return -ENODEV;
 
 	of = &macio_dev->ofdev;
-	scratch = buffer;
 
 	/* stuff we want to pass to /sbin/hotplug */
-	envp[i++] = scratch;
-	length += scnprintf (scratch, buffer_size - length, "OF_NAME=%s",
-	                     of->node->name);
-	if ((buffer_size - length <= 0) || (i >= num_envp))
-		return -ENOMEM;
+	envp[i++] = scratch = buffer;
+	length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name);
 	++length;
+	buffer_size -= length;
+	if ((buffer_size <= 0) || (i >= num_envp))
+		return -ENOMEM;
 	scratch += length;
 
 	envp[i++] = scratch;
-	length += scnprintf (scratch, buffer_size - length, "OF_TYPE=%s",
-	                     of->node->type);
-	if ((buffer_size - length <= 0) || (i >= num_envp))
-		return -ENOMEM;
+	length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type);
 	++length;
+	buffer_size -= length;
+	if ((buffer_size <= 0) || (i >= num_envp))
+		return -ENOMEM;
 	scratch += length;
 
         /* Since the compatible field can contain pretty much anything
@@ -177,29 +175,55 @@
          * up using a number of environment variables instead. */
 
 	compat = (char *) get_property(of->node, "compatible", &cplen);
+	compat2 = compat;
+	cplen2= cplen;
 	while (compat && cplen > 0) {
-		int l;
                 envp[i++] = scratch;
-		length += scnprintf (scratch, buffer_size - length,
+		length = scnprintf (scratch, buffer_size,
 		                     "OF_COMPATIBLE_%d=%s", seen, compat);
-		if ((buffer_size - length <= 0) || (i >= num_envp))
+		++length;
+		buffer_size -= length;
+		if ((buffer_size <= 0) || (i >= num_envp))
 			return -ENOMEM;
-		length++;
 		scratch += length;
-		l = strlen (compat) + 1;
-		compat += l;
-		cplen -= l;
+		length = strlen (compat) + 1;
+		compat += length;
+		cplen -= length;
 		seen++;
 	}
 
 	envp[i++] = scratch;
-	length += scnprintf (scratch, buffer_size - length,
-	                     "OF_COMPATIBLE_N=%d", seen);
-	if ((buffer_size - length <= 0) || (i >= num_envp))
-		return -ENOMEM;
+	length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen);
 	++length;
+	buffer_size -= length;
+	if ((buffer_size <= 0) || (i >= num_envp))
+		return -ENOMEM;
 	scratch += length;
 
+	envp[i++] = scratch;
+	length = scnprintf (scratch, buffer_size, "MODALIAS=of:N%sT%s",
+			of->node->name, of->node->type);
+	/* overwrite '\0' */
+	buffer_size -= length;
+	if ((buffer_size <= 0) || (i >= num_envp))
+		return -ENOMEM;
+	scratch += length;
+
+	if (!compat2) {
+		compat2 = "";
+		cplen2 = 1;
+	}
+	while (cplen2 > 0) {
+		length = snprintf (scratch, buffer_size, "C%s", compat2);
+		buffer_size -= length;
+		if (buffer_size <= 0)
+			return -ENOMEM;
+		scratch += length;
+		length = strlen (compat2) + 1;
+		compat2 += length;
+		cplen2 -= length;
+	}
+
 	envp[i] = NULL;
 
 	return 0;
diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h
index 3f0cb03..7a2482c 100644
--- a/drivers/macintosh/windfarm.h
+++ b/drivers/macintosh/windfarm.h
@@ -14,6 +14,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/notifier.h>
+#include <linux/device.h>
 
 /* Display a 16.16 fixed point value */
 #define FIX32TOPRINT(f)	((f) >> 16),((((f) & 0xffff) * 1000) >> 16)
@@ -39,6 +40,7 @@
 	char			*name;
 	int			type;
 	struct kref		ref;
+	struct device_attribute	attr;
 };
 
 #define WF_CONTROL_TYPE_GENERIC		0
@@ -87,6 +89,7 @@
 	struct wf_sensor_ops	*ops;
 	char			*name;
 	struct kref		ref;
+	struct device_attribute	attr;
 };
 
 /* Same lifetime rules as controls */
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 6c2a471..bb8d5ef 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -33,6 +33,7 @@
 #include <linux/reboot.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/mutex.h>
 
 #include "windfarm.h"
 
@@ -48,13 +49,17 @@
 
 static LIST_HEAD(wf_controls);
 static LIST_HEAD(wf_sensors);
-static DECLARE_MUTEX(wf_lock);
+static DEFINE_MUTEX(wf_lock);
 static struct notifier_block *wf_client_list;
 static int wf_client_count;
 static unsigned int wf_overtemp;
 static unsigned int wf_overtemp_counter;
 struct task_struct *wf_thread;
 
+static struct platform_device wf_platform_device = {
+	.name	= "windfarm",
+};
+
 /*
  * Utilities & tick thread
  */
@@ -156,26 +161,67 @@
 		kfree(ct);
 }
 
+static ssize_t wf_show_control(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
+	s32 val = 0;
+	int err;
+
+	err = ctrl->ops->get_value(ctrl, &val);
+	if (err < 0)
+		return err;
+	return sprintf(buf, "%d\n", val);
+}
+
+/* This is really only for debugging... */
+static ssize_t wf_store_control(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
+	int val;
+	int err;
+	char *endp;
+
+	val = simple_strtoul(buf, &endp, 0);
+	while (endp < buf + count && (*endp == ' ' || *endp == '\n'))
+		++endp;
+	if (endp - buf < count)
+		return -EINVAL;
+	err = ctrl->ops->set_value(ctrl, val);
+	if (err < 0)
+		return err;
+	return count;
+}
+
 int wf_register_control(struct wf_control *new_ct)
 {
 	struct wf_control *ct;
 
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	list_for_each_entry(ct, &wf_controls, link) {
 		if (!strcmp(ct->name, new_ct->name)) {
 			printk(KERN_WARNING "windfarm: trying to register"
 			       " duplicate control %s\n", ct->name);
-			up(&wf_lock);
+			mutex_unlock(&wf_lock);
 			return -EEXIST;
 		}
 	}
 	kref_init(&new_ct->ref);
 	list_add(&new_ct->link, &wf_controls);
 
+	new_ct->attr.attr.name = new_ct->name;
+	new_ct->attr.attr.owner = THIS_MODULE;
+	new_ct->attr.attr.mode = 0644;
+	new_ct->attr.show = wf_show_control;
+	new_ct->attr.store = wf_store_control;
+	device_create_file(&wf_platform_device.dev, &new_ct->attr);
+
 	DBG("wf: Registered control %s\n", new_ct->name);
 
 	wf_notify(WF_EVENT_NEW_CONTROL, new_ct);
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 
 	return 0;
 }
@@ -183,9 +229,9 @@
 
 void wf_unregister_control(struct wf_control *ct)
 {
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	list_del(&ct->link);
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 
 	DBG("wf: Unregistered control %s\n", ct->name);
 
@@ -197,16 +243,16 @@
 {
 	struct wf_control *ct;
 
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	list_for_each_entry(ct, &wf_controls, link) {
 		if (!strcmp(ct->name, name)) {
 			if (wf_get_control(ct))
 				ct = NULL;
-			up(&wf_lock);
+			mutex_unlock(&wf_lock);
 			return ct;
 		}
 	}
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(wf_find_control);
@@ -246,26 +292,46 @@
 		kfree(sr);
 }
 
+static ssize_t wf_show_sensor(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct wf_sensor *sens = container_of(attr, struct wf_sensor, attr);
+	s32 val = 0;
+	int err;
+
+	err = sens->ops->get_value(sens, &val);
+	if (err < 0)
+		return err;
+	return sprintf(buf, "%d.%03d\n", FIX32TOPRINT(val));
+}
+
 int wf_register_sensor(struct wf_sensor *new_sr)
 {
 	struct wf_sensor *sr;
 
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	list_for_each_entry(sr, &wf_sensors, link) {
 		if (!strcmp(sr->name, new_sr->name)) {
 			printk(KERN_WARNING "windfarm: trying to register"
 			       " duplicate sensor %s\n", sr->name);
-			up(&wf_lock);
+			mutex_unlock(&wf_lock);
 			return -EEXIST;
 		}
 	}
 	kref_init(&new_sr->ref);
 	list_add(&new_sr->link, &wf_sensors);
 
+	new_sr->attr.attr.name = new_sr->name;
+	new_sr->attr.attr.owner = THIS_MODULE;
+	new_sr->attr.attr.mode = 0444;
+	new_sr->attr.show = wf_show_sensor;
+	new_sr->attr.store = NULL;
+	device_create_file(&wf_platform_device.dev, &new_sr->attr);
+
 	DBG("wf: Registered sensor %s\n", new_sr->name);
 
 	wf_notify(WF_EVENT_NEW_SENSOR, new_sr);
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 
 	return 0;
 }
@@ -273,9 +339,9 @@
 
 void wf_unregister_sensor(struct wf_sensor *sr)
 {
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	list_del(&sr->link);
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 
 	DBG("wf: Unregistered sensor %s\n", sr->name);
 
@@ -287,16 +353,16 @@
 {
 	struct wf_sensor *sr;
 
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	list_for_each_entry(sr, &wf_sensors, link) {
 		if (!strcmp(sr->name, name)) {
 			if (wf_get_sensor(sr))
 				sr = NULL;
-			up(&wf_lock);
+			mutex_unlock(&wf_lock);
 			return sr;
 		}
 	}
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(wf_find_sensor);
@@ -329,7 +395,7 @@
 	struct wf_control *ct;
 	struct wf_sensor *sr;
 
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	rc = notifier_chain_register(&wf_client_list, nb);
 	if (rc != 0)
 		goto bail;
@@ -341,19 +407,19 @@
 	if (wf_client_count == 1)
 		wf_start_thread();
  bail:
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(wf_register_client);
 
 int wf_unregister_client(struct notifier_block *nb)
 {
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	notifier_chain_unregister(&wf_client_list, nb);
 	wf_client_count++;
 	if (wf_client_count == 0)
 		wf_stop_thread();
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 
 	return 0;
 }
@@ -361,23 +427,23 @@
 
 void wf_set_overtemp(void)
 {
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	wf_overtemp++;
 	if (wf_overtemp == 1) {
 		printk(KERN_WARNING "windfarm: Overtemp condition detected !\n");
 		wf_overtemp_counter = 0;
 		wf_notify(WF_EVENT_OVERTEMP, NULL);
 	}
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 }
 EXPORT_SYMBOL_GPL(wf_set_overtemp);
 
 void wf_clear_overtemp(void)
 {
-	down(&wf_lock);
+	mutex_lock(&wf_lock);
 	WARN_ON(wf_overtemp == 0);
 	if (wf_overtemp == 0) {
-		up(&wf_lock);
+		mutex_unlock(&wf_lock);
 		return;
 	}
 	wf_overtemp--;
@@ -385,7 +451,7 @@
 		printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n");
 		wf_notify(WF_EVENT_NORMALTEMP, NULL);
 	}
-	up(&wf_lock);
+	mutex_unlock(&wf_lock);
 }
 EXPORT_SYMBOL_GPL(wf_clear_overtemp);
 
@@ -395,10 +461,6 @@
 }
 EXPORT_SYMBOL_GPL(wf_is_overtemp);
 
-static struct platform_device wf_platform_device = {
-	.name	= "windfarm",
-};
-
 static int __init windfarm_core_init(void)
 {
 	DBG("wf: core loaded\n");
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
new file mode 100644
index 0000000..5b9ad6c
--- /dev/null
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -0,0 +1,169 @@
+/*
+ * Windfarm PowerMac thermal control.  MAX6690 sensor.
+ *
+ * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ *
+ * Use and redistribute under the terms of the GNU GPL v2.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/prom.h>
+#include <asm/pmac_low_i2c.h>
+
+#include "windfarm.h"
+
+#define VERSION "0.1"
+
+/* This currently only exports the external temperature sensor,
+   since that's all the control loops need. */
+
+/* Some MAX6690 register numbers */
+#define MAX6690_INTERNAL_TEMP	0
+#define MAX6690_EXTERNAL_TEMP	1
+
+struct wf_6690_sensor {
+	struct i2c_client	i2c;
+	struct wf_sensor	sens;
+};
+
+#define wf_to_6690(x)	container_of((x), struct wf_6690_sensor, sens)
+#define i2c_to_6690(x)	container_of((x), struct wf_6690_sensor, i2c)
+
+static int wf_max6690_attach(struct i2c_adapter *adapter);
+static int wf_max6690_detach(struct i2c_client *client);
+
+static struct i2c_driver wf_max6690_driver = {
+	.driver = {
+		.name		= "wf_max6690",
+	},
+	.attach_adapter	= wf_max6690_attach,
+	.detach_client	= wf_max6690_detach,
+};
+
+static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
+{
+	struct wf_6690_sensor *max = wf_to_6690(sr);
+	s32 data;
+
+	if (max->i2c.adapter == NULL)
+		return -ENODEV;
+
+	/* chip gets initialized by firmware */
+	data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP);
+	if (data < 0)
+		return data;
+	*value = data << 16;
+	return 0;
+}
+
+static void wf_max6690_release(struct wf_sensor *sr)
+{
+	struct wf_6690_sensor *max = wf_to_6690(sr);
+
+	if (max->i2c.adapter) {
+		i2c_detach_client(&max->i2c);
+		max->i2c.adapter = NULL;
+	}
+	kfree(max);
+}
+
+static struct wf_sensor_ops wf_max6690_ops = {
+	.get_value	= wf_max6690_get,
+	.release	= wf_max6690_release,
+	.owner		= THIS_MODULE,
+};
+
+static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
+{
+	struct wf_6690_sensor *max;
+	char *name = "u4-temp";
+
+	max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
+	if (max == NULL) {
+		printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
+		       "no memory\n", name);
+		return;
+	}
+
+	max->sens.ops = &wf_max6690_ops;
+	max->sens.name = name;
+	max->i2c.addr = addr >> 1;
+	max->i2c.adapter = adapter;
+	max->i2c.driver = &wf_max6690_driver;
+	strncpy(max->i2c.name, name, I2C_NAME_SIZE-1);
+
+	if (i2c_attach_client(&max->i2c)) {
+		printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
+		goto fail;
+	}
+
+	if (wf_register_sensor(&max->sens)) {
+		i2c_detach_client(&max->i2c);
+		goto fail;
+	}
+
+	return;
+
+ fail:
+	kfree(max);
+}
+
+static int wf_max6690_attach(struct i2c_adapter *adapter)
+{
+	struct device_node *busnode, *dev = NULL;
+	struct pmac_i2c_bus *bus;
+	const char *loc;
+	u32 *reg;
+
+	bus = pmac_i2c_adapter_to_bus(adapter);
+	if (bus == NULL)
+		return -ENODEV;
+	busnode = pmac_i2c_get_bus_node(bus);
+
+	while ((dev = of_get_next_child(busnode, dev)) != NULL) {
+		if (!device_is_compatible(dev, "max6690"))
+			continue;
+		loc = get_property(dev, "hwsensor-location", NULL);
+		reg = (u32 *) get_property(dev, "reg", NULL);
+		if (!loc || !reg)
+			continue;
+		printk("found max6690, loc=%s reg=%x\n", loc, *reg);
+		if (strcmp(loc, "BACKSIDE"))
+			continue;
+		wf_max6690_create(adapter, *reg);
+	}
+
+	return 0;
+}
+
+static int wf_max6690_detach(struct i2c_client *client)
+{
+	struct wf_6690_sensor *max = i2c_to_6690(client);
+
+	max->i2c.adapter = NULL;
+	wf_unregister_sensor(&max->sens);
+
+	return 0;
+}
+
+static int __init wf_max6690_sensor_init(void)
+{
+	return i2c_add_driver(&wf_max6690_driver);
+}
+
+static void __exit wf_max6690_sensor_exit(void)
+{
+	i2c_del_driver(&wf_max6690_driver);
+}
+
+module_init(wf_max6690_sensor_init);
+module_exit(wf_max6690_sensor_exit);
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_pid.c b/drivers/macintosh/windfarm_pid.c
index 2e803b3..0842432 100644
--- a/drivers/macintosh/windfarm_pid.c
+++ b/drivers/macintosh/windfarm_pid.c
@@ -88,8 +88,8 @@
 
 s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
 {
-	s64	error, integ, deriv, prop;
-	s32	target, sval, adj;
+	s64	integ, deriv, prop;
+	s32	error, target, sval, adj;
 	int	i, hlen = st->param.history_len;
 
 	/* Calculate error term */
@@ -117,7 +117,7 @@
 		integ += st->errors[(st->index + hlen - i) % hlen];
 	integ *= st->param.interval;
 	integ *= st->param.gr;
-	sval = st->param.tmax - ((integ >> 20) & 0xffffffff);
+	sval = st->param.tmax - (s32)(integ >> 20);
 	adj = min(st->param.ttarget, sval);
 
 	DBG("integ: %lx, sval: %lx, adj: %lx\n", integ, sval, adj);
@@ -129,7 +129,7 @@
 	deriv *= st->param.gd;
 
 	/* Calculate proportional term */
-	prop = (new_temp - adj);
+	prop = st->last_delta = (new_temp - adj);
 	prop *= st->param.gp;
 
 	DBG("deriv: %lx, prop: %lx\n", deriv, prop);
diff --git a/drivers/macintosh/windfarm_pid.h b/drivers/macintosh/windfarm_pid.h
index a364c2a..bbccc22 100644
--- a/drivers/macintosh/windfarm_pid.h
+++ b/drivers/macintosh/windfarm_pid.h
@@ -72,6 +72,7 @@
 	int	index; 				/* index of current power */
 	int	tindex; 			/* index of current temp */
 	s32	target;				/* current target value */
+	s32	last_delta;			/* last Tactual - Ttarget */
 	s32	powers[WF_PID_MAX_HISTORY];	/* power history buffer */
 	s32	errors[WF_PID_MAX_HISTORY];	/* error history buffer */
 	s32	temps[2];			/* temp. history buffer */
diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c
new file mode 100644
index 0000000..c2a4e68
--- /dev/null
+++ b/drivers/macintosh/windfarm_pm112.c
@@ -0,0 +1,698 @@
+/*
+ * Windfarm PowerMac thermal control.
+ * Control loops for machines with SMU and PPC970MP processors.
+ *
+ * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Use and redistribute under the terms of the GNU GPL v2.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <asm/prom.h>
+#include <asm/smu.h>
+
+#include "windfarm.h"
+#include "windfarm_pid.h"
+
+#define VERSION "0.2"
+
+#define DEBUG
+#undef LOTSA_DEBUG
+
+#ifdef DEBUG
+#define DBG(args...)	printk(args)
+#else
+#define DBG(args...)	do { } while(0)
+#endif
+
+#ifdef LOTSA_DEBUG
+#define DBG_LOTS(args...)	printk(args)
+#else
+#define DBG_LOTS(args...)	do { } while(0)
+#endif
+
+/* define this to force CPU overtemp to 60 degree, useful for testing
+ * the overtemp code
+ */
+#undef HACKED_OVERTEMP
+
+/* We currently only handle 2 chips, 4 cores... */
+#define NR_CHIPS	2
+#define NR_CORES	4
+#define NR_CPU_FANS	3 * NR_CHIPS
+
+/* Controls and sensors */
+static struct wf_sensor *sens_cpu_temp[NR_CORES];
+static struct wf_sensor *sens_cpu_power[NR_CORES];
+static struct wf_sensor *hd_temp;
+static struct wf_sensor *slots_power;
+static struct wf_sensor *u4_temp;
+
+static struct wf_control *cpu_fans[NR_CPU_FANS];
+static char *cpu_fan_names[NR_CPU_FANS] = {
+	"cpu-rear-fan-0",
+	"cpu-rear-fan-1",
+	"cpu-front-fan-0",
+	"cpu-front-fan-1",
+	"cpu-pump-0",
+	"cpu-pump-1",
+};
+static struct wf_control *cpufreq_clamp;
+
+/* Second pump isn't required (and isn't actually present) */
+#define CPU_FANS_REQD		(NR_CPU_FANS - 2)
+#define FIRST_PUMP		4
+#define LAST_PUMP		5
+
+/* We keep a temperature history for average calculation of 180s */
+#define CPU_TEMP_HIST_SIZE	180
+
+/* Scale factor for fan speed, *100 */
+static int cpu_fan_scale[NR_CPU_FANS] = {
+	100,
+	100,
+	97,		/* inlet fans run at 97% of exhaust fan */
+	97,
+	100,		/* updated later */
+	100,		/* updated later */
+};
+
+static struct wf_control *backside_fan;
+static struct wf_control *slots_fan;
+static struct wf_control *drive_bay_fan;
+
+/* PID loop state */
+static struct wf_cpu_pid_state cpu_pid[NR_CORES];
+static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
+static int cpu_thist_pt;
+static s64 cpu_thist_total;
+static s32 cpu_all_tmax = 100 << 16;
+static int cpu_last_target;
+static struct wf_pid_state backside_pid;
+static int backside_tick;
+static struct wf_pid_state slots_pid;
+static int slots_started;
+static struct wf_pid_state drive_bay_pid;
+static int drive_bay_tick;
+
+static int nr_cores;
+static int have_all_controls;
+static int have_all_sensors;
+static int started;
+
+static int failure_state;
+#define FAILURE_SENSOR		1
+#define FAILURE_FAN		2
+#define FAILURE_PERM		4
+#define FAILURE_LOW_OVERTEMP	8
+#define FAILURE_HIGH_OVERTEMP	16
+
+/* Overtemp values */
+#define LOW_OVER_AVERAGE	0
+#define LOW_OVER_IMMEDIATE	(10 << 16)
+#define LOW_OVER_CLEAR		((-10) << 16)
+#define HIGH_OVER_IMMEDIATE	(14 << 16)
+#define HIGH_OVER_AVERAGE	(10 << 16)
+#define HIGH_OVER_IMMEDIATE	(14 << 16)
+
+
+/* Implementation... */
+static int create_cpu_loop(int cpu)
+{
+	int chip = cpu / 2;
+	int core = cpu & 1;
+	struct smu_sdbp_header *hdr;
+	struct smu_sdbp_cpupiddata *piddata;
+	struct wf_cpu_pid_param pid;
+	struct wf_control *main_fan = cpu_fans[0];
+	s32 tmax;
+	int fmin;
+
+	/* Get PID params from the appropriate SAT */
+	hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL);
+	if (hdr == NULL) {
+		printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n");
+		return -EINVAL;
+	}
+	piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
+
+	/* Get FVT params to get Tmax; if not found, assume default */
+	hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL);
+	if (hdr) {
+		struct smu_sdbp_fvt *fvt = (struct smu_sdbp_fvt *)&hdr[1];
+		tmax = fvt->maxtemp << 16;
+	} else
+		tmax = 95 << 16;	/* default to 95 degrees C */
+
+	/* We keep a global tmax for overtemp calculations */
+	if (tmax < cpu_all_tmax)
+		cpu_all_tmax = tmax;
+
+	/*
+	 * Darwin has a minimum fan speed of 1000 rpm for the 4-way and
+	 * 515 for the 2-way.  That appears to be overkill, so for now,
+	 * impose a minimum of 750 or 515.
+	 */
+	fmin = (nr_cores > 2) ? 750 : 515;
+
+	/* Initialize PID loop */
+	pid.interval = 1;	/* seconds */
+	pid.history_len = piddata->history_len;
+	pid.gd = piddata->gd;
+	pid.gp = piddata->gp;
+	pid.gr = piddata->gr / piddata->history_len;
+	pid.pmaxadj = (piddata->max_power << 16) - (piddata->power_adj << 8);
+	pid.ttarget = tmax - (piddata->target_temp_delta << 16);
+	pid.tmax = tmax;
+	pid.min = main_fan->ops->get_min(main_fan);
+	pid.max = main_fan->ops->get_max(main_fan);
+	if (pid.min < fmin)
+		pid.min = fmin;
+
+	wf_cpu_pid_init(&cpu_pid[cpu], &pid);
+	return 0;
+}
+
+static void cpu_max_all_fans(void)
+{
+	int i;
+
+	/* We max all CPU fans in case of a sensor error. We also do the
+	 * cpufreq clamping now, even if it's supposedly done later by the
+	 * generic code anyway, we do it earlier here to react faster
+	 */
+	if (cpufreq_clamp)
+		wf_control_set_max(cpufreq_clamp);
+	for (i = 0; i < NR_CPU_FANS; ++i)
+		if (cpu_fans[i])
+			wf_control_set_max(cpu_fans[i]);
+}
+
+static int cpu_check_overtemp(s32 temp)
+{
+	int new_state = 0;
+	s32 t_avg, t_old;
+
+	/* First check for immediate overtemps */
+	if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
+		new_state |= FAILURE_LOW_OVERTEMP;
+		if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+			printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
+			       " temperature !\n");
+	}
+	if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
+		new_state |= FAILURE_HIGH_OVERTEMP;
+		if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+			printk(KERN_ERR "windfarm: Critical overtemp due to"
+			       " immediate CPU temperature !\n");
+	}
+
+	/* We calculate a history of max temperatures and use that for the
+	 * overtemp management
+	 */
+	t_old = cpu_thist[cpu_thist_pt];
+	cpu_thist[cpu_thist_pt] = temp;
+	cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
+	cpu_thist_total -= t_old;
+	cpu_thist_total += temp;
+	t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
+
+	DBG_LOTS("t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
+		 FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
+
+	/* Now check for average overtemps */
+	if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
+		new_state |= FAILURE_LOW_OVERTEMP;
+		if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+			printk(KERN_ERR "windfarm: Overtemp due to average CPU"
+			       " temperature !\n");
+	}
+	if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
+		new_state |= FAILURE_HIGH_OVERTEMP;
+		if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+			printk(KERN_ERR "windfarm: Critical overtemp due to"
+			       " average CPU temperature !\n");
+	}
+
+	/* Now handle overtemp conditions. We don't currently use the windfarm
+	 * overtemp handling core as it's not fully suited to the needs of those
+	 * new machine. This will be fixed later.
+	 */
+	if (new_state) {
+		/* High overtemp -> immediate shutdown */
+		if (new_state & FAILURE_HIGH_OVERTEMP)
+			machine_power_off();
+		if ((failure_state & new_state) != new_state)
+			cpu_max_all_fans();
+		failure_state |= new_state;
+	} else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
+		   (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
+		printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
+		failure_state &= ~FAILURE_LOW_OVERTEMP;
+	}
+
+	return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
+}
+
+static void cpu_fans_tick(void)
+{
+	int err, cpu;
+	s32 greatest_delta = 0;
+	s32 temp, power, t_max = 0;
+	int i, t, target = 0;
+	struct wf_sensor *sr;
+	struct wf_control *ct;
+	struct wf_cpu_pid_state *sp;
+
+	DBG_LOTS(KERN_DEBUG);
+	for (cpu = 0; cpu < nr_cores; ++cpu) {
+		/* Get CPU core temperature */
+		sr = sens_cpu_temp[cpu];
+		err = sr->ops->get_value(sr, &temp);
+		if (err) {
+			DBG("\n");
+			printk(KERN_WARNING "windfarm: CPU %d temperature "
+			       "sensor error %d\n", cpu, err);
+			failure_state |= FAILURE_SENSOR;
+			cpu_max_all_fans();
+			return;
+		}
+
+		/* Keep track of highest temp */
+		t_max = max(t_max, temp);
+
+		/* Get CPU power */
+		sr = sens_cpu_power[cpu];
+		err = sr->ops->get_value(sr, &power);
+		if (err) {
+			DBG("\n");
+			printk(KERN_WARNING "windfarm: CPU %d power "
+			       "sensor error %d\n", cpu, err);
+			failure_state |= FAILURE_SENSOR;
+			cpu_max_all_fans();
+			return;
+		}
+
+		/* Run PID */
+		sp = &cpu_pid[cpu];
+		t = wf_cpu_pid_run(sp, power, temp);
+
+		if (cpu == 0 || sp->last_delta > greatest_delta) {
+			greatest_delta = sp->last_delta;
+			target = t;
+		}
+		DBG_LOTS("[%d] P=%d.%.3d T=%d.%.3d ",
+		    cpu, FIX32TOPRINT(power), FIX32TOPRINT(temp));
+	}
+	DBG_LOTS("fans = %d, t_max = %d.%03d\n", target, FIX32TOPRINT(t_max));
+
+	/* Darwin limits decrease to 20 per iteration */
+	if (target < (cpu_last_target - 20))
+		target = cpu_last_target - 20;
+	cpu_last_target = target;
+	for (cpu = 0; cpu < nr_cores; ++cpu)
+		cpu_pid[cpu].target = target;
+
+	/* Handle possible overtemps */
+	if (cpu_check_overtemp(t_max))
+		return;
+
+	/* Set fans */
+	for (i = 0; i < NR_CPU_FANS; ++i) {
+		ct = cpu_fans[i];
+		if (ct == NULL)
+			continue;
+		err = ct->ops->set_value(ct, target * cpu_fan_scale[i] / 100);
+		if (err) {
+			printk(KERN_WARNING "windfarm: fan %s reports "
+			       "error %d\n", ct->name, err);
+			failure_state |= FAILURE_FAN;
+			break;
+		}
+	}
+}
+
+/* Backside/U4 fan */
+static struct wf_pid_param backside_param = {
+	.interval	= 5,
+	.history_len	= 2,
+	.gd		= 48 << 20,
+	.gp		= 5 << 20,
+	.gr		= 0,
+	.itarget	= 64 << 16,
+	.additive	= 1,
+};
+
+static void backside_fan_tick(void)
+{
+	s32 temp;
+	int speed;
+	int err;
+
+	if (!backside_fan || !u4_temp)
+		return;
+	if (!backside_tick) {
+		/* first time; initialize things */
+		backside_param.min = backside_fan->ops->get_min(backside_fan);
+		backside_param.max = backside_fan->ops->get_max(backside_fan);
+		wf_pid_init(&backside_pid, &backside_param);
+		backside_tick = 1;
+	}
+	if (--backside_tick > 0)
+		return;
+	backside_tick = backside_pid.param.interval;
+
+	err = u4_temp->ops->get_value(u4_temp, &temp);
+	if (err) {
+		printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n",
+		       err);
+		failure_state |= FAILURE_SENSOR;
+		wf_control_set_max(backside_fan);
+		return;
+	}
+	speed = wf_pid_run(&backside_pid, temp);
+	DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
+		 FIX32TOPRINT(temp), speed);
+
+	err = backside_fan->ops->set_value(backside_fan, speed);
+	if (err) {
+		printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
+		failure_state |= FAILURE_FAN;
+	}
+}
+
+/* Drive bay fan */
+static struct wf_pid_param drive_bay_prm = {
+	.interval	= 5,
+	.history_len	= 2,
+	.gd		= 30 << 20,
+	.gp		= 5 << 20,
+	.gr		= 0,
+	.itarget	= 40 << 16,
+	.additive	= 1,
+};
+
+static void drive_bay_fan_tick(void)
+{
+	s32 temp;
+	int speed;
+	int err;
+
+	if (!drive_bay_fan || !hd_temp)
+		return;
+	if (!drive_bay_tick) {
+		/* first time; initialize things */
+		drive_bay_prm.min = drive_bay_fan->ops->get_min(drive_bay_fan);
+		drive_bay_prm.max = drive_bay_fan->ops->get_max(drive_bay_fan);
+		wf_pid_init(&drive_bay_pid, &drive_bay_prm);
+		drive_bay_tick = 1;
+	}
+	if (--drive_bay_tick > 0)
+		return;
+	drive_bay_tick = drive_bay_pid.param.interval;
+
+	err = hd_temp->ops->get_value(hd_temp, &temp);
+	if (err) {
+		printk(KERN_WARNING "windfarm: drive bay temp sensor "
+		       "error %d\n", err);
+		failure_state |= FAILURE_SENSOR;
+		wf_control_set_max(drive_bay_fan);
+		return;
+	}
+	speed = wf_pid_run(&drive_bay_pid, temp);
+	DBG_LOTS("drive_bay PID temp=%d.%.3d speed=%d\n",
+		 FIX32TOPRINT(temp), speed);
+
+	err = drive_bay_fan->ops->set_value(drive_bay_fan, speed);
+	if (err) {
+		printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err);
+		failure_state |= FAILURE_FAN;
+	}
+}
+
+/* PCI slots area fan */
+/* This makes the fan speed proportional to the power consumed */
+static struct wf_pid_param slots_param = {
+	.interval	= 1,
+	.history_len	= 2,
+	.gd		= 0,
+	.gp		= 0,
+	.gr		= 0x1277952,
+	.itarget	= 0,
+	.min		= 1560,
+	.max		= 3510,
+};
+
+static void slots_fan_tick(void)
+{
+	s32 power;
+	int speed;
+	int err;
+
+	if (!slots_fan || !slots_power)
+		return;
+	if (!slots_started) {
+		/* first time; initialize things */
+		wf_pid_init(&slots_pid, &slots_param);
+		slots_started = 1;
+	}
+
+	err = slots_power->ops->get_value(slots_power, &power);
+	if (err) {
+		printk(KERN_WARNING "windfarm: slots power sensor error %d\n",
+		       err);
+		failure_state |= FAILURE_SENSOR;
+		wf_control_set_max(slots_fan);
+		return;
+	}
+	speed = wf_pid_run(&slots_pid, power);
+	DBG_LOTS("slots PID power=%d.%.3d speed=%d\n",
+		 FIX32TOPRINT(power), speed);
+
+	err = slots_fan->ops->set_value(slots_fan, speed);
+	if (err) {
+		printk(KERN_WARNING "windfarm: slots fan error %d\n", err);
+		failure_state |= FAILURE_FAN;
+	}
+}
+
+static void set_fail_state(void)
+{
+	int i;
+
+	if (cpufreq_clamp)
+		wf_control_set_max(cpufreq_clamp);
+	for (i = 0; i < NR_CPU_FANS; ++i)
+		if (cpu_fans[i])
+			wf_control_set_max(cpu_fans[i]);
+	if (backside_fan)
+		wf_control_set_max(backside_fan);
+	if (slots_fan)
+		wf_control_set_max(slots_fan);
+	if (drive_bay_fan)
+		wf_control_set_max(drive_bay_fan);
+}
+
+static void pm112_tick(void)
+{
+	int i, last_failure;
+
+	if (!started) {
+		started = 1;
+		for (i = 0; i < nr_cores; ++i) {
+			if (create_cpu_loop(i) < 0) {
+				failure_state = FAILURE_PERM;
+				set_fail_state();
+				break;
+			}
+		}
+		DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
+
+#ifdef HACKED_OVERTEMP
+		cpu_all_tmax = 60 << 16;
+#endif
+	}
+
+	/* Permanent failure, bail out */
+	if (failure_state & FAILURE_PERM)
+		return;
+	/* Clear all failure bits except low overtemp which will be eventually
+	 * cleared by the control loop itself
+	 */
+	last_failure = failure_state;
+	failure_state &= FAILURE_LOW_OVERTEMP;
+	cpu_fans_tick();
+	backside_fan_tick();
+	slots_fan_tick();
+	drive_bay_fan_tick();
+
+	DBG_LOTS("last_failure: 0x%x, failure_state: %x\n",
+		 last_failure, failure_state);
+
+	/* Check for failures. Any failure causes cpufreq clamping */
+	if (failure_state && last_failure == 0 && cpufreq_clamp)
+		wf_control_set_max(cpufreq_clamp);
+	if (failure_state == 0 && last_failure && cpufreq_clamp)
+		wf_control_set_min(cpufreq_clamp);
+
+	/* That's it for now, we might want to deal with other failures
+	 * differently in the future though
+	 */
+}
+
+static void pm112_new_control(struct wf_control *ct)
+{
+	int i, max_exhaust;
+
+	if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) {
+		if (wf_get_control(ct) == 0)
+			cpufreq_clamp = ct;
+	}
+
+	for (i = 0; i < NR_CPU_FANS; ++i) {
+		if (!strcmp(ct->name, cpu_fan_names[i])) {
+			if (cpu_fans[i] == NULL && wf_get_control(ct) == 0)
+				cpu_fans[i] = ct;
+			break;
+		}
+	}
+	if (i >= NR_CPU_FANS) {
+		/* not a CPU fan, try the others */
+		if (!strcmp(ct->name, "backside-fan")) {
+			if (backside_fan == NULL && wf_get_control(ct) == 0)
+				backside_fan = ct;
+		} else if (!strcmp(ct->name, "slots-fan")) {
+			if (slots_fan == NULL && wf_get_control(ct) == 0)
+				slots_fan = ct;
+		} else if (!strcmp(ct->name, "drive-bay-fan")) {
+			if (drive_bay_fan == NULL && wf_get_control(ct) == 0)
+				drive_bay_fan = ct;
+		}
+		return;
+	}
+
+	for (i = 0; i < CPU_FANS_REQD; ++i)
+		if (cpu_fans[i] == NULL)
+			return;
+
+	/* work out pump scaling factors */
+	max_exhaust = cpu_fans[0]->ops->get_max(cpu_fans[0]);
+	for (i = FIRST_PUMP; i <= LAST_PUMP; ++i)
+		if ((ct = cpu_fans[i]) != NULL)
+			cpu_fan_scale[i] =
+				ct->ops->get_max(ct) * 100 / max_exhaust;
+
+	have_all_controls = 1;
+}
+
+static void pm112_new_sensor(struct wf_sensor *sr)
+{
+	unsigned int i;
+
+	if (have_all_sensors)
+		return;
+	if (!strncmp(sr->name, "cpu-temp-", 9)) {
+		i = sr->name[9] - '0';
+		if (sr->name[10] == 0 && i < NR_CORES &&
+		    sens_cpu_temp[i] == NULL && wf_get_sensor(sr) == 0)
+			sens_cpu_temp[i] = sr;
+
+	} else if (!strncmp(sr->name, "cpu-power-", 10)) {
+		i = sr->name[10] - '0';
+		if (sr->name[11] == 0 && i < NR_CORES &&
+		    sens_cpu_power[i] == NULL && wf_get_sensor(sr) == 0)
+			sens_cpu_power[i] = sr;
+	} else if (!strcmp(sr->name, "hd-temp")) {
+		if (hd_temp == NULL && wf_get_sensor(sr) == 0)
+			hd_temp = sr;
+	} else if (!strcmp(sr->name, "slots-power")) {
+		if (slots_power == NULL && wf_get_sensor(sr) == 0)
+			slots_power = sr;
+	} else if (!strcmp(sr->name, "u4-temp")) {
+		if (u4_temp == NULL && wf_get_sensor(sr) == 0)
+			u4_temp = sr;
+	} else
+		return;
+
+	/* check if we have all the sensors we need */
+	for (i = 0; i < nr_cores; ++i)
+		if (sens_cpu_temp[i] == NULL || sens_cpu_power[i] == NULL)
+			return;
+
+	have_all_sensors = 1;
+}
+
+static int pm112_wf_notify(struct notifier_block *self,
+			   unsigned long event, void *data)
+{
+	switch (event) {
+	case WF_EVENT_NEW_SENSOR:
+		pm112_new_sensor(data);
+		break;
+	case WF_EVENT_NEW_CONTROL:
+		pm112_new_control(data);
+		break;
+	case WF_EVENT_TICK:
+		if (have_all_controls && have_all_sensors)
+			pm112_tick();
+	}
+	return 0;
+}
+
+static struct notifier_block pm112_events = {
+	.notifier_call = pm112_wf_notify,
+};
+
+static int wf_pm112_probe(struct device *dev)
+{
+	wf_register_client(&pm112_events);
+	return 0;
+}
+
+static int wf_pm112_remove(struct device *dev)
+{
+	wf_unregister_client(&pm112_events);
+	/* should release all sensors and controls */
+	return 0;
+}
+
+static struct device_driver wf_pm112_driver = {
+	.name = "windfarm",
+	.bus = &platform_bus_type,
+	.probe = wf_pm112_probe,
+	.remove = wf_pm112_remove,
+};
+
+static int __init wf_pm112_init(void)
+{
+	struct device_node *cpu;
+
+	if (!machine_is_compatible("PowerMac11,2"))
+		return -ENODEV;
+
+	/* Count the number of CPU cores */
+	nr_cores = 0;
+	for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
+		++nr_cores;
+
+	printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n");
+	driver_register(&wf_pm112_driver);
+	return 0;
+}
+
+static void __exit wf_pm112_exit(void)
+{
+	driver_unregister(&wf_pm112_driver);
+}
+
+module_init(wf_pm112_init);
+module_exit(wf_pm112_exit);
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("Thermal control for PowerMac11,2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index eb69a60..f1df6ef 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -538,45 +538,6 @@
 	}
 }
 
-
-/*
- * ****** Attributes ******
- *
- */
-
-#define BUILD_SHOW_FUNC_FIX(name, data)				\
-static ssize_t show_##name(struct device *dev,                  \
-			   struct device_attribute *attr,       \
-			   char *buf)	                        \
-{								\
-	ssize_t r;						\
-	s32 val = 0;                                            \
-	data->ops->get_value(data, &val);                       \
-	r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); 	\
-	return r;						\
-}                                                               \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-
-#define BUILD_SHOW_FUNC_INT(name, data)				\
-static ssize_t show_##name(struct device *dev,                  \
-			   struct device_attribute *attr,       \
-			   char *buf)	                        \
-{								\
-	s32 val = 0;                                            \
-	data->ops->get_value(data, &val);                       \
-	return sprintf(buf, "%d", val);  			\
-}                                                               \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main);
-BUILD_SHOW_FUNC_INT(sys_fan, fan_system);
-BUILD_SHOW_FUNC_INT(hd_fan, fan_hd);
-
-BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp);
-BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power);
-BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp);
-
 /*
  * ****** Setup / Init / Misc ... ******
  *
@@ -654,17 +615,13 @@
 		return;
 
 	if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-fan")) {
-		if (wf_get_control(ct) == 0) {
+		if (wf_get_control(ct) == 0)
 			fan_cpu_main = ct;
-			device_create_file(wf_smu_dev, &dev_attr_cpu_fan);
-		}
 	}
 
 	if (fan_system == NULL && !strcmp(ct->name, "system-fan")) {
-		if (wf_get_control(ct) == 0) {
+		if (wf_get_control(ct) == 0)
 			fan_system = ct;
-			device_create_file(wf_smu_dev, &dev_attr_sys_fan);
-		}
 	}
 
 	if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) {
@@ -683,10 +640,8 @@
 	}
 
 	if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) {
-		if (wf_get_control(ct) == 0) {
+		if (wf_get_control(ct) == 0)
 			fan_hd = ct;
-			device_create_file(wf_smu_dev, &dev_attr_hd_fan);
-		}
 	}
 
 	if (fan_system && fan_hd && fan_cpu_main && cpufreq_clamp)
@@ -699,24 +654,18 @@
 		return;
 
 	if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) {
-		if (wf_get_sensor(sr) == 0) {
+		if (wf_get_sensor(sr) == 0)
 			sensor_cpu_power = sr;
-			device_create_file(wf_smu_dev, &dev_attr_cpu_power);
-		}
 	}
 
 	if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) {
-		if (wf_get_sensor(sr) == 0) {
+		if (wf_get_sensor(sr) == 0)
 			sensor_cpu_temp = sr;
-			device_create_file(wf_smu_dev, &dev_attr_cpu_temp);
-		}
 	}
 
 	if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) {
-		if (wf_get_sensor(sr) == 0) {
+		if (wf_get_sensor(sr) == 0)
 			sensor_hd_temp = sr;
-			device_create_file(wf_smu_dev, &dev_attr_hd_temp);
-		}
 	}
 
 	if (sensor_cpu_power && sensor_cpu_temp && sensor_hd_temp)
@@ -794,32 +743,20 @@
 	 * with that except by adding locks all over... I'll do that
 	 * eventually but heh, who ever rmmod this module anyway ?
 	 */
-	if (sensor_cpu_power) {
-		device_remove_file(wf_smu_dev, &dev_attr_cpu_power);
+	if (sensor_cpu_power)
 		wf_put_sensor(sensor_cpu_power);
-	}
-	if (sensor_cpu_temp) {
-		device_remove_file(wf_smu_dev, &dev_attr_cpu_temp);
+	if (sensor_cpu_temp)
 		wf_put_sensor(sensor_cpu_temp);
-	}
-	if (sensor_hd_temp) {
-		device_remove_file(wf_smu_dev, &dev_attr_hd_temp);
+	if (sensor_hd_temp)
 		wf_put_sensor(sensor_hd_temp);
-	}
 
 	/* Release all controls */
-	if (fan_cpu_main) {
-		device_remove_file(wf_smu_dev, &dev_attr_cpu_fan);
+	if (fan_cpu_main)
 		wf_put_control(fan_cpu_main);
-	}
-	if (fan_hd) {
-		device_remove_file(wf_smu_dev, &dev_attr_hd_fan);
+	if (fan_hd)
 		wf_put_control(fan_hd);
-	}
-	if (fan_system) {
-		device_remove_file(wf_smu_dev, &dev_attr_sys_fan);
+	if (fan_system)
 		wf_put_control(fan_system);
-	}
 	if (cpufreq_clamp)
 		wf_put_control(cpufreq_clamp);
 
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
index 43243cf..0d6372e 100644
--- a/drivers/macintosh/windfarm_pm91.c
+++ b/drivers/macintosh/windfarm_pm91.c
@@ -458,45 +458,6 @@
 
 
 /*
- * ****** Attributes ******
- *
- */
-
-#define BUILD_SHOW_FUNC_FIX(name, data)				\
-static ssize_t show_##name(struct device *dev,                  \
-			   struct device_attribute *attr,       \
-			   char *buf)	                        \
-{								\
-	ssize_t r;						\
-	s32 val = 0;                                            \
-	data->ops->get_value(data, &val);                       \
-	r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); 	\
-	return r;						\
-}                                                               \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-
-#define BUILD_SHOW_FUNC_INT(name, data)				\
-static ssize_t show_##name(struct device *dev,                  \
-			   struct device_attribute *attr,       \
-			   char *buf)	                        \
-{								\
-	s32 val = 0;                                            \
-	data->ops->get_value(data, &val);                       \
-	return sprintf(buf, "%d", val);  			\
-}                                                               \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main);
-BUILD_SHOW_FUNC_INT(hd_fan, fan_hd);
-BUILD_SHOW_FUNC_INT(slots_fan, fan_slots);
-
-BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp);
-BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power);
-BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp);
-BUILD_SHOW_FUNC_FIX(slots_power, sensor_slots_power);
-
-/*
  * ****** Setup / Init / Misc ... ******
  *
  */
@@ -581,10 +542,8 @@
 		return;
 
 	if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-rear-fan-0")) {
-		if (wf_get_control(ct) == 0) {
+		if (wf_get_control(ct) == 0)
 			fan_cpu_main = ct;
-			device_create_file(wf_smu_dev, &dev_attr_cpu_fan);
-		}
 	}
 
 	if (fan_cpu_second == NULL && !strcmp(ct->name, "cpu-rear-fan-1")) {
@@ -603,17 +562,13 @@
 	}
 
 	if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) {
-		if (wf_get_control(ct) == 0) {
+		if (wf_get_control(ct) == 0)
 			fan_hd = ct;
-			device_create_file(wf_smu_dev, &dev_attr_hd_fan);
-		}
 	}
 
 	if (fan_slots == NULL && !strcmp(ct->name, "slots-fan")) {
-		if (wf_get_control(ct) == 0) {
+		if (wf_get_control(ct) == 0)
 			fan_slots = ct;
-			device_create_file(wf_smu_dev, &dev_attr_slots_fan);
-		}
 	}
 
 	if (fan_cpu_main && (fan_cpu_second || fan_cpu_third) && fan_hd &&
@@ -627,31 +582,23 @@
 		return;
 
 	if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) {
-		if (wf_get_sensor(sr) == 0) {
+		if (wf_get_sensor(sr) == 0)
 			sensor_cpu_power = sr;
-			device_create_file(wf_smu_dev, &dev_attr_cpu_power);
-		}
 	}
 
 	if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) {
-		if (wf_get_sensor(sr) == 0) {
+		if (wf_get_sensor(sr) == 0)
 			sensor_cpu_temp = sr;
-			device_create_file(wf_smu_dev, &dev_attr_cpu_temp);
-		}
 	}
 
 	if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) {
-		if (wf_get_sensor(sr) == 0) {
+		if (wf_get_sensor(sr) == 0)
 			sensor_hd_temp = sr;
-			device_create_file(wf_smu_dev, &dev_attr_hd_temp);
-		}
 	}
 
 	if (sensor_slots_power == NULL && !strcmp(sr->name, "slots-power")) {
-		if (wf_get_sensor(sr) == 0) {
+		if (wf_get_sensor(sr) == 0)
 			sensor_slots_power = sr;
-			device_create_file(wf_smu_dev, &dev_attr_slots_power);
-		}
 	}
 
 	if (sensor_cpu_power && sensor_cpu_temp &&
@@ -720,40 +667,26 @@
 	 * with that except by adding locks all over... I'll do that
 	 * eventually but heh, who ever rmmod this module anyway ?
 	 */
-	if (sensor_cpu_power) {
-		device_remove_file(wf_smu_dev, &dev_attr_cpu_power);
+	if (sensor_cpu_power)
 		wf_put_sensor(sensor_cpu_power);
-	}
-	if (sensor_cpu_temp) {
-		device_remove_file(wf_smu_dev, &dev_attr_cpu_temp);
+	if (sensor_cpu_temp)
 		wf_put_sensor(sensor_cpu_temp);
-	}
-	if (sensor_hd_temp) {
-		device_remove_file(wf_smu_dev, &dev_attr_hd_temp);
+	if (sensor_hd_temp)
 		wf_put_sensor(sensor_hd_temp);
-	}
-	if (sensor_slots_power) {
-		device_remove_file(wf_smu_dev, &dev_attr_slots_power);
+	if (sensor_slots_power)
 		wf_put_sensor(sensor_slots_power);
-	}
 
 	/* Release all controls */
-	if (fan_cpu_main) {
-		device_remove_file(wf_smu_dev, &dev_attr_cpu_fan);
+	if (fan_cpu_main)
 		wf_put_control(fan_cpu_main);
-	}
 	if (fan_cpu_second)
 		wf_put_control(fan_cpu_second);
 	if (fan_cpu_third)
 		wf_put_control(fan_cpu_third);
-	if (fan_hd) {
-		device_remove_file(wf_smu_dev, &dev_attr_hd_fan);
+	if (fan_hd)
 		wf_put_control(fan_hd);
-	}
-	if (fan_slots) {
-		device_remove_file(wf_smu_dev, &dev_attr_slots_fan);
+	if (fan_slots)
 		wf_put_control(fan_slots);
-	}
 	if (cpufreq_clamp)
 		wf_put_control(cpufreq_clamp);
 
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 4d81160..a9e88ed 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -24,7 +24,7 @@
 
 #include "windfarm.h"
 
-#define VERSION "0.3"
+#define VERSION "0.4"
 
 #undef DEBUG
 
@@ -34,6 +34,8 @@
 #define DBG(args...)	do { } while(0)
 #endif
 
+static int smu_supports_new_fans_ops = 1;
+
 /*
  * SMU fans control object
  */
@@ -59,23 +61,49 @@
 
 	/* Fill SMU command structure */
 	cmd.cmd = SMU_CMD_FAN_COMMAND;
-	cmd.data_len = 14;
+
+	/* The SMU has an "old" and a "new" way of setting the fan speed
+	 * Unfortunately, I found no reliable way to know which one works
+	 * on a given machine model. After some investigations it appears
+	 * that MacOS X just tries the new one, and if it fails fallbacks
+	 * to the old ones ... Ugh.
+	 */
+ retry:
+	if (smu_supports_new_fans_ops) {
+		buffer[0] = 0x30;
+		buffer[1] = id;
+		*((u16 *)(&buffer[2])) = value;
+		cmd.data_len = 4;
+	} else {
+		if (id > 7)
+			return -EINVAL;
+		/* Fill argument buffer */
+		memset(buffer, 0, 16);
+		buffer[0] = pwm ? 0x10 : 0x00;
+		buffer[1] = 0x01 << id;
+		*((u16 *)&buffer[2 + id * 2]) = value;
+		cmd.data_len = 14;
+	}
+
 	cmd.reply_len = 16;
 	cmd.data_buf = cmd.reply_buf = buffer;
 	cmd.status = 0;
 	cmd.done = smu_done_complete;
 	cmd.misc = &comp;
 
-	/* Fill argument buffer */
-	memset(buffer, 0, 16);
-	buffer[0] = pwm ? 0x10 : 0x00;
-	buffer[1] = 0x01 << id;
-	*((u16 *)&buffer[2 + id * 2]) = value;
-
 	rc = smu_queue_cmd(&cmd);
 	if (rc)
 		return rc;
 	wait_for_completion(&comp);
+
+	/* Handle fallback (see coment above) */
+	if (cmd.status != 0 && smu_supports_new_fans_ops) {
+		printk(KERN_WARNING "windfarm: SMU failed new fan command "
+		       "falling back to old method\n");
+		smu_supports_new_fans_ops = 0;
+		goto retry;
+	}
+
 	return cmd.status;
 }
 
@@ -158,19 +186,29 @@
 
 	/* Names used on desktop models */
 	if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") ||
-	    !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan"))
+	    !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan") ||
+	    !strcmp(l, "CPU A EXHAUST"))
 		fct->ctrl.name = "cpu-rear-fan-0";
-	else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1"))
+	else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1") ||
+		 !strcmp(l, "CPU B EXHAUST"))
 		fct->ctrl.name = "cpu-rear-fan-1";
 	else if (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") ||
-		 !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan"))
+		 !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan") ||
+		 !strcmp(l, "CPU A INTAKE"))
 		fct->ctrl.name = "cpu-front-fan-0";
-	else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1"))
+	else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1") ||
+		 !strcmp(l, "CPU B INTAKE"))
 		fct->ctrl.name = "cpu-front-fan-1";
-	else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan"))
+	else if (!strcmp(l, "CPU A PUMP"))
+		fct->ctrl.name = "cpu-pump-0";
+	else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") ||
+		 !strcmp(l, "EXPANSION SLOTS INTAKE"))
 		fct->ctrl.name = "slots-fan";
-	else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay"))
+	else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay") ||
+		 !strcmp(l, "DRIVE BAY A INTAKE"))
 		fct->ctrl.name = "drive-bay-fan";
+	else if (!strcmp(l, "BACKSIDE"))
+		fct->ctrl.name = "backside-fan";
 
 	/* Names used on iMac models */
 	if (!strcmp(l, "System Fan") || !strcmp(l, "System fan"))
@@ -223,7 +261,8 @@
 
 	/* Look for RPM fans */
 	for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;)
-		if (!strcmp(fans->name, "rpm-fans"))
+		if (!strcmp(fans->name, "rpm-fans") ||
+		    device_is_compatible(fans, "smu-rpm-fans"))
 			break;
 	for (fan = NULL;
 	     fans && (fan = of_get_next_child(fans, fan)) != NULL;) {
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
new file mode 100644
index 0000000..3a32c59
--- /dev/null
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -0,0 +1,418 @@
+/*
+ * Windfarm PowerMac thermal control.  SMU "satellite" controller sensors.
+ *
+ * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ *
+ * Released under the terms of the GNU GPL v2.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/semaphore.h>
+#include <asm/prom.h>
+#include <asm/smu.h>
+#include <asm/pmac_low_i2c.h>
+
+#include "windfarm.h"
+
+#define VERSION "0.2"
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(args...)	printk(args)
+#else
+#define DBG(args...)	do { } while(0)
+#endif
+
+/* If the cache is older than 800ms we'll refetch it */
+#define MAX_AGE		msecs_to_jiffies(800)
+
+struct wf_sat {
+	int			nr;
+	atomic_t		refcnt;
+	struct semaphore	mutex;
+	unsigned long		last_read; /* jiffies when cache last updated */
+	u8			cache[16];
+	struct i2c_client	i2c;
+	struct device_node	*node;
+};
+
+static struct wf_sat *sats[2];
+
+struct wf_sat_sensor {
+	int		index;
+	int		index2;		/* used for power sensors */
+	int		shift;
+	struct wf_sat	*sat;
+	struct wf_sensor sens;
+};
+
+#define wf_to_sat(c)	container_of(c, struct wf_sat_sensor, sens)
+#define i2c_to_sat(c)	container_of(c, struct wf_sat, i2c)
+
+static int wf_sat_attach(struct i2c_adapter *adapter);
+static int wf_sat_detach(struct i2c_client *client);
+
+static struct i2c_driver wf_sat_driver = {
+	.driver = {
+		.name		= "wf_smu_sat",
+	},
+	.attach_adapter	= wf_sat_attach,
+	.detach_client	= wf_sat_detach,
+};
+
+/*
+ * XXX i2c_smbus_read_i2c_block_data doesn't pass the requested
+ * length down to the low-level driver, so we use this, which
+ * works well enough with the SMU i2c driver code...
+ */
+static int sat_read_block(struct i2c_client *client, u8 command,
+			  u8 *values, int len)
+{
+	union i2c_smbus_data data;
+	int err;
+
+	data.block[0] = len;
+	err = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+			     I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA,
+			     &data);
+	if (!err)
+		memcpy(values, data.block, len);
+	return err;
+}
+
+struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
+						  unsigned int *size)
+{
+	struct wf_sat *sat;
+	int err;
+	unsigned int i, len;
+	u8 *buf;
+	u8 data[4];
+
+	/* TODO: Add the resulting partition to the device-tree */
+
+	if (sat_id > 1 || (sat = sats[sat_id]) == NULL)
+		return NULL;
+
+	err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8);
+	if (err) {
+		printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err);
+		return NULL;
+	}
+
+	len = i2c_smbus_read_word_data(&sat->i2c, 9);
+	if (len < 0) {
+		printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n");
+		return NULL;
+	}
+	if (len == 0) {
+		printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id);
+		return NULL;
+	}
+
+	len = le16_to_cpu(len);
+	len = (len + 3) & ~3;
+	buf = kmalloc(len, GFP_KERNEL);
+	if (buf == NULL)
+		return NULL;
+
+	for (i = 0; i < len; i += 4) {
+		err = sat_read_block(&sat->i2c, 0xa, data, 4);
+		if (err) {
+			printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n",
+			       err);
+			goto fail;
+		}
+		buf[i] = data[1];
+		buf[i+1] = data[0];
+		buf[i+2] = data[3];
+		buf[i+3] = data[2];
+	}
+#ifdef DEBUG
+	DBG(KERN_DEBUG "sat %d partition %x:", sat_id, id);
+	for (i = 0; i < len; ++i)
+		DBG(" %x", buf[i]);
+	DBG("\n");
+#endif
+
+	if (size)
+		*size = len;
+	return (struct smu_sdbp_header *) buf;
+
+ fail:
+	kfree(buf);
+	return NULL;
+}
+
+/* refresh the cache */
+static int wf_sat_read_cache(struct wf_sat *sat)
+{
+	int err;
+
+	err = sat_read_block(&sat->i2c, 0x3f, sat->cache, 16);
+	if (err)
+		return err;
+	sat->last_read = jiffies;
+#ifdef LOTSA_DEBUG
+	{
+		int i;
+		DBG(KERN_DEBUG "wf_sat_get: data is");
+		for (i = 0; i < 16; ++i)
+			DBG(" %.2x", sat->cache[i]);
+		DBG("\n");
+	}
+#endif
+	return 0;
+}
+
+static int wf_sat_get(struct wf_sensor *sr, s32 *value)
+{
+	struct wf_sat_sensor *sens = wf_to_sat(sr);
+	struct wf_sat *sat = sens->sat;
+	int i, err;
+	s32 val;
+
+	if (sat->i2c.adapter == NULL)
+		return -ENODEV;
+
+	down(&sat->mutex);
+	if (time_after(jiffies, (sat->last_read + MAX_AGE))) {
+		err = wf_sat_read_cache(sat);
+		if (err)
+			goto fail;
+	}
+
+	i = sens->index * 2;
+	val = ((sat->cache[i] << 8) + sat->cache[i+1]) << sens->shift;
+	if (sens->index2 >= 0) {
+		i = sens->index2 * 2;
+		/* 4.12 * 8.8 -> 12.20; shift right 4 to get 16.16 */
+		val = (val * ((sat->cache[i] << 8) + sat->cache[i+1])) >> 4;
+	}
+
+	*value = val;
+	err = 0;
+
+ fail:
+	up(&sat->mutex);
+	return err;
+}
+
+static void wf_sat_release(struct wf_sensor *sr)
+{
+	struct wf_sat_sensor *sens = wf_to_sat(sr);
+	struct wf_sat *sat = sens->sat;
+
+	if (atomic_dec_and_test(&sat->refcnt)) {
+		if (sat->i2c.adapter) {
+			i2c_detach_client(&sat->i2c);
+			sat->i2c.adapter = NULL;
+		}
+		if (sat->nr >= 0)
+			sats[sat->nr] = NULL;
+		kfree(sat);
+	}
+	kfree(sens);
+}
+
+static struct wf_sensor_ops wf_sat_ops = {
+	.get_value	= wf_sat_get,
+	.release	= wf_sat_release,
+	.owner		= THIS_MODULE,
+};
+
+static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
+{
+	struct wf_sat *sat;
+	struct wf_sat_sensor *sens;
+	u32 *reg;
+	char *loc, *type;
+	u8 addr, chip, core;
+	struct device_node *child;
+	int shift, cpu, index;
+	char *name;
+	int vsens[2], isens[2];
+
+	reg = (u32 *) get_property(dev, "reg", NULL);
+	if (reg == NULL)
+		return;
+	addr = *reg;
+	DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
+
+	sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL);
+	if (sat == NULL)
+		return;
+	sat->nr = -1;
+	sat->node = of_node_get(dev);
+	atomic_set(&sat->refcnt, 0);
+	init_MUTEX(&sat->mutex);
+	sat->i2c.addr = (addr >> 1) & 0x7f;
+	sat->i2c.adapter = adapter;
+	sat->i2c.driver = &wf_sat_driver;
+	strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1);
+
+	if (i2c_attach_client(&sat->i2c)) {
+		printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
+		goto fail;
+	}
+
+	vsens[0] = vsens[1] = -1;
+	isens[0] = isens[1] = -1;
+	child = NULL;
+	while ((child = of_get_next_child(dev, child)) != NULL) {
+		reg = (u32 *) get_property(child, "reg", NULL);
+		type = get_property(child, "device_type", NULL);
+		loc = get_property(child, "location", NULL);
+		if (reg == NULL || loc == NULL)
+			continue;
+
+		/* the cooked sensors are between 0x30 and 0x37 */
+		if (*reg < 0x30 || *reg > 0x37)
+			continue;
+		index = *reg - 0x30;
+
+		/* expect location to be CPU [AB][01] ... */
+		if (strncmp(loc, "CPU ", 4) != 0)
+			continue;
+		chip = loc[4] - 'A';
+		core = loc[5] - '0';
+		if (chip > 1 || core > 1) {
+			printk(KERN_ERR "wf_sat_create: don't understand "
+			       "location %s for %s\n", loc, child->full_name);
+			continue;
+		}
+		cpu = 2 * chip + core;
+		if (sat->nr < 0)
+			sat->nr = chip;
+		else if (sat->nr != chip) {
+			printk(KERN_ERR "wf_sat_create: can't cope with "
+			       "multiple CPU chips on one SAT (%s)\n", loc);
+			continue;
+		}
+
+		if (strcmp(type, "voltage-sensor") == 0) {
+			name = "cpu-voltage";
+			shift = 4;
+			vsens[core] = index;
+		} else if (strcmp(type, "current-sensor") == 0) {
+			name = "cpu-current";
+			shift = 8;
+			isens[core] = index;
+		} else if (strcmp(type, "temp-sensor") == 0) {
+			name = "cpu-temp";
+			shift = 10;
+		} else
+			continue;	/* hmmm shouldn't happen */
+
+		/* the +16 is enough for "cpu-voltage-n" */
+		sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL);
+		if (sens == NULL) {
+			printk(KERN_ERR "wf_sat_create: couldn't create "
+			       "%s sensor %d (no memory)\n", name, cpu);
+			continue;
+		}
+		sens->index = index;
+		sens->index2 = -1;
+		sens->shift = shift;
+		sens->sat = sat;
+		atomic_inc(&sat->refcnt);
+		sens->sens.ops = &wf_sat_ops;
+		sens->sens.name = (char *) (sens + 1);
+		snprintf(sens->sens.name, 16, "%s-%d", name, cpu);
+
+		if (wf_register_sensor(&sens->sens)) {
+			atomic_dec(&sat->refcnt);
+			kfree(sens);
+		}
+	}
+
+	/* make the power sensors */
+	for (core = 0; core < 2; ++core) {
+		if (vsens[core] < 0 || isens[core] < 0)
+			continue;
+		cpu = 2 * sat->nr + core;
+		sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL);
+		if (sens == NULL) {
+			printk(KERN_ERR "wf_sat_create: couldn't create power "
+			       "sensor %d (no memory)\n", cpu);
+			continue;
+		}
+		sens->index = vsens[core];
+		sens->index2 = isens[core];
+		sens->shift = 0;
+		sens->sat = sat;
+		atomic_inc(&sat->refcnt);
+		sens->sens.ops = &wf_sat_ops;
+		sens->sens.name = (char *) (sens + 1);
+		snprintf(sens->sens.name, 16, "cpu-power-%d", cpu);
+
+		if (wf_register_sensor(&sens->sens)) {
+			atomic_dec(&sat->refcnt);
+			kfree(sens);
+		}
+	}
+
+	if (sat->nr >= 0)
+		sats[sat->nr] = sat;
+
+	return;
+
+ fail:
+	kfree(sat);
+}
+
+static int wf_sat_attach(struct i2c_adapter *adapter)
+{
+	struct device_node *busnode, *dev = NULL;
+	struct pmac_i2c_bus *bus;
+
+	bus = pmac_i2c_adapter_to_bus(adapter);
+	if (bus == NULL)
+		return -ENODEV;
+	busnode = pmac_i2c_get_bus_node(bus);
+
+	while ((dev = of_get_next_child(busnode, dev)) != NULL)
+		if (device_is_compatible(dev, "smu-sat"))
+			wf_sat_create(adapter, dev);
+	return 0;
+}
+
+static int wf_sat_detach(struct i2c_client *client)
+{
+	struct wf_sat *sat = i2c_to_sat(client);
+
+	/* XXX TODO */
+
+	sat->i2c.adapter = NULL;
+	return 0;
+}
+
+static int __init sat_sensors_init(void)
+{
+	int err;
+
+	err = i2c_add_driver(&wf_sat_driver);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static void __exit sat_sensors_exit(void)
+{
+	i2c_del_driver(&wf_sat_driver);
+}
+
+module_init(sat_sensors_init);
+/*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c
index 1a00d9c..bed25dc 100644
--- a/drivers/macintosh/windfarm_smu_sensors.c
+++ b/drivers/macintosh/windfarm_smu_sensors.c
@@ -220,14 +220,29 @@
 	    !strcmp(l, "CPU T-Diode")) {
 		ads->sens.ops = &smu_cputemp_ops;
 		ads->sens.name = "cpu-temp";
+		if (cpudiode == NULL) {
+			DBG("wf: cpudiode partition (%02x) not found\n",
+			    SMU_SDB_CPUDIODE_ID);
+			goto fail;
+		}
 	} else if (!strcmp(c, "current-sensor") &&
 		   !strcmp(l, "CPU Current")) {
 		ads->sens.ops = &smu_cpuamp_ops;
 		ads->sens.name = "cpu-current";
+		if (cpuvcp == NULL) {
+			DBG("wf: cpuvcp partition (%02x) not found\n",
+			    SMU_SDB_CPUVCP_ID);
+			goto fail;
+		}
 	} else if (!strcmp(c, "voltage-sensor") &&
 		   !strcmp(l, "CPU Voltage")) {
 		ads->sens.ops = &smu_cpuvolt_ops;
 		ads->sens.name = "cpu-voltage";
+		if (cpuvcp == NULL) {
+			DBG("wf: cpuvcp partition (%02x) not found\n",
+			    SMU_SDB_CPUVCP_ID);
+			goto fail;
+		}
 	} else if (!strcmp(c, "power-sensor") &&
 		   !strcmp(l, "Slots Power")) {
 		ads->sens.ops = &smu_slotspow_ops;
@@ -365,29 +380,22 @@
 	return NULL;
 }
 
-static int smu_fetch_param_partitions(void)
+static void smu_fetch_param_partitions(void)
 {
 	struct smu_sdbp_header *hdr;
 
 	/* Get CPU voltage/current/power calibration data */
 	hdr = smu_get_sdb_partition(SMU_SDB_CPUVCP_ID, NULL);
-	if (hdr == NULL) {
-		DBG("wf: cpuvcp partition (%02x) not found\n",
-		    SMU_SDB_CPUVCP_ID);
-		return -ENODEV;
+	if (hdr != NULL) {
+		cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1];
+		/* Keep version around */
+		cpuvcp_version = hdr->version;
 	}
-	cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1];
-	/* Keep version around */
-	cpuvcp_version = hdr->version;
 
 	/* Get CPU diode calibration data */
 	hdr = smu_get_sdb_partition(SMU_SDB_CPUDIODE_ID, NULL);
-	if (hdr == NULL) {
-		DBG("wf: cpudiode partition (%02x) not found\n",
-		    SMU_SDB_CPUDIODE_ID);
-		return -ENODEV;
-	}
-	cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1];
+	if (hdr != NULL)
+		cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1];
 
 	/* Get slots power calibration data if any */
 	hdr = smu_get_sdb_partition(SMU_SDB_SLOTSPOW_ID, NULL);
@@ -398,23 +406,18 @@
 	hdr = smu_get_sdb_partition(SMU_SDB_DEBUG_SWITCHES_ID, NULL);
 	if (hdr != NULL)
 		debugswitches = (u8 *)&hdr[1];
-
-	return 0;
 }
 
 static int __init smu_sensors_init(void)
 {
 	struct device_node *smu, *sensors, *s;
 	struct smu_ad_sensor *volt_sensor = NULL, *curr_sensor = NULL;
-	int rc;
 
 	if (!smu_present())
 		return -ENODEV;
 
 	/* Get parameters partitions */
-	rc = smu_fetch_param_partitions();
-	if (rc)
-		return rc;
+	smu_fetch_param_partitions();
 
 	smu = of_find_node_by_type(NULL, "smu");
 	if (smu == NULL)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 1235135..442e2be 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1359,16 +1359,11 @@
 	 * Copy the parameters into kernel space.
 	 */
 	r = copy_params(user, &param);
-	if (r) {
-		current->flags &= ~PF_MEMALLOC;
-		return r;
-	}
 
-	/*
-	 * FIXME: eventually we will remove the PF_MEMALLOC flag
-	 * here.  However the tools still do nasty things like
-	 * 'load' while a device is suspended.
-	 */
+	current->flags &= ~PF_MEMALLOC;
+
+	if (r)
+		return r;
 
 	r = validate_params(cmd, param);
 	if (r)
@@ -1386,7 +1381,6 @@
 
  out:
 	free_params(param);
-	current->flags &= ~PF_MEMALLOC;
 	return r;
 }
 
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index efe4adf..d73779a 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -112,7 +112,7 @@
 /*
  * The on-disk version of the metadata.
  */
-#define MIRROR_DISK_VERSION 1
+#define MIRROR_DISK_VERSION 2
 #define LOG_OFFSET 2
 
 struct log_header {
@@ -157,7 +157,6 @@
 	struct log_header *disk_header;
 
 	struct io_region bits_location;
-	uint32_t *disk_bits;
 };
 
 /*
@@ -166,20 +165,20 @@
  */
 static  inline int log_test_bit(uint32_t *bs, unsigned bit)
 {
-	return test_bit(bit, (unsigned long *) bs) ? 1 : 0;
+	return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0;
 }
 
 static inline void log_set_bit(struct log_c *l,
 			       uint32_t *bs, unsigned bit)
 {
-	set_bit(bit, (unsigned long *) bs);
+	ext2_set_bit(bit, (unsigned long *) bs);
 	l->touched = 1;
 }
 
 static inline void log_clear_bit(struct log_c *l,
 				 uint32_t *bs, unsigned bit)
 {
-	clear_bit(bit, (unsigned long *) bs);
+	ext2_clear_bit(bit, (unsigned long *) bs);
 	l->touched = 1;
 }
 
@@ -219,6 +218,11 @@
 		log->header.nr_regions = 0;
 	}
 
+#ifdef __LITTLE_ENDIAN
+	if (log->header.version == 1)
+		log->header.version = 2;
+#endif
+
 	if (log->header.version != MIRROR_DISK_VERSION) {
 		DMWARN("incompatible disk log version");
 		return -EINVAL;
@@ -239,45 +243,24 @@
 /*----------------------------------------------------------------
  * Bits IO
  *--------------------------------------------------------------*/
-static inline void bits_to_core(uint32_t *core, uint32_t *disk, unsigned count)
-{
-	unsigned i;
-
-	for (i = 0; i < count; i++)
-		core[i] = le32_to_cpu(disk[i]);
-}
-
-static inline void bits_to_disk(uint32_t *core, uint32_t *disk, unsigned count)
-{
-	unsigned i;
-
-	/* copy across the clean/dirty bitset */
-	for (i = 0; i < count; i++)
-		disk[i] = cpu_to_le32(core[i]);
-}
-
 static int read_bits(struct log_c *log)
 {
 	int r;
 	unsigned long ebits;
 
 	r = dm_io_sync_vm(1, &log->bits_location, READ,
-			  log->disk_bits, &ebits);
+			  log->clean_bits, &ebits);
 	if (r)
 		return r;
 
-	bits_to_core(log->clean_bits, log->disk_bits,
-		     log->bitset_uint32_count);
 	return 0;
 }
 
 static int write_bits(struct log_c *log)
 {
 	unsigned long ebits;
-	bits_to_disk(log->clean_bits, log->disk_bits,
-		     log->bitset_uint32_count);
 	return dm_io_sync_vm(1, &log->bits_location, WRITE,
-			     log->disk_bits, &ebits);
+			     log->clean_bits, &ebits);
 }
 
 /*----------------------------------------------------------------
@@ -433,11 +416,6 @@
 	size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t),
 			   1 << SECTOR_SHIFT);
 	lc->bits_location.count = size >> SECTOR_SHIFT;
-	lc->disk_bits = vmalloc(size);
-	if (!lc->disk_bits) {
-		vfree(lc->disk_header);
-		goto bad;
-	}
 	return 0;
 
  bad:
@@ -451,7 +429,6 @@
 	struct log_c *lc = (struct log_c *) log->context;
 	dm_put_device(lc->ti, lc->log_dev);
 	vfree(lc->disk_header);
-	vfree(lc->disk_bits);
 	core_dtr(log);
 }
 
@@ -568,7 +545,8 @@
 		return 0;
 
 	do {
-		*region = find_next_zero_bit((unsigned long *) lc->sync_bits,
+		*region = ext2_find_next_zero_bit(
+					     (unsigned long *) lc->sync_bits,
 					     lc->region_count,
 					     lc->sync_search);
 		lc->sync_search = *region + 1;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 87727d8..f3759dd 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -373,16 +373,11 @@
 
 static void read_snapshot_metadata(struct dm_snapshot *s)
 {
-	if (s->have_metadata)
-		return;
-
 	if (s->store.read_metadata(&s->store)) {
 		down_write(&s->lock);
 		s->valid = 0;
 		up_write(&s->lock);
 	}
-
-	s->have_metadata = 1;
 }
 
 /*
@@ -471,7 +466,7 @@
 	s->chunk_shift = ffs(chunk_size) - 1;
 
 	s->valid = 1;
-	s->have_metadata = 0;
+	s->active = 0;
 	s->last_percent = 0;
 	init_rwsem(&s->lock);
 	s->table = ti->table;
@@ -506,7 +501,11 @@
 		goto bad5;
 	}
 
+	/* Metadata must only be loaded into one table at once */
+	read_snapshot_metadata(s);
+
 	/* Add snapshot to the list of snapshots for this origin */
+	/* Exceptions aren't triggered till snapshot_resume() is called */
 	if (register_snapshot(s)) {
 		r = -EINVAL;
 		ti->error = "Cannot register snapshot origin";
@@ -793,6 +792,9 @@
 	if (!s->valid)
 		return -EIO;
 
+	if (unlikely(bio_barrier(bio)))
+		return -EOPNOTSUPP;
+
 	/*
 	 * Write to snapshot - higher level takes care of RW/RO
 	 * flags so we should only get this if we are
@@ -862,7 +864,9 @@
 {
 	struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
 
-	read_snapshot_metadata(s);
+	down_write(&s->lock);
+	s->active = 1;
+	up_write(&s->lock);
 }
 
 static int snapshot_status(struct dm_target *ti, status_type_t type,
@@ -932,8 +936,8 @@
 	/* Do all the snapshots on this origin */
 	list_for_each_entry (snap, snapshots, list) {
 
-		/* Only deal with valid snapshots */
-		if (!snap->valid)
+		/* Only deal with valid and active snapshots */
+		if (!snap->valid || !snap->active)
 			continue;
 
 		/* Nothing to do if writing beyond end of snapshot */
@@ -1057,6 +1061,9 @@
 	struct dm_dev *dev = (struct dm_dev *) ti->private;
 	bio->bi_bdev = dev->bdev;
 
+	if (unlikely(bio_barrier(bio)))
+		return -EOPNOTSUPP;
+
 	/* Only tell snapshots if this is a write */
 	return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1;
 }
@@ -1104,7 +1111,7 @@
 
 static struct target_type origin_target = {
 	.name    = "snapshot-origin",
-	.version = {1, 0, 1},
+	.version = {1, 1, 0},
 	.module  = THIS_MODULE,
 	.ctr     = origin_ctr,
 	.dtr     = origin_dtr,
@@ -1115,7 +1122,7 @@
 
 static struct target_type snapshot_target = {
 	.name    = "snapshot",
-	.version = {1, 0, 1},
+	.version = {1, 1, 0},
 	.module  = THIS_MODULE,
 	.ctr     = snapshot_ctr,
 	.dtr     = snapshot_dtr,
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 375aa24..fdec1e2 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -99,7 +99,9 @@
 
 	/* You can't use a snapshot if this is 0 (e.g. if full) */
 	int valid;
-	int have_metadata;
+
+	/* Origin writes don't trigger exceptions until this is set */
+	int active;
 
 	/* Used for display of table */
 	char type;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a6f2dc6..9b1e2f5 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -508,7 +508,7 @@
 		if (q->merge_bvec_fn)
 			rs->max_sectors =
 				min_not_zero(rs->max_sectors,
-					     (unsigned short)(PAGE_SIZE >> 9));
+					     (unsigned int) (PAGE_SIZE >> 9));
 
 		rs->max_phys_segments =
 			min_not_zero(rs->max_phys_segments,
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 8c16359..e9adeb9 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -31,6 +31,7 @@
 	int error;
 	struct bio *bio;
 	atomic_t io_count;
+	unsigned long start_time;
 };
 
 /*
@@ -244,6 +245,36 @@
 	mempool_free(tio, md->tio_pool);
 }
 
+static void start_io_acct(struct dm_io *io)
+{
+	struct mapped_device *md = io->md;
+
+	io->start_time = jiffies;
+
+	preempt_disable();
+	disk_round_stats(dm_disk(md));
+	preempt_enable();
+	dm_disk(md)->in_flight = atomic_inc_return(&md->pending);
+}
+
+static int end_io_acct(struct dm_io *io)
+{
+	struct mapped_device *md = io->md;
+	struct bio *bio = io->bio;
+	unsigned long duration = jiffies - io->start_time;
+	int pending;
+	int rw = bio_data_dir(bio);
+
+	preempt_disable();
+	disk_round_stats(dm_disk(md));
+	preempt_enable();
+	dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending);
+
+	disk_stat_add(dm_disk(md), ticks[rw], duration);
+
+	return !pending;
+}
+
 /*
  * Add the bio to the list of deferred io.
  */
@@ -299,7 +330,7 @@
 		io->error = error;
 
 	if (atomic_dec_and_test(&io->io_count)) {
-		if (atomic_dec_and_test(&io->md->pending))
+		if (end_io_acct(io))
 			/* nudge anyone waiting on suspend queue */
 			wake_up(&io->md->wait);
 
@@ -554,7 +585,7 @@
 	ci.sector_count = bio_sectors(bio);
 	ci.idx = bio->bi_idx;
 
-	atomic_inc(&md->pending);
+	start_io_acct(ci.io);
 	while (ci.sector_count)
 		__clone_and_map(&ci);
 
@@ -573,10 +604,14 @@
 static int dm_request(request_queue_t *q, struct bio *bio)
 {
 	int r;
+	int rw = bio_data_dir(bio);
 	struct mapped_device *md = q->queuedata;
 
 	down_read(&md->io_lock);
 
+	disk_stat_inc(dm_disk(md), ios[rw]);
+	disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio));
+
 	/*
 	 * If we're suspended we have to queue
 	 * this io for later.
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index ca99979..8b3515f 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -8,6 +8,7 @@
  * completion notification.
  */
 
+#include <asm/types.h>
 #include <asm/atomic.h>
 
 #include <linux/blkdev.h>
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 7145cd1..d05e312 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1024,7 +1024,7 @@
 		rdev-> sb_size = (rdev->sb_size | bmask)+1;
 
 	if (refdev == 0)
-		return 1;
+		ret = 1;
 	else {
 		__u64 ev1, ev2;
 		struct mdp_superblock_1 *refsb = 
@@ -1044,7 +1044,9 @@
 		ev2 = le64_to_cpu(refsb->events);
 
 		if (ev1 > ev2)
-			return 1;
+			ret = 1;
+		else
+			ret = 0;
 	}
 	if (minor_version) 
 		rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2;
@@ -1058,7 +1060,7 @@
 
 	if (le32_to_cpu(sb->size) > rdev->size*2)
 		return -EINVAL;
-	return 0;
+	return ret;
 }
 
 static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
@@ -1081,7 +1083,7 @@
 		mddev->size = le64_to_cpu(sb->size)/2;
 		mddev->events = le64_to_cpu(sb->events);
 		mddev->bitmap_offset = 0;
-		mddev->default_bitmap_offset = 1024;
+		mddev->default_bitmap_offset = 1024 >> 9;
 		
 		mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
 		memcpy(mddev->uuid, sb->set_uuid, 16);
@@ -1161,6 +1163,9 @@
 
 	sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors);
 
+	sb->raid_disks = cpu_to_le32(mddev->raid_disks);
+	sb->size = cpu_to_le64(mddev->size<<1);
+
 	if (mddev->bitmap && mddev->bitmap_file == NULL) {
 		sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
 		sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
@@ -2686,14 +2691,6 @@
 			set_disk_ro(disk, 1);
 	}
 
-	bitmap_destroy(mddev);
-	if (mddev->bitmap_file) {
-		atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1);
-		fput(mddev->bitmap_file);
-		mddev->bitmap_file = NULL;
-	}
-	mddev->bitmap_offset = 0;
-
 	/*
 	 * Free resources if final stop
 	 */
@@ -2703,6 +2700,14 @@
 		struct gendisk *disk;
 		printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
 
+		bitmap_destroy(mddev);
+		if (mddev->bitmap_file) {
+			atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1);
+			fput(mddev->bitmap_file);
+			mddev->bitmap_file = NULL;
+		}
+		mddev->bitmap_offset = 0;
+
 		ITERATE_RDEV(mddev,rdev,tmp)
 			if (rdev->raid_disk >= 0) {
 				char nm[20];
@@ -2939,6 +2944,8 @@
 	info.ctime         = mddev->ctime;
 	info.level         = mddev->level;
 	info.size          = mddev->size;
+	if (info.size != mddev->size) /* overflow */
+		info.size = -1;
 	info.nr_disks      = nr;
 	info.raid_disks    = mddev->raid_disks;
 	info.md_minor      = mddev->md_minor;
@@ -3465,7 +3472,7 @@
 		bdev = bdget_disk(mddev->gendisk, 0);
 		if (bdev) {
 			mutex_lock(&bdev->bd_inode->i_mutex);
-			i_size_write(bdev->bd_inode, mddev->array_size << 10);
+			i_size_write(bdev->bd_inode, (loff_t)mddev->array_size << 10);
 			mutex_unlock(&bdev->bd_inode->i_mutex);
 			bdput(bdev);
 		}
@@ -3485,17 +3492,6 @@
 	if (mddev->sync_thread)
 		return -EBUSY;
 	rv = mddev->pers->reshape(mddev, raid_disks);
-	if (!rv) {
-		struct block_device *bdev;
-
-		bdev = bdget_disk(mddev->gendisk, 0);
-		if (bdev) {
-			mutex_lock(&bdev->bd_inode->i_mutex);
-			i_size_write(bdev->bd_inode, mddev->array_size << 10);
-			mutex_unlock(&bdev->bd_inode->i_mutex);
-			bdput(bdev);
-		}
-	}
 	return rv;
 }
 
@@ -3531,7 +3527,7 @@
 		)
 		return -EINVAL;
 	/* Check there is only one change */
-	if (mddev->size != info->size) cnt++;
+	if (info->size >= 0 && mddev->size != info->size) cnt++;
 	if (mddev->raid_disks != info->raid_disks) cnt++;
 	if (mddev->layout != info->layout) cnt++;
 	if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++;
@@ -3548,7 +3544,7 @@
 		else
 			return mddev->pers->reconfig(mddev, info->layout, -1);
 	}
-	if (mddev->size != info->size)
+	if (info->size >= 0 && mddev->size != info->size)
 		rv = update_size(mddev, info->size);
 
 	if (mddev->raid_disks    != info->raid_disks)
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index d03f99c..678f4db 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -372,7 +372,7 @@
 	kfree(conf);
 	mddev->private = NULL;
 out:
-	return 1;
+	return -ENOMEM;
 }
 
 static int raid0_stop (mddev_t *mddev)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9130d05..ab90a6d 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -565,6 +565,8 @@
 
 	if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL)
 		atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
+	else
+		disk = -1;
 	rcu_read_unlock();
 
 	return disk;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 25976bf..2dba305 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -350,7 +350,8 @@
 	while (drop_one_stripe(conf))
 		;
 
-	kmem_cache_destroy(conf->slab_cache);
+	if (conf->slab_cache)
+		kmem_cache_destroy(conf->slab_cache);
 	conf->slab_cache = NULL;
 }
 
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index f618a53..cd477eb 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -115,7 +115,7 @@
 			list_add_tail(&sh->lru, &conf->inactive_list);
 			atomic_dec(&conf->active_stripes);
 			if (!conf->inactive_blocked ||
-			    atomic_read(&conf->active_stripes) < (NR_STRIPES*3/4))
+			    atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4))
 				wake_up(&conf->wait_for_stripe);
 		}
 	}
@@ -273,7 +273,8 @@
 				conf->inactive_blocked = 1;
 				wait_event_lock_irq(conf->wait_for_stripe,
 						    !list_empty(&conf->inactive_list) &&
-						    (atomic_read(&conf->active_stripes) < (NR_STRIPES *3/4)
+						    (atomic_read(&conf->active_stripes)
+						     < (conf->max_nr_stripes *3/4)
 						     || !conf->inactive_blocked),
 						    conf->device_lock,
 						    unplug_slaves(conf->mddev);
@@ -302,9 +303,31 @@
 	return sh;
 }
 
-static int grow_stripes(raid6_conf_t *conf, int num)
+static int grow_one_stripe(raid6_conf_t *conf)
 {
 	struct stripe_head *sh;
+	sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
+	if (!sh)
+		return 0;
+	memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
+	sh->raid_conf = conf;
+	spin_lock_init(&sh->lock);
+
+	if (grow_buffers(sh, conf->raid_disks)) {
+		shrink_buffers(sh, conf->raid_disks);
+		kmem_cache_free(conf->slab_cache, sh);
+		return 0;
+	}
+	/* we just created an active stripe so... */
+	atomic_set(&sh->count, 1);
+	atomic_inc(&conf->active_stripes);
+	INIT_LIST_HEAD(&sh->lru);
+	release_stripe(sh);
+	return 1;
+}
+
+static int grow_stripes(raid6_conf_t *conf, int num)
+{
 	kmem_cache_t *sc;
 	int devs = conf->raid_disks;
 
@@ -316,45 +339,35 @@
 	if (!sc)
 		return 1;
 	conf->slab_cache = sc;
-	while (num--) {
-		sh = kmem_cache_alloc(sc, GFP_KERNEL);
-		if (!sh)
+	while (num--)
+		if (!grow_one_stripe(conf))
 			return 1;
-		memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev));
-		sh->raid_conf = conf;
-		spin_lock_init(&sh->lock);
-
-		if (grow_buffers(sh, conf->raid_disks)) {
-			shrink_buffers(sh, conf->raid_disks);
-			kmem_cache_free(sc, sh);
-			return 1;
-		}
-		/* we just created an active stripe so... */
-		atomic_set(&sh->count, 1);
-		atomic_inc(&conf->active_stripes);
-		INIT_LIST_HEAD(&sh->lru);
-		release_stripe(sh);
-	}
 	return 0;
 }
 
+static int drop_one_stripe(raid6_conf_t *conf)
+{
+	struct stripe_head *sh;
+	spin_lock_irq(&conf->device_lock);
+	sh = get_free_stripe(conf);
+	spin_unlock_irq(&conf->device_lock);
+	if (!sh)
+		return 0;
+	if (atomic_read(&sh->count))
+		BUG();
+	shrink_buffers(sh, conf->raid_disks);
+	kmem_cache_free(conf->slab_cache, sh);
+	atomic_dec(&conf->active_stripes);
+	return 1;
+}
+
 static void shrink_stripes(raid6_conf_t *conf)
 {
-	struct stripe_head *sh;
+	while (drop_one_stripe(conf))
+		;
 
-	while (1) {
-		spin_lock_irq(&conf->device_lock);
-		sh = get_free_stripe(conf);
-		spin_unlock_irq(&conf->device_lock);
-		if (!sh)
-			break;
-		if (atomic_read(&sh->count))
-			BUG();
-		shrink_buffers(sh, conf->raid_disks);
-		kmem_cache_free(conf->slab_cache, sh);
-		atomic_dec(&conf->active_stripes);
-	}
-	kmem_cache_destroy(conf->slab_cache);
+	if (conf->slab_cache)
+		kmem_cache_destroy(conf->slab_cache);
 	conf->slab_cache = NULL;
 }
 
@@ -1912,6 +1925,74 @@
 	PRINTK("--- raid6d inactive\n");
 }
 
+static ssize_t
+raid6_show_stripe_cache_size(mddev_t *mddev, char *page)
+{
+	raid6_conf_t *conf = mddev_to_conf(mddev);
+	if (conf)
+		return sprintf(page, "%d\n", conf->max_nr_stripes);
+	else
+		return 0;
+}
+
+static ssize_t
+raid6_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
+{
+	raid6_conf_t *conf = mddev_to_conf(mddev);
+	char *end;
+	int new;
+	if (len >= PAGE_SIZE)
+		return -EINVAL;
+	if (!conf)
+		return -ENODEV;
+
+	new = simple_strtoul(page, &end, 10);
+	if (!*page || (*end && *end != '\n') )
+		return -EINVAL;
+	if (new <= 16 || new > 32768)
+		return -EINVAL;
+	while (new < conf->max_nr_stripes) {
+		if (drop_one_stripe(conf))
+			conf->max_nr_stripes--;
+		else
+			break;
+	}
+	while (new > conf->max_nr_stripes) {
+		if (grow_one_stripe(conf))
+			conf->max_nr_stripes++;
+		else break;
+	}
+	return len;
+}
+
+static struct md_sysfs_entry
+raid6_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR,
+				raid6_show_stripe_cache_size,
+				raid6_store_stripe_cache_size);
+
+static ssize_t
+stripe_cache_active_show(mddev_t *mddev, char *page)
+{
+	raid6_conf_t *conf = mddev_to_conf(mddev);
+	if (conf)
+		return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
+	else
+		return 0;
+}
+
+static struct md_sysfs_entry
+raid6_stripecache_active = __ATTR_RO(stripe_cache_active);
+
+static struct attribute *raid6_attrs[] =  {
+	&raid6_stripecache_size.attr,
+	&raid6_stripecache_active.attr,
+	NULL,
+};
+static struct attribute_group raid6_attrs_group = {
+	.name = NULL,
+	.attrs = raid6_attrs,
+};
+
 static int run(mddev_t *mddev)
 {
 	raid6_conf_t *conf;
@@ -2095,6 +2176,7 @@
 	shrink_stripes(conf);
 	kfree(conf->stripe_hashtbl);
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
+	sysfs_remove_group(&mddev->kobj, &raid6_attrs_group);
 	kfree(conf);
 	mddev->private = NULL;
 	return 0;
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index 2583a86..2963605 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -4,7 +4,7 @@
 	select DVB_STV0299
 	select DVB_MT352
 	select DVB_MT312
-	select DVB_NXT2002
+	select DVB_NXT200X
 	select DVB_STV0297
 	select DVB_BCM3510
 	select DVB_LGDT330X
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 344a3c8..7d7e161 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -116,11 +116,9 @@
 
 int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
 int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
-int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
 int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx);
 int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff);
 int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles);
-int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets);
 
 /* from flexcop-eeprom.c */
 /* the PCI part uses this call to get the MAC address, the USB part has its own */
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
index cf4ed1d..6f592bc 100644
--- a/drivers/media/dvb/b2c2/flexcop-dma.c
+++ b/drivers/media/dvb/b2c2/flexcop-dma.c
@@ -169,38 +169,3 @@
 }
 EXPORT_SYMBOL(flexcop_dma_config_timer);
 
-/* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */
-int flexcop_dma_control_packet_irq(struct flexcop_device *fc,
-		flexcop_dma_index_t no,
-		int onoff)
-{
-	flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
-
-	deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
-	if (no & FC_DMA_1)
-		v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
-
-	if (no & FC_DMA_2)
-		v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
-
-	fc->write_ibi_reg(fc,ctrl_208,v);
-	deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
-
-	return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
-
-int flexcop_dma_config_packet_count(struct flexcop_device *fc,
-		flexcop_dma_index_t dma_idx,
-		u8 packets)
-{
-	flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
-	flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
-
-	flexcop_dma_remap(fc,dma_idx,1);
-
-	v.dma_0x4_remap.DMA_maxpackets = packets;
-	fc->write_ibi_reg(fc,r,v);
-	return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_config_packet_count);
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 0b940e1..390cc3a 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -9,7 +9,7 @@
 
 #include "stv0299.h"
 #include "mt352.h"
-#include "nxt2002.h"
+#include "nxt200x.h"
 #include "bcm3510.h"
 #include "stv0297.h"
 #include "mt312.h"
@@ -343,9 +343,10 @@
 	.clock_polarity_flip = 1,
 };
 
-static struct nxt2002_config samsung_tbmv_config = {
+static struct nxt200x_config samsung_tbmv_config = {
 	.demod_address    = 0x0a,
-	.request_firmware = flexcop_fe_request_firmware,
+	.pll_address      = 0xc2,
+	.pll_desc         = &dvb_pll_samsung_tbmv,
 };
 
 static struct bcm3510_config air2pc_atsc_first_gen_config = {
@@ -505,7 +506,7 @@
 		info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
 	} else
 	/* try the air atsc 2nd generation (nxt2002) */
-	if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
+	if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
 		fc->dev_type          = FC_AIR_ATSC2;
 		info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
 	} else
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
index 62282d8..167583b 100644
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -36,14 +36,14 @@
 	/* bus parts have to decide if hw pid filtering is used or not. */
 }
 
-const char *flexcop_revision_names[] = {
+static const char *flexcop_revision_names[] = {
 	"Unkown chip",
 	"FlexCopII",
 	"FlexCopIIb",
 	"FlexCopIII",
 };
 
-const char *flexcop_device_names[] = {
+static const char *flexcop_device_names[] = {
 	"Unkown device",
 	"Air2PC/AirStar 2 DVB-T",
 	"Air2PC/AirStar 2 ATSC 1st generation",
@@ -54,7 +54,7 @@
 	"Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
 };
 
-const char *flexcop_bus_names[] = {
+static const char *flexcop_bus_names[] = {
 	"USB",
 	"PCI",
 };
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
index 2f76eb3..9bc40bd 100644
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -161,8 +161,10 @@
 			fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
 		u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
 
-		deb_irq("%u irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ",
-				jiffies_to_usecs(jiffies - fc_pci->last_irq),v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos);
+		deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ",
+				jiffies_to_usecs(jiffies - fc_pci->last_irq),
+				v.raw, (unsigned long long)cur_addr, cur_pos,
+				fc_pci->last_dma1_cur_pos);
 		fc_pci->last_irq = jiffies;
 
 		/* buffer end was reached, restarted from the beginning
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 3153f95..491f9bd 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -16,8 +16,6 @@
 	FLEXCOP_III,
 } flexcop_revision_t;
 
-extern const char *flexcop_revision_names[];
-
 typedef enum {
 	FC_UNK = 0,
 	FC_AIR_DVB,
@@ -34,8 +32,6 @@
 	FC_PCI,
 } flexcop_bus_t;
 
-extern const char *flexcop_device_names[];
-
 /* FlexCop IBI Registers */
 #if defined(__LITTLE_ENDIAN)
 	#include "flexcop_ibi_value_le.h"
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index a04bb61..34c3189 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -381,6 +381,23 @@
 
 EXPORT_SYMBOL(bt878_device_control);
 
+
+struct cards card_list[] __devinitdata = {
+
+	{ 0x01010071, BTTV_BOARD_NEBULA_DIGITV,			"Nebula Electronics DigiTV" },
+	{ 0x07611461, BTTV_BOARD_AVDVBT_761,			"AverMedia AverTV DVB-T 761" },
+	{ 0x001c11bd, BTTV_BOARD_PINNACLESAT,			"Pinnacle PCTV Sat" },
+	{ 0x002611bd, BTTV_BOARD_TWINHAN_DST,			"Pinnacle PCTV SAT CI" },
+	{ 0x00011822, BTTV_BOARD_TWINHAN_DST,			"Twinhan VisionPlus DVB" },
+	{ 0xfc00270f, BTTV_BOARD_TWINHAN_DST,			"ChainTech digitop DST-1000 DVB-S" },
+	{ 0x07711461, BTTV_BOARD_AVDVBT_771,			"AVermedia AverTV DVB-T 771" },
+	{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,		"DViCO FusionHDTV DVB-T Lite" },
+	{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,	"DViCO FusionHDTV 5 Lite" },
+	{ 0x20007063, BTTV_BOARD_PC_HDTV,			"pcHDTV HD-2000 TV"},
+	{ 0, -1, NULL }
+};
+
+
 /***********************/
 /* PCI device handling */
 /***********************/
@@ -388,18 +405,41 @@
 static int __devinit bt878_probe(struct pci_dev *dev,
 				 const struct pci_device_id *pci_id)
 {
-	int result;
+	int result = 0, has_dvb = 0, i;
 	unsigned char lat;
 	struct bt878 *bt;
 #if defined(__powerpc__)
 	unsigned int cmd;
 #endif
+	unsigned int cardid;
+	unsigned short id;
+	struct cards *dvb_cards;
 
 	printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
 	       bt878_num);
 	if (pci_enable_device(dev))
 		return -EIO;
 
+	pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &id);
+	cardid = id << 16;
+	pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &id);
+	cardid |= id;
+
+	for (i = 0, dvb_cards = card_list; i < ARRAY_SIZE(card_list); i++, dvb_cards++) {
+		if (cardid == dvb_cards->pci_id) {
+			printk("%s: card id=[0x%x],[ %s ] has DVB functions.\n",
+				__func__, cardid, dvb_cards->name);
+			has_dvb = 1;
+		}
+	}
+
+	if (!has_dvb) {
+		printk("%s: card id=[0x%x], Unknown card.\nExiting..\n", __func__, cardid);
+		result = -EINVAL;
+
+		goto fail0;
+	}
+
 	bt = &bt878[bt878_num];
 	bt->dev = dev;
 	bt->nr = bt878_num;
@@ -416,6 +456,8 @@
 
 	pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
 	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+
+
 	printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ",
 	       bt878_num, bt->id, bt->revision, dev->bus->number,
 	       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index a73baf0..9faf937 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -88,6 +88,23 @@
 
 #define BT878_RISC_SYNC_MASK	(1 << 15)
 
+
+#define BTTV_BOARD_UNKNOWN                 0x00
+#define BTTV_BOARD_PINNACLESAT             0x5e
+#define BTTV_BOARD_NEBULA_DIGITV           0x68
+#define BTTV_BOARD_PC_HDTV                 0x70
+#define BTTV_BOARD_TWINHAN_DST             0x71
+#define BTTV_BOARD_AVDVBT_771              0x7b
+#define BTTV_BOARD_AVDVBT_761              0x7c
+#define BTTV_BOARD_DVICO_DVBT_LITE         0x80
+#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
+
+struct cards {
+	__u32 pci_id;
+	__u16 card_id;
+	char  *name;
+};
+
 extern int bt878_num;
 
 struct bt878 {
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 90a69d3..d3df120 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -83,12 +83,18 @@
 	  Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
 
 config DVB_USB_CXUSB
-	tristate "Medion MD95700 hybrid USB2.0 (Conexant) support"
+	tristate "Conexant USB2.0 hybrid reference design support"
 	depends on DVB_USB
 	select DVB_CX22702
+	select DVB_LGDT330X
+	select DVB_MT352
 	help
-	  Say Y here to support the Medion MD95700 hybrid USB2.0 device. Currently
-	  only the DVB-T part is supported.
+	  Say Y here to support the Conexant USB2.0 hybrid reference design.
+	  Currently, only DVB and ATSC modes are supported, analog mode
+	  shall be added in the future. Devices that require this module:
+
+	  Medion MD95700 hybrid USB2.0 device.
+	  DViCO FusionHDTV (Bluebird) USB2.0 devices
 
 config DVB_USB_DIGITV
 	tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index a7fb06f..f327fac 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -184,7 +184,7 @@
 	return 0;
 }
 
-struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
+static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
 	{ 0xfe, 0x02, KEY_TV },
 	{ 0xfe, 0x0e, KEY_MP3 },
 	{ 0xfe, 0x1a, KEY_DVD },
@@ -234,7 +234,7 @@
 
 static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
 {
-	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
+	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x28 };
 	static u8 reset []         = { RESET,      0x80 };
 	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
 	static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
@@ -255,7 +255,7 @@
 
 static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
 {	/* used in both lgz201 and th7579 */
-	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
+	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x29 };
 	static u8 reset []         = { RESET,      0x80 };
 	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
 	static u8 agc_cfg []       = { AGC_TARGET, 0x24, 0x20 };
@@ -273,7 +273,7 @@
 	return 0;
 }
 
-struct cx22702_config cxusb_cx22702_config = {
+static struct cx22702_config cxusb_cx22702_config = {
 	.demod_address = 0x63,
 
 	.output_mode = CX22702_PARALLEL_OUTPUT,
@@ -282,13 +282,13 @@
 	.pll_set  = dvb_usb_pll_set_i2c,
 };
 
-struct lgdt330x_config cxusb_lgdt330x_config = {
+static struct lgdt330x_config cxusb_lgdt330x_config = {
 	.demod_address = 0x0e,
 	.demod_chip    = LGDT3303,
 	.pll_set       = dvb_usb_pll_set_i2c,
 };
 
-struct mt352_config cxusb_dee1601_config = {
+static struct mt352_config cxusb_dee1601_config = {
 	.demod_address = 0x0f,
 	.demod_init    = cxusb_dee1601_demod_init,
 	.pll_set       = dvb_usb_pll_set,
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index e6c55c9..caa1346 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -175,11 +175,13 @@
 	if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
 		u8 b[4] = { 0 };
 
-		b[0] = 1;
-		digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
+		if (d != NULL) { /* do that only when the firmware is loaded */
+			b[0] = 1;
+			digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
 
-		b[0] = 0;
-		digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+			b[0] = 0;
+			digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+		}
 	}
 	return ret;
 }
@@ -194,7 +196,7 @@
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-digitv-01.fw",
+	.firmware = "dvb-usb-digitv-02.fw",
 
 	.size_of_priv     = 0,
 
@@ -229,6 +231,7 @@
 			{ &digitv_table[0], NULL },
 			{ NULL },
 		},
+		{ NULL },
 	}
 };
 
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 130ea7f..12ebaf8 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -151,7 +151,7 @@
 		  .cold_ids = { &dtt200u_usb_table[0], NULL },
 		  .warm_ids = { &dtt200u_usb_table[1], NULL },
 		},
-		{ 0 },
+		{ NULL },
 	}
 };
 
@@ -192,7 +192,7 @@
 		  .cold_ids = { &dtt200u_usb_table[2], NULL },
 		  .warm_ids = { &dtt200u_usb_table[3], NULL },
 		},
-		{ 0 },
+		{ NULL },
 	}
 };
 
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index 8535895..9222b0a 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -24,6 +24,9 @@
 	{ .id = CYPRESS_FX2,     .name = "Cypress FX2",     .cpu_cs_register = 0xe600 },
 };
 
+static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
+			       int *pos);
+
 /*
  * load a firmware packet to the device
  */
@@ -112,7 +115,8 @@
 	return ret;
 }
 
-int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
+static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
+			       int *pos)
 {
 	u8 *b = (u8 *) &fw->data[*pos];
 	int data_offs = 4;
@@ -142,5 +146,3 @@
 
 	return *pos;
 }
-EXPORT_SYMBOL(dvb_usb_get_hexline);
-
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index dd56839..5e5d21a 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -341,7 +341,6 @@
 	u8 data[255];
 	u8 chk;
 };
-extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *);
 extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
 
 #endif
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index afa00fd..4a95eca 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -53,7 +53,8 @@
 	return ret;
 }
 
-int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+			     u16 index, u8 *b, int blen)
 {
 	deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
 	debug_dump(b,blen,deb_xfer);
@@ -88,7 +89,8 @@
 	return ret;
 }
 
-int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec)
+static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
+				int olen, u8 *i, int ilen, int msec)
 {
 	u8 bout[olen+2];
 	u8 bin[ilen+1];
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
index a808d48..c2f97f9 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.h
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -101,8 +101,6 @@
 extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
 
 extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
-extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec);
 extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
-extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
 
 #endif
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
index 5242cca..9999336 100644
--- a/drivers/media/dvb/dvb-usb/vp7045-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -23,10 +23,11 @@
 
 struct vp7045_fe_state {
 	struct dvb_frontend fe;
+	struct dvb_frontend_ops ops;
+
 	struct dvb_usb_device *d;
 };
 
-
 static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
 {
 	struct vp7045_fe_state *state = fe->demodulator_priv;
@@ -150,7 +151,8 @@
 		goto error;
 
 	s->d = d;
-	s->fe.ops = &vp7045_fe_ops;
+	memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
+	s->fe.ops = &s->ops;
 	s->fe.demodulator_priv = s;
 
 	goto success;
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 0282049..3835235 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -247,7 +247,7 @@
 		  .cold_ids = { &vp7045_usb_table[2], NULL },
 		  .warm_ids = { &vp7045_usb_table[3], NULL },
 		},
-		{ 0 },
+		{ NULL },
 	}
 };
 
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index db3a8b4..76b6a2a 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -28,12 +28,6 @@
 	help
 	  A DVB-S tuner module. Say Y when you want to support this frontend.
 
-config DVB_TDA80XX
-	tristate "Philips TDA8044 or TDA8083 based"
-	depends on DVB_CORE
-	help
-	  A DVB-S tuner module. Say Y when you want to support this frontend.
-
 config DVB_MT312
 	tristate "Zarlink MT312 based"
 	depends on DVB_CORE
@@ -139,12 +133,6 @@
 comment "DVB-C (cable) frontends"
 	depends on DVB_CORE
 
-config DVB_ATMEL_AT76C651
-	tristate "Atmel AT76C651 based"
-	depends on DVB_CORE
-	help
-	  A DVB-C tuner module. Say Y when you want to support this frontend.
-
 config DVB_VES1820
 	tristate "VLSI VES1820 based"
 	depends on DVB_CORE
@@ -166,18 +154,6 @@
 comment "ATSC (North American/Korean Terresterial DTV) frontends"
 	depends on DVB_CORE
 
-config DVB_NXT2002
-	tristate "Nxt2002 based"
-	depends on DVB_CORE
-	select FW_LOADER
-	help
-	  An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
-
-	  This driver needs external firmware. Please use the command
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
-	  download/extract it, and then copy it to /usr/lib/hotplug/firmware
-	  or /lib/firmware (depending on configuration of firmware hotplug).
-
 config DVB_NXT200X
 	tristate "Nextwave NXT2002/NXT2004 based"
 	depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 615ec83..1af769c 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -8,7 +8,6 @@
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
 obj-$(CONFIG_DVB_SP8870) += sp8870.o
 obj-$(CONFIG_DVB_CX22700) += cx22700.o
-obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o
 obj-$(CONFIG_DVB_CX24110) += cx24110.o
 obj-$(CONFIG_DVB_TDA8083) += tda8083.o
 obj-$(CONFIG_DVB_L64781) += l64781.o
@@ -22,10 +21,8 @@
 obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
 obj-$(CONFIG_DVB_MT352) += mt352.o
 obj-$(CONFIG_DVB_CX22702) += cx22702.o
-obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o
 obj-$(CONFIG_DVB_TDA10021) += tda10021.o
 obj-$(CONFIG_DVB_STV0297) += stv0297.o
-obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
 obj-$(CONFIG_DVB_NXT200X) += nxt200x.o
 obj-$(CONFIG_DVB_OR51211) += or51211.o
 obj-$(CONFIG_DVB_OR51132) += or51132.o
diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c
deleted file mode 100644
index 8e0f4b3..0000000
--- a/drivers/media/dvb/frontends/at76c651.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * at76c651.c
- *
- * Atmel DVB-C Frontend Driver (at76c651/tua6010xs)
- *
- * Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
- *             & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- *             & 2003 Wolfram Joost <dbox2@frokaschwei.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * AT76C651
- * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
- * http://www.atmel.com/atmel/acrobat/doc1320.pdf
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include "dvb_frontend.h"
-#include "at76c651.h"
-
-
-struct at76c651_state {
-
-	struct i2c_adapter* i2c;
-
-	struct dvb_frontend_ops ops;
-
-	const struct at76c651_config* config;
-
-	struct dvb_frontend frontend;
-
-	/* revision of the chip */
-	u8 revision;
-
-	/* last QAM value set */
-	u8 qam;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "at76c651: " args); \
-	} while (0)
-
-
-#if ! defined(__powerpc__)
-static __inline__ int __ilog2(unsigned long x)
-{
-	int i;
-
-	if (x == 0)
-		return -1;
-
-	for (i = 0; x != 0; i++)
-		x >>= 1;
-
-	return i - 1;
-}
-#endif
-
-static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg =
-		{ .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: writereg error "
-			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-			__FUNCTION__, reg, data, ret);
-
-	msleep(10);
-
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static u8 at76c651_readreg(struct at76c651_state* state, u8 reg)
-{
-	int ret;
-	u8 val;
-	struct i2c_msg msg[] = {
-		{ .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 }
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
-
-	return val;
-}
-
-static int at76c651_reset(struct at76c651_state* state)
-{
-	return at76c651_writereg(state, 0x07, 0x01);
-}
-
-static void at76c651_disable_interrupts(struct at76c651_state* state)
-{
-	at76c651_writereg(state, 0x0b, 0x00);
-}
-
-static int at76c651_set_auto_config(struct at76c651_state *state)
-{
-	/*
-	 * Autoconfig
-	 */
-
-	at76c651_writereg(state, 0x06, 0x01);
-
-	/*
-	 * Performance optimizations, should be done after autoconfig
-	 */
-
-	at76c651_writereg(state, 0x10, 0x06);
-	at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10);
-	at76c651_writereg(state, 0x15, 0x28);
-	at76c651_writereg(state, 0x20, 0x09);
-	at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90);
-	at76c651_writereg(state, 0x30, 0x90);
-	if (state->qam == 5)
-		at76c651_writereg(state, 0x35, 0x2A);
-
-	/*
-	 * Initialize A/D-converter
-	 */
-
-	if (state->revision == 0x11) {
-		at76c651_writereg(state, 0x2E, 0x38);
-		at76c651_writereg(state, 0x2F, 0x13);
-	}
-
-	at76c651_disable_interrupts(state);
-
-	/*
-	 * Restart operation
-	 */
-
-	at76c651_reset(state);
-
-	return 0;
-}
-
-static void at76c651_set_bbfreq(struct at76c651_state* state)
-{
-	at76c651_writereg(state, 0x04, 0x3f);
-	at76c651_writereg(state, 0x05, 0xee);
-}
-
-static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate)
-{
-	u8 exponent;
-	u32 mantissa;
-
-	if (symbol_rate > 9360000)
-		return -EINVAL;
-
-	/*
-	 * FREF = 57800 kHz
-	 * exponent = 10 + floor (log2(symbol_rate / FREF))
-	 * mantissa = (symbol_rate / FREF) * (1 << (30 - exponent))
-	 */
-
-	exponent = __ilog2((symbol_rate << 4) / 903125);
-	mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289;
-
-	at76c651_writereg(state, 0x00, mantissa >> 13);
-	at76c651_writereg(state, 0x01, mantissa >> 5);
-	at76c651_writereg(state, 0x02, (mantissa << 3) | exponent);
-
-	return 0;
-}
-
-static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam)
-{
-	switch (qam) {
-	case QPSK:
-		state->qam = 0x02;
-		break;
-	case QAM_16:
-		state->qam = 0x04;
-		break;
-	case QAM_32:
-		state->qam = 0x05;
-		break;
-	case QAM_64:
-		state->qam = 0x06;
-		break;
-	case QAM_128:
-		state->qam = 0x07;
-		break;
-	case QAM_256:
-		state->qam = 0x08;
-		break;
-#if 0
-	case QAM_512:
-		state->qam = 0x09;
-		break;
-	case QAM_1024:
-		state->qam = 0x0A;
-		break;
-#endif
-	default:
-		return -EINVAL;
-
-	}
-
-	return at76c651_writereg(state, 0x03, state->qam);
-}
-
-static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion)
-{
-	u8 feciqinv = at76c651_readreg(state, 0x60);
-
-	switch (inversion) {
-	case INVERSION_OFF:
-		feciqinv |= 0x02;
-		feciqinv &= 0xFE;
-		break;
-
-	case INVERSION_ON:
-		feciqinv |= 0x03;
-		break;
-
-	case INVERSION_AUTO:
-		feciqinv &= 0xFC;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return at76c651_writereg(state, 0x60, feciqinv);
-}
-
-static int at76c651_set_parameters(struct dvb_frontend* fe,
-				   struct dvb_frontend_parameters *p)
-{
-	int ret;
-	struct at76c651_state* state = fe->demodulator_priv;
-
-	at76c651_writereg(state, 0x0c, 0xc3);
-	state->config->pll_set(fe, p);
-	at76c651_writereg(state, 0x0c, 0xc2);
-
-	if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate)))
-		return ret;
-
-	if ((ret = at76c651_set_inversion(state, p->inversion)))
-		return ret;
-
-	return at76c651_set_auto_config(state);
-}
-
-static int at76c651_set_defaults(struct dvb_frontend* fe)
-{
-	struct at76c651_state* state = fe->demodulator_priv;
-
-	at76c651_set_symbol_rate(state, 6900000);
-	at76c651_set_qam(state, QAM_64);
-	at76c651_set_bbfreq(state);
-	at76c651_set_auto_config(state);
-
-	if (state->config->pll_init) {
-		at76c651_writereg(state, 0x0c, 0xc3);
-		state->config->pll_init(fe);
-		at76c651_writereg(state, 0x0c, 0xc2);
-	}
-
-	return 0;
-}
-
-static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct at76c651_state* state = fe->demodulator_priv;
-	u8 sync;
-
-	/*
-	 * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0)
-	 */
-	sync = at76c651_readreg(state, 0x80);
-	*status = 0;
-
-	if (sync & (0x04 | 0x10))	/* AGC1 || TIM */
-		*status |= FE_HAS_SIGNAL;
-	if (sync & 0x10)		/* TIM */
-		*status |= FE_HAS_CARRIER;
-	if (sync & 0x80)		/* FEC */
-		*status |= FE_HAS_VITERBI;
-	if (sync & 0x40)		/* CAR */
-		*status |= FE_HAS_SYNC;
-	if ((sync & 0xF0) == 0xF0)	/* TIM && EQU && CAR && FEC */
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct at76c651_state* state = fe->demodulator_priv;
-
-	*ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16;
-	*ber |= at76c651_readreg(state, 0x82) << 8;
-	*ber |= at76c651_readreg(state, 0x83);
-	*ber *= 10;
-
-	return 0;
-}
-
-static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct at76c651_state* state = fe->demodulator_priv;
-
-	u8 gain = ~at76c651_readreg(state, 0x91);
-	*strength = (gain << 8) | gain;
-
-	return 0;
-}
-
-static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct at76c651_state* state = fe->demodulator_priv;
-
-	*snr = 0xFFFF -
-	    ((at76c651_readreg(state, 0x8F) << 8) |
-	     at76c651_readreg(state, 0x90));
-
-	return 0;
-}
-
-static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct at76c651_state* state = fe->demodulator_priv;
-
-	*ucblocks = at76c651_readreg(state, 0x82);
-
-	return 0;
-}
-
-static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings)
-{
-	fesettings->min_delay_ms = 50;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static void at76c651_release(struct dvb_frontend* fe)
-{
-	struct at76c651_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops at76c651_ops;
-
-struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
-				     struct i2c_adapter* i2c)
-{
-	struct at76c651_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->qam = 0;
-
-	/* check if the demod is there */
-	if (at76c651_readreg(state, 0x0e) != 0x65) goto error;
-
-	/* finalise state setup */
-	state->i2c = i2c;
-	state->revision = at76c651_readreg(state, 0x0f) & 0xfe;
-	memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops));
-
-	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops at76c651_ops = {
-
-	.info = {
-		.name = "Atmel AT76C651B DVB-C",
-		.type = FE_QAM,
-		.frequency_min = 48250000,
-		.frequency_max = 863250000,
-		.frequency_stepsize = 62500,
-		/*.frequency_tolerance = */	/* FIXME: 12% of SR */
-		.symbol_rate_min = 0,		/* FIXME */
-		.symbol_rate_max = 9360000,	/* FIXME */
-		.symbol_rate_tolerance = 4000,
-		.caps = FE_CAN_INVERSION_AUTO |
-		    FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-		    FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-		    FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-		    FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 |
-		    FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
-	},
-
-	.release = at76c651_release,
-
-	.init = at76c651_set_defaults,
-
-	.set_frontend = at76c651_set_parameters,
-	.get_tune_settings = at76c651_get_tune_settings,
-
-	.read_status = at76c651_read_status,
-	.read_ber = at76c651_read_ber,
-	.read_signal_strength = at76c651_read_signal_strength,
-	.read_snr = at76c651_read_snr,
-	.read_ucblocks = at76c651_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver");
-MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(at76c651_attach);
diff --git a/drivers/media/dvb/frontends/at76c651.h b/drivers/media/dvb/frontends/at76c651.h
deleted file mode 100644
index 34054df..0000000
--- a/drivers/media/dvb/frontends/at76c651.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * at76c651.c
- *
- * Atmel DVB-C Frontend Driver (at76c651)
- *
- * Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
- *             & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- *             & 2003 Wolfram Joost <dbox2@frokaschwei.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * AT76C651
- * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
- * http://www.atmel.com/atmel/acrobat/doc1320.pdf
- */
-
-#ifndef AT76C651_H
-#define AT76C651_H
-
-#include <linux/dvb/frontend.h>
-
-struct at76c651_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-};
-
-extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
-					    struct i2c_adapter* i2c);
-
-#endif // AT76C651_H
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 1b9934e..4dcb605 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -326,11 +326,11 @@
 };
 EXPORT_SYMBOL(dvb_pll_tuv1236d);
 
-/* Samsung TBMV30111IN
+/* Samsung TBMV30111IN / TBMV30712IN1
  * used in Air2PC ATSC - 2nd generation (nxt2002)
  */
-struct dvb_pll_desc dvb_pll_tbmv30111in = {
-	.name = "Samsung TBMV30111IN",
+struct dvb_pll_desc dvb_pll_samsung_tbmv = {
+	.name = "Samsung TBMV30111IN / TBMV30712IN1",
 	.min = 54000000,
 	.max = 860000000,
 	.count = 6,
@@ -343,7 +343,7 @@
 		{ 999999999, 44000000, 166666, 0xfc, 0x02 },
 	}
 };
-EXPORT_SYMBOL(dvb_pll_tbmv30111in);
+EXPORT_SYMBOL(dvb_pll_samsung_tbmv);
 
 /*
  * Philips SD1878 Tuner.
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index f682c09..bb8d4b4 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -38,7 +38,7 @@
 
 extern struct dvb_pll_desc dvb_pll_tuv1236d;
 extern struct dvb_pll_desc dvb_pll_tdhu2;
-extern struct dvb_pll_desc dvb_pll_tbmv30111in;
+extern struct dvb_pll_desc dvb_pll_samsung_tbmv;
 extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261;
 
 int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
deleted file mode 100644
index 4f263e6..0000000
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
-    Support for B2C2/BBTI Technisat Air2PC - ATSC
-
-    Copyright (C) 2004 Taylor Jacob <rtjacob@earthlink.net>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/*
- * This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware
- * or /lib/firmware (depending on configuration of firmware hotplug).
- */
-#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
-#define CRC_CCIT_MASK 0x1021
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "nxt2002.h"
-
-struct nxt2002_state {
-
-	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
-	const struct nxt2002_config* config;
-	struct dvb_frontend frontend;
-
-	/* demodulator private data */
-	u8 initialised:1;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "nxt2002: " args); \
-	} while (0)
-
-static int i2c_writebytes (struct nxt2002_state* state, u8 reg, u8 *buf, u8 len)
-{
-	/* probbably a much better way or doing this */
-	u8 buf2 [256],x;
-	int err;
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
-
-	buf2[0] = reg;
-	for (x = 0 ; x < len ; x++)
-		buf2[x+1] = buf[x];
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-		printk ("%s: i2c write error (addr %02x, err == %i)\n",
-			__FUNCTION__, state->config->demod_address, err);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static u8 i2c_readbytes (struct nxt2002_state* state, u8 reg, u8* buf, u8 len)
-{
-	u8 reg2 [] = { reg };
-
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },
-			{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
-
-	int err;
-
-	if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
-		printk ("%s: i2c read error (addr %02x, err == %i)\n",
-			__FUNCTION__, state->config->demod_address, err);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static u16 nxt2002_crc(u16 crc, u8 c)
-{
-
-	u8 i;
-	u16 input = (u16) c & 0xFF;
-
-	input<<=8;
-	for(i=0 ;i<8 ;i++) {
-		if((crc ^ input) & 0x8000)
-			crc=(crc<<1)^CRC_CCIT_MASK;
-		else
-			crc<<=1;
-	input<<=1;
-	}
-	return crc;
-}
-
-static int nxt2002_writereg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len)
-{
-	u8 buf;
-	dprintk("%s\n", __FUNCTION__);
-
-	/* set multi register length */
-	i2c_writebytes(state,0x34,&len,1);
-
-	/* set mutli register register */
-	i2c_writebytes(state,0x35,&reg,1);
-
-	/* send the actual data */
-	i2c_writebytes(state,0x36,data,len);
-
-	/* toggle the multireg write bit*/
-	buf = 0x02;
-	i2c_writebytes(state,0x21,&buf,1);
-
-	i2c_readbytes(state,0x21,&buf,1);
-
-	if ((buf & 0x02) == 0)
-		return 0;
-
-	dprintk("Error writing multireg register %02X\n",reg);
-
-	return 0;
-}
-
-static int nxt2002_readreg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len)
-{
-	u8 len2;
-	dprintk("%s\n", __FUNCTION__);
-
-	/* set multi register length */
-	len2 = len & 0x80;
-	i2c_writebytes(state,0x34,&len2,1);
-
-	/* set mutli register register */
-	i2c_writebytes(state,0x35,&reg,1);
-
-	/* send the actual data */
-	i2c_readbytes(state,reg,data,len);
-
-	return 0;
-}
-
-static void nxt2002_microcontroller_stop (struct nxt2002_state* state)
-{
-	u8 buf[2],counter = 0;
-	dprintk("%s\n", __FUNCTION__);
-
-	buf[0] = 0x80;
-	i2c_writebytes(state,0x22,buf,1);
-
-	while (counter < 20) {
-		i2c_readbytes(state,0x31,buf,1);
-		if (buf[0] & 0x40)
-			return;
-		msleep(10);
-		counter++;
-	}
-
-	dprintk("Timeout waiting for micro to stop.. This is ok after firmware upload\n");
-	return;
-}
-
-static void nxt2002_microcontroller_start (struct nxt2002_state* state)
-{
-	u8 buf;
-	dprintk("%s\n", __FUNCTION__);
-
-	buf = 0x00;
-	i2c_writebytes(state,0x22,&buf,1);
-}
-
-static int nxt2002_writetuner (struct nxt2002_state* state, u8* data)
-{
-	u8 buf,count = 0;
-
-	dprintk("Tuner Bytes: %02X %02X %02X %02X\n",data[0],data[1],data[2],data[3]);
-
-	dprintk("%s\n", __FUNCTION__);
-	/* stop the micro first */
-	nxt2002_microcontroller_stop(state);
-
-	/* set the i2c transfer speed to the tuner */
-	buf = 0x03;
-	i2c_writebytes(state,0x20,&buf,1);
-
-	/* setup to transfer 4 bytes via i2c */
-	buf = 0x04;
-	i2c_writebytes(state,0x34,&buf,1);
-
-	/* write actual tuner bytes */
-	i2c_writebytes(state,0x36,data,4);
-
-	/* set tuner i2c address */
-	buf = 0xC2;
-	i2c_writebytes(state,0x35,&buf,1);
-
-	/* write UC Opmode to begin transfer */
-	buf = 0x80;
-	i2c_writebytes(state,0x21,&buf,1);
-
-	while (count < 20) {
-		i2c_readbytes(state,0x21,&buf,1);
-		if ((buf & 0x80)== 0x00)
-			return 0;
-		msleep(100);
-		count++;
-	}
-
-	printk("nxt2002: timeout error writing tuner\n");
-	return 0;
-}
-
-static void nxt2002_agc_reset(struct nxt2002_state* state)
-{
-	u8 buf;
-	dprintk("%s\n", __FUNCTION__);
-
-	buf = 0x08;
-	i2c_writebytes(state,0x08,&buf,1);
-
-	buf = 0x00;
-	i2c_writebytes(state,0x08,&buf,1);
-
-	return;
-}
-
-static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
-{
-
-	struct nxt2002_state* state = fe->demodulator_priv;
-	u8 buf[256],written = 0,chunkpos = 0;
-	u16 rambase,position,crc = 0;
-
-	dprintk("%s\n", __FUNCTION__);
-	dprintk("Firmware is %zu bytes\n",fw->size);
-
-	/* Get the RAM base for this nxt2002 */
-	i2c_readbytes(state,0x10,buf,1);
-
-	if (buf[0] & 0x10)
-		rambase = 0x1000;
-	else
-		rambase = 0x0000;
-
-	dprintk("rambase on this nxt2002 is %04X\n",rambase);
-
-	/* Hold the micro in reset while loading firmware */
-	buf[0] = 0x80;
-	i2c_writebytes(state,0x2B,buf,1);
-
-	for (position = 0; position < fw->size ; position++) {
-		if (written == 0) {
-			crc = 0;
-			chunkpos = 0x28;
-			buf[0] = ((rambase + position) >> 8);
-			buf[1] = (rambase + position) & 0xFF;
-			buf[2] = 0x81;
-			/* write starting address */
-			i2c_writebytes(state,0x29,buf,3);
-		}
-		written++;
-		chunkpos++;
-
-		if ((written % 4) == 0)
-			i2c_writebytes(state,chunkpos,&fw->data[position-3],4);
-
-		crc = nxt2002_crc(crc,fw->data[position]);
-
-		if ((written == 255) || (position+1 == fw->size)) {
-			/* write remaining bytes of firmware */
-			i2c_writebytes(state, chunkpos+4-(written %4),
-				&fw->data[position-(written %4) + 1],
-				written %4);
-			buf[0] = crc << 8;
-			buf[1] = crc & 0xFF;
-
-			/* write crc */
-			i2c_writebytes(state,0x2C,buf,2);
-
-			/* do a read to stop things */
-			i2c_readbytes(state,0x2A,buf,1);
-
-			/* set transfer mode to complete */
-			buf[0] = 0x80;
-			i2c_writebytes(state,0x2B,buf,1);
-
-			written = 0;
-		}
-	}
-
-	printk ("done.\n");
-	return 0;
-};
-
-static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
-					     struct dvb_frontend_parameters *p)
-{
-	struct nxt2002_state* state = fe->demodulator_priv;
-	u32 freq = 0;
-	u16 tunerfreq = 0;
-	u8 buf[4];
-
-	freq = 44000 + ( p->frequency / 1000 );
-
-	dprintk("freq = %d      p->frequency = %d\n",freq,p->frequency);
-
-	tunerfreq = freq * 24/4000;
-
-	buf[0] = (tunerfreq >> 8) & 0x7F;
-	buf[1] = (tunerfreq & 0xFF);
-
-	if (p->frequency <= 214000000) {
-		buf[2] = 0x84 + (0x06 << 3);
-		buf[3] = (p->frequency <= 172000000) ? 0x01 : 0x02;
-	} else if (p->frequency <= 721000000) {
-		buf[2] = 0x84 + (0x07 << 3);
-		buf[3] = (p->frequency <= 467000000) ? 0x02 : 0x08;
-	} else if (p->frequency <= 841000000) {
-		buf[2] = 0x84 + (0x0E << 3);
-		buf[3] = 0x08;
-	} else {
-		buf[2] = 0x84 + (0x0F << 3);
-		buf[3] = 0x02;
-	}
-
-	/* write frequency information */
-	nxt2002_writetuner(state,buf);
-
-	/* reset the agc now that tuning has been completed */
-	nxt2002_agc_reset(state);
-
-	/* set target power level */
-	switch (p->u.vsb.modulation) {
-		case QAM_64:
-		case QAM_256:
-				buf[0] = 0x74;
-				break;
-		case VSB_8:
-				buf[0] = 0x70;
-				break;
-		default:
-				return -EINVAL;
-				break;
-	}
-	i2c_writebytes(state,0x42,buf,1);
-
-	/* configure sdm */
-	buf[0] = 0x87;
-	i2c_writebytes(state,0x57,buf,1);
-
-	/* write sdm1 input */
-	buf[0] = 0x10;
-	buf[1] = 0x00;
-	nxt2002_writereg_multibyte(state,0x58,buf,2);
-
-	/* write sdmx input */
-	switch (p->u.vsb.modulation) {
-		case QAM_64:
-				buf[0] = 0x68;
-				break;
-		case QAM_256:
-				buf[0] = 0x64;
-				break;
-		case VSB_8:
-				buf[0] = 0x60;
-				break;
-		default:
-				return -EINVAL;
-				break;
-	}
-	buf[1] = 0x00;
-	nxt2002_writereg_multibyte(state,0x5C,buf,2);
-
-	/* write adc power lpf fc */
-	buf[0] = 0x05;
-	i2c_writebytes(state,0x43,buf,1);
-
-	/* write adc power lpf fc */
-	buf[0] = 0x05;
-	i2c_writebytes(state,0x43,buf,1);
-
-	/* write accumulator2 input */
-	buf[0] = 0x80;
-	buf[1] = 0x00;
-	nxt2002_writereg_multibyte(state,0x4B,buf,2);
-
-	/* write kg1 */
-	buf[0] = 0x00;
-	i2c_writebytes(state,0x4D,buf,1);
-
-	/* write sdm12 lpf fc */
-	buf[0] = 0x44;
-	i2c_writebytes(state,0x55,buf,1);
-
-	/* write agc control reg */
-	buf[0] = 0x04;
-	i2c_writebytes(state,0x41,buf,1);
-
-	/* write agc ucgp0 */
-	switch (p->u.vsb.modulation) {
-		case QAM_64:
-				buf[0] = 0x02;
-				break;
-		case QAM_256:
-				buf[0] = 0x03;
-				break;
-		case VSB_8:
-				buf[0] = 0x00;
-				break;
-		default:
-				return -EINVAL;
-				break;
-	}
-	i2c_writebytes(state,0x30,buf,1);
-
-	/* write agc control reg */
-	buf[0] = 0x00;
-	i2c_writebytes(state,0x41,buf,1);
-
-	/* write accumulator2 input */
-	buf[0] = 0x80;
-	buf[1] = 0x00;
-	nxt2002_writereg_multibyte(state,0x49,buf,2);
-	nxt2002_writereg_multibyte(state,0x4B,buf,2);
-
-	/* write agc control reg */
-	buf[0] = 0x04;
-	i2c_writebytes(state,0x41,buf,1);
-
-	nxt2002_microcontroller_start(state);
-
-	/* adjacent channel detection should be done here, but I don't
-	have any stations with this need so I cannot test it */
-
-	return 0;
-}
-
-static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct nxt2002_state* state = fe->demodulator_priv;
-	u8 lock;
-	i2c_readbytes(state,0x31,&lock,1);
-
-	*status = 0;
-	if (lock & 0x20) {
-		*status |= FE_HAS_SIGNAL;
-		*status |= FE_HAS_CARRIER;
-		*status |= FE_HAS_VITERBI;
-		*status |= FE_HAS_SYNC;
-		*status |= FE_HAS_LOCK;
-	}
-	return 0;
-}
-
-static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct nxt2002_state* state = fe->demodulator_priv;
-	u8 b[3];
-
-	nxt2002_readreg_multibyte(state,0xE6,b,3);
-
-	*ber = ((b[0] << 8) + b[1]) * 8;
-
-	return 0;
-}
-
-static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct nxt2002_state* state = fe->demodulator_priv;
-	u8 b[2];
-	u16 temp = 0;
-
-	/* setup to read cluster variance */
-	b[0] = 0x00;
-	i2c_writebytes(state,0xA1,b,1);
-
-	/* get multreg val */
-	nxt2002_readreg_multibyte(state,0xA6,b,2);
-
-	temp = (b[0] << 8) | b[1];
-	*strength = ((0x7FFF - temp) & 0x0FFF) * 16;
-
-	return 0;
-}
-
-static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-
-	struct nxt2002_state* state = fe->demodulator_priv;
-	u8 b[2];
-	u16 temp = 0, temp2;
-	u32 snrdb = 0;
-
-	/* setup to read cluster variance */
-	b[0] = 0x00;
-	i2c_writebytes(state,0xA1,b,1);
-
-	/* get multreg val from 0xA6 */
-	nxt2002_readreg_multibyte(state,0xA6,b,2);
-
-	temp = (b[0] << 8) | b[1];
-	temp2 = 0x7FFF - temp;
-
-	/* snr will be in db */
-	if (temp2 > 0x7F00)
-		snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );
-	else if (temp2 > 0x7EC0)
-		snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );
-	else if (temp2 > 0x7C00)
-		snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );
-	else
-		snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );
-
-	/* the value reported back from the frontend will be FFFF=32db 0000=0db */
-
-	*snr = snrdb * (0xFFFF/32000);
-
-	return 0;
-}
-
-static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct nxt2002_state* state = fe->demodulator_priv;
-	u8 b[3];
-
-	nxt2002_readreg_multibyte(state,0xE6,b,3);
-	*ucblocks = b[2];
-
-	return 0;
-}
-
-static int nxt2002_sleep(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int nxt2002_init(struct dvb_frontend* fe)
-{
-	struct nxt2002_state* state = fe->demodulator_priv;
-	const struct firmware *fw;
-	int ret;
-	u8 buf[2];
-
-	if (!state->initialised) {
-		/* request the firmware, this will block until someone uploads it */
-		printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
-		ret = state->config->request_firmware(fe, &fw, NXT2002_DEFAULT_FIRMWARE);
-		printk("nxt2002: Waiting for firmware upload(2)...\n");
-		if (ret) {
-			printk("nxt2002: no firmware upload (timeout or file not found?)\n");
-			return ret;
-		}
-
-		ret = nxt2002_load_firmware(fe, fw);
-		if (ret) {
-			printk("nxt2002: writing firmware to device failed\n");
-			release_firmware(fw);
-			return ret;
-		}
-		printk("nxt2002: firmware upload complete\n");
-
-		/* Put the micro into reset */
-		nxt2002_microcontroller_stop(state);
-
-		/* ensure transfer is complete */
-		buf[0]=0;
-		i2c_writebytes(state,0x2B,buf,1);
-
-		/* Put the micro into reset for real this time */
-		nxt2002_microcontroller_stop(state);
-
-		/* soft reset everything (agc,frontend,eq,fec)*/
-		buf[0] = 0x0F;
-		i2c_writebytes(state,0x08,buf,1);
-		buf[0] = 0x00;
-		i2c_writebytes(state,0x08,buf,1);
-
-		/* write agc sdm configure */
-		buf[0] = 0xF1;
-		i2c_writebytes(state,0x57,buf,1);
-
-		/* write mod output format */
-		buf[0] = 0x20;
-		i2c_writebytes(state,0x09,buf,1);
-
-		/* write fec mpeg mode */
-		buf[0] = 0x7E;
-		buf[1] = 0x00;
-		i2c_writebytes(state,0xE9,buf,2);
-
-		/* write mux selection */
-		buf[0] = 0x00;
-		i2c_writebytes(state,0xCC,buf,1);
-
-		state->initialised = 1;
-	}
-
-	return 0;
-}
-
-static int nxt2002_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
-	fesettings->min_delay_ms = 500;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static void nxt2002_release(struct dvb_frontend* fe)
-{
-	struct nxt2002_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops nxt2002_ops;
-
-struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
-				   struct i2c_adapter* i2c)
-{
-	struct nxt2002_state* state = NULL;
-	u8 buf [] = {0,0,0,0,0};
-
-	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	memcpy(&state->ops, &nxt2002_ops, sizeof(struct dvb_frontend_ops));
-	state->initialised = 0;
-
-	/* Check the first 5 registers to ensure this a revision we can handle */
-
-	i2c_readbytes(state, 0x00, buf, 5);
-	if (buf[0] != 0x04) goto error;		/* device id */
-	if (buf[1] != 0x02) goto error;		/* fab id */
-	if (buf[2] != 0x11) goto error;		/* month */
-	if (buf[3] != 0x20) goto error;		/* year msb */
-	if (buf[4] != 0x00) goto error;		/* year lsb */
-
-	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops nxt2002_ops = {
-
-	.info = {
-		.name = "Nextwave nxt2002 VSB/QAM frontend",
-		.type = FE_ATSC,
-		.frequency_min =  54000000,
-		.frequency_max = 860000000,
-		/* stepsize is just a guess */
-		.frequency_stepsize = 166666,
-		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
-	},
-
-	.release = nxt2002_release,
-
-	.init = nxt2002_init,
-	.sleep = nxt2002_sleep,
-
-	.set_frontend = nxt2002_setup_frontend_parameters,
-	.get_tune_settings = nxt2002_get_tune_settings,
-
-	.read_status = nxt2002_read_status,
-	.read_ber = nxt2002_read_ber,
-	.read_signal_strength = nxt2002_read_signal_strength,
-	.read_snr = nxt2002_read_snr,
-	.read_ucblocks = nxt2002_read_ucblocks,
-
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("NXT2002 ATSC (8VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
-MODULE_AUTHOR("Taylor Jacob");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(nxt2002_attach);
diff --git a/drivers/media/dvb/frontends/nxt2002.h b/drivers/media/dvb/frontends/nxt2002.h
deleted file mode 100644
index 462301f..0000000
--- a/drivers/media/dvb/frontends/nxt2002.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-   Driver for the Nxt2002 demodulator
-*/
-
-#ifndef NXT2002_H
-#define NXT2002_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-struct nxt2002_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* request firmware for device */
-	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
-};
-
-extern struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
-					   struct i2c_adapter* i2c);
-
-#endif // NXT2002_H
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index 78d2b93..9e353539 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -1,9 +1,10 @@
 /*
  *    Support for NXT2002 and NXT2004 - VSB/QAM
  *
- *    Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com)
+ *    Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>
+ *    Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net>
  *    based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
- *    and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com)
+ *    and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.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
@@ -614,7 +615,17 @@
 	/* write sdm1 input */
 	buf[0] = 0x10;
 	buf[1] = 0x00;
-	nxt200x_writebytes(state, 0x58, buf, 2);
+	switch (state->demod_chip) {
+		case NXT2002:
+			nxt200x_writereg_multibyte(state, 0x58, buf, 2);
+			break;
+		case NXT2004:
+			nxt200x_writebytes(state, 0x58, buf, 2);
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
 
 	/* write sdmx input */
 	switch (p->u.vsb.modulation) {
@@ -632,7 +643,17 @@
 				break;
 	}
 	buf[1] = 0x00;
-	nxt200x_writebytes(state, 0x5C, buf, 2);
+	switch (state->demod_chip) {
+		case NXT2002:
+			nxt200x_writereg_multibyte(state, 0x5C, buf, 2);
+			break;
+		case NXT2004:
+			nxt200x_writebytes(state, 0x5C, buf, 2);
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
 
 	/* write adc power lpf fc */
 	buf[0] = 0x05;
@@ -648,7 +669,17 @@
 	/* write accumulator2 input */
 	buf[0] = 0x80;
 	buf[1] = 0x00;
-	nxt200x_writebytes(state, 0x4B, buf, 2);
+	switch (state->demod_chip) {
+		case NXT2002:
+			nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
+			break;
+		case NXT2004:
+			nxt200x_writebytes(state, 0x4B, buf, 2);
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
 
 	/* write kg1 */
 	buf[0] = 0x00;
@@ -714,8 +745,19 @@
 	/* write accumulator2 input */
 	buf[0] = 0x80;
 	buf[1] = 0x00;
-	nxt200x_writebytes(state, 0x49, buf,2);
-	nxt200x_writebytes(state, 0x4B, buf,2);
+	switch (state->demod_chip) {
+		case NXT2002:
+			nxt200x_writereg_multibyte(state, 0x49, buf, 2);
+			nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
+			break;
+		case NXT2004:
+			nxt200x_writebytes(state, 0x49, buf, 2);
+			nxt200x_writebytes(state, 0x4B, buf, 2);
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
 
 	/* write agc control reg */
 	buf[0] = 0x04;
@@ -1199,7 +1241,7 @@
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
 MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
-MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob");
+MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(nxt200x_attach);
diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c
deleted file mode 100644
index d1cabb6..0000000
--- a/drivers/media/dvb/frontends/tda80xx.c
+++ /dev/null
@@ -1,734 +0,0 @@
-/*
- * tda80xx.c
- *
- * Philips TDA8044 / TDA8083 QPSK demodulator driver
- *
- * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net>
- * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <asm/irq.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "tda80xx.h"
-
-enum {
-	ID_TDA8044 = 0x04,
-	ID_TDA8083 = 0x05,
-};
-
-
-struct tda80xx_state {
-
-	struct i2c_adapter* i2c;
-
-	struct dvb_frontend_ops ops;
-
-	/* configuration settings */
-	const struct tda80xx_config* config;
-
-	struct dvb_frontend frontend;
-
-	u32 clk;
-	int afc_loop;
-	struct work_struct worklet;
-	fe_code_rate_t code_rate;
-	fe_spectral_inversion_t spectral_inversion;
-	fe_status_t status;
-	u8 id;
-};
-
-static int debug = 1;
-#define dprintk	if (debug) printk
-
-static u8 tda8044_inittab_pre[] = {
-	0x02, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea,
-	0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x58,
-	0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68,
-	0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x00,
-	0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00
-};
-
-static u8 tda8044_inittab_post[] = {
-	0x04, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea,
-	0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x50,
-	0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68,
-	0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x6c,
-	0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00
-};
-
-static u8 tda8083_inittab[] = {
-	0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea,
-	0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10,
-	0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8,
-	0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00,
-	0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00
-};
-
-static __inline__ u32 tda80xx_div(u32 a, u32 b)
-{
-	return (a + (b / 2)) / b;
-}
-
-static __inline__ u32 tda80xx_gcd(u32 a, u32 b)
-{
-	u32 r;
-
-	while ((r = a % b)) {
-		a = b;
-		b = r;
-	}
-
-	return b;
-}
-
-static int tda80xx_read(struct tda80xx_state* state, u8 reg, u8 *buf, u8 len)
-{
-	int ret;
-	struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
-			  { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		dprintk("%s: readreg error (reg %02x, ret == %i)\n",
-				__FUNCTION__, reg, ret);
-
-	mdelay(10);
-
-	return (ret == 2) ? 0 : -EREMOTEIO;
-}
-
-static int tda80xx_write(struct tda80xx_state* state, u8 reg, const u8 *buf, u8 len)
-{
-	int ret;
-	u8 wbuf[len + 1];
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = wbuf, .len = len + 1 };
-
-	wbuf[0] = reg;
-	memcpy(&wbuf[1], buf, len);
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: i2c xfer error (ret == %i)\n", __FUNCTION__, ret);
-
-	mdelay(10);
-
-	return (ret == 1) ? 0 : -EREMOTEIO;
-}
-
-static __inline__ u8 tda80xx_readreg(struct tda80xx_state* state, u8 reg)
-{
-	u8 val;
-
-	tda80xx_read(state, reg, &val, 1);
-
-	return val;
-}
-
-static __inline__ int tda80xx_writereg(struct tda80xx_state* state, u8 reg, u8 data)
-{
-	return tda80xx_write(state, reg, &data, 1);
-}
-
-static int tda80xx_set_parameters(struct tda80xx_state* state,
-				  fe_spectral_inversion_t inversion,
-				  u32 symbol_rate,
-				  fe_code_rate_t fec_inner)
-{
-	u8 buf[15];
-	u64 ratio;
-	u32 clk;
-	u32 k;
-	u32 sr = symbol_rate;
-	u32 gcd;
-	u8 scd;
-
-	if (symbol_rate > (state->clk * 3) / 16)
-		scd = 0;
-	else if (symbol_rate > (state->clk * 3) / 32)
-		scd = 1;
-	else if (symbol_rate > (state->clk * 3) / 64)
-		scd = 2;
-	else
-		scd = 3;
-
-	clk = scd ? (state->clk / (scd * 2)) : state->clk;
-
-	/*
-	 * Viterbi decoder:
-	 * Differential decoding off
-	 * Spectral inversion unknown
-	 * QPSK modulation
-	 */
-	if (inversion == INVERSION_ON)
-		buf[0] = 0x60;
-	else if (inversion == INVERSION_OFF)
-		buf[0] = 0x20;
-	else
-		buf[0] = 0x00;
-
-	/*
-	 * CLK ratio:
-	 * system clock frequency is up to 64 or 96 MHz
-	 *
-	 * formula:
-	 * r = k * clk / symbol_rate
-	 *
-	 * k:	2^21 for caa 0..3,
-	 *	2^20 for caa 4..5,
-	 *	2^19 for caa 6..7
-	 */
-	if (symbol_rate <= (clk * 3) / 32)
-		k = (1 << 19);
-	else if (symbol_rate <= (clk * 3) / 16)
-		k = (1 << 20);
-	else
-		k = (1 << 21);
-
-	gcd = tda80xx_gcd(clk, sr);
-	clk /= gcd;
-	sr /= gcd;
-
-	gcd = tda80xx_gcd(k, sr);
-	k /= gcd;
-	sr /= gcd;
-
-	ratio = (u64)k * (u64)clk;
-	do_div(ratio, sr);
-
-	buf[1] = ratio >> 16;
-	buf[2] = ratio >> 8;
-	buf[3] = ratio;
-
-	/* nyquist filter roll-off factor 35% */
-	buf[4] = 0x20;
-
-	clk = scd ? (state->clk / (scd * 2)) : state->clk;
-
-	/* Anti Alias Filter */
-	if (symbol_rate < (clk * 3) / 64)
-		printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate);
-	else if (symbol_rate <= clk / 16)
-		buf[4] |= 0x07;
-	else if (symbol_rate <= (clk * 3) / 32)
-		buf[4] |= 0x06;
-	else if (symbol_rate <= clk / 8)
-		buf[4] |= 0x05;
-	else if (symbol_rate <= (clk * 3) / 16)
-		buf[4] |= 0x04;
-	else if (symbol_rate <= clk / 4)
-		buf[4] |= 0x03;
-	else if (symbol_rate <= (clk * 3) / 8)
-		buf[4] |= 0x02;
-	else if (symbol_rate <= clk / 2)
-		buf[4] |= 0x01;
-	else
-		buf[4] |= 0x00;
-
-	/* Sigma Delta converter */
-	buf[5] = 0x00;
-
-	/* FEC: Possible puncturing rates */
-	if (fec_inner == FEC_NONE)
-		buf[6] = 0x00;
-	else if ((fec_inner >= FEC_1_2) && (fec_inner <= FEC_8_9))
-		buf[6] = (1 << (8 - fec_inner));
-	else if (fec_inner == FEC_AUTO)
-		buf[6] = 0xff;
-	else
-		return -EINVAL;
-
-	/* carrier lock detector threshold value */
-	buf[7] = 0x30;
-	/* AFC1: proportional part settings */
-	buf[8] = 0x42;
-	/* AFC1: integral part settings */
-	buf[9] = 0x98;
-	/* PD: Leaky integrator SCPC mode */
-	buf[10] = 0x28;
-	/* AFC2, AFC1 controls */
-	buf[11] = 0x30;
-	/* PD: proportional part settings */
-	buf[12] = 0x42;
-	/* PD: integral part settings */
-	buf[13] = 0x99;
-	/* AGC */
-	buf[14] = 0x50 | scd;
-
-	printk("symbol_rate=%u clk=%u\n", symbol_rate, clk);
-
-	return tda80xx_write(state, 0x01, buf, sizeof(buf));
-}
-
-static int tda80xx_set_clk(struct tda80xx_state* state)
-{
-	u8 buf[2];
-
-	/* CLK proportional part */
-	buf[0] = (0x06 << 5) | 0x08;	/* CMP[2:0], CSP[4:0] */
-	/* CLK integral part */
-	buf[1] = (0x04 << 5) | 0x1a;	/* CMI[2:0], CSI[4:0] */
-
-	return tda80xx_write(state, 0x17, buf, sizeof(buf));
-}
-
-#if 0
-static int tda80xx_set_scpc_freq_offset(struct tda80xx_state* state)
-{
-	/* a constant value is nonsense here imho */
-	return tda80xx_writereg(state, 0x22, 0xf9);
-}
-#endif
-
-static int tda80xx_close_loop(struct tda80xx_state* state)
-{
-	u8 buf[2];
-
-	/* PD: Loop closed, LD: lock detect enable, SCPC: Sweep mode - AFC1 loop closed */
-	buf[0] = 0x68;
-	/* AFC1: Loop closed, CAR Feedback: 8192 */
-	buf[1] = 0x70;
-
-	return tda80xx_write(state, 0x0b, buf, sizeof(buf));
-}
-
-static irqreturn_t tda80xx_irq(int irq, void *priv, struct pt_regs *pt)
-{
-	schedule_work(priv);
-
-	return IRQ_HANDLED;
-}
-
-static void tda80xx_read_status_int(struct tda80xx_state* state)
-{
-	u8 val;
-
-	static const fe_spectral_inversion_t inv_tab[] = {
-		INVERSION_OFF, INVERSION_ON
-	};
-
-	static const fe_code_rate_t fec_tab[] = {
-		FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
-		FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8,
-	};
-
-	val = tda80xx_readreg(state, 0x02);
-
-	state->status = 0;
-
-	if (val & 0x01) /* demodulator lock */
-		state->status |= FE_HAS_SIGNAL;
-	if (val & 0x02) /* clock recovery lock */
-		state->status |= FE_HAS_CARRIER;
-	if (val & 0x04) /* viterbi lock */
-		state->status |= FE_HAS_VITERBI;
-	if (val & 0x08) /* deinterleaver lock (packet sync) */
-		state->status |= FE_HAS_SYNC;
-	if (val & 0x10) /* derandomizer lock (frame sync) */
-		state->status |= FE_HAS_LOCK;
-	if (val & 0x20) /* frontend can not lock */
-		state->status |= FE_TIMEDOUT;
-
-	if ((state->status & (FE_HAS_CARRIER)) && (state->afc_loop)) {
-		printk("tda80xx: closing loop\n");
-		tda80xx_close_loop(state);
-		state->afc_loop = 0;
-	}
-
-	if (state->status & (FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK)) {
-		val = tda80xx_readreg(state, 0x0e);
-		state->code_rate = fec_tab[val & 0x07];
-		if (state->status & (FE_HAS_SYNC | FE_HAS_LOCK))
-			state->spectral_inversion = inv_tab[(val >> 7) & 0x01];
-		else
-			state->spectral_inversion = INVERSION_AUTO;
-	}
-	else {
-		state->code_rate = FEC_AUTO;
-	}
-}
-
-static void tda80xx_worklet(void *priv)
-{
-	struct tda80xx_state *state = priv;
-
-	tda80xx_writereg(state, 0x00, 0x04);
-	enable_irq(state->config->irq);
-
-	tda80xx_read_status_int(state);
-}
-
-static void tda80xx_wait_diseqc_fifo(struct tda80xx_state* state)
-{
-	size_t i;
-
-	for (i = 0; i < 100; i++) {
-		if (tda80xx_readreg(state, 0x02) & 0x80)
-			break;
-		msleep(10);
-	}
-}
-
-static int tda8044_init(struct dvb_frontend* fe)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-	int ret;
-
-	/*
-	 * this function is a mess...
-	 */
-
-	if ((ret = tda80xx_write(state, 0x00, tda8044_inittab_pre, sizeof(tda8044_inittab_pre))))
-		return ret;
-
-	tda80xx_writereg(state, 0x0f, 0x50);
-#if 1
-	tda80xx_writereg(state, 0x20, 0x8F);		/* FIXME */
-	tda80xx_writereg(state, 0x20, state->config->volt18setting);	/* FIXME */
-	//tda80xx_writereg(state, 0x00, 0x04);
-	tda80xx_writereg(state, 0x00, 0x0C);
-#endif
-	//tda80xx_writereg(state, 0x00, 0x08); /* Reset AFC1 loop filter */
-
-	tda80xx_write(state, 0x00, tda8044_inittab_post, sizeof(tda8044_inittab_post));
-
-	if (state->config->pll_init) {
-		tda80xx_writereg(state, 0x1c, 0x80);
-		state->config->pll_init(fe);
-		tda80xx_writereg(state, 0x1c, 0x00);
-	}
-
-	return 0;
-}
-
-static int tda8083_init(struct dvb_frontend* fe)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab));
-
-	if (state->config->pll_init) {
-		tda80xx_writereg(state, 0x1c, 0x80);
-		state->config->pll_init(fe);
-		tda80xx_writereg(state, 0x1c, 0x00);
-	}
-
-	return 0;
-}
-
-static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		return tda80xx_writereg(state, 0x20, state->config->volt13setting);
-	case SEC_VOLTAGE_18:
-		return tda80xx_writereg(state, 0x20, state->config->volt18setting);
-	case SEC_VOLTAGE_OFF:
-		return tda80xx_writereg(state, 0x20, 0);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	switch (tone) {
-	case SEC_TONE_OFF:
-		return tda80xx_writereg(state, 0x29, 0x00);
-	case SEC_TONE_ON:
-		return tda80xx_writereg(state, 0x29, 0x80);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	if (cmd->msg_len > 6)
-		return -EINVAL;
-
-	tda80xx_writereg(state, 0x29, 0x08 | (cmd->msg_len - 3));
-	tda80xx_write(state, 0x23, cmd->msg, cmd->msg_len);
-	tda80xx_writereg(state, 0x29, 0x0c | (cmd->msg_len - 3));
-	tda80xx_wait_diseqc_fifo(state);
-
-	return 0;
-}
-
-static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t cmd)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	switch (cmd) {
-	case SEC_MINI_A:
-		tda80xx_writereg(state, 0x29, 0x14);
-		break;
-	case SEC_MINI_B:
-		tda80xx_writereg(state, 0x29, 0x1c);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	tda80xx_wait_diseqc_fifo(state);
-
-	return 0;
-}
-
-static int tda80xx_sleep(struct dvb_frontend* fe)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	tda80xx_writereg(state, 0x00, 0x02);	/* enter standby */
-
-	return 0;
-}
-
-static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	tda80xx_writereg(state, 0x1c, 0x80);
-	state->config->pll_set(fe, p);
-	tda80xx_writereg(state, 0x1c, 0x00);
-
-	tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner);
-	tda80xx_set_clk(state);
-	//tda80xx_set_scpc_freq_offset(state);
-	state->afc_loop = 1;
-
-	return 0;
-}
-
-static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	if (!state->config->irq)
-		tda80xx_read_status_int(state);
-
-	p->inversion = state->spectral_inversion;
-	p->u.qpsk.fec_inner = state->code_rate;
-
-	return 0;
-}
-
-static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	if (!state->config->irq)
-		tda80xx_read_status_int(state);
-	*status = state->status;
-
-	return 0;
-}
-
-static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-	int ret;
-	u8 buf[3];
-
-	if ((ret = tda80xx_read(state, 0x0b, buf, sizeof(buf))))
-		return ret;
-
-	*ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
-
-	return 0;
-}
-
-static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	u8 gain = ~tda80xx_readreg(state, 0x01);
-	*strength = (gain << 8) | gain;
-
-	return 0;
-}
-
-static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	u8 quality = tda80xx_readreg(state, 0x08);
-	*snr = (quality << 8) | quality;
-
-	return 0;
-}
-
-static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	*ucblocks = tda80xx_readreg(state, 0x0f);
-	if (*ucblocks == 0xff)
-		*ucblocks = 0xffffffff;
-
-	return 0;
-}
-
-static int tda80xx_init(struct dvb_frontend* fe)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	switch(state->id) {
-	case ID_TDA8044:
-		return tda8044_init(fe);
-
-	case ID_TDA8083:
-		return tda8083_init(fe);
-	}
-	return 0;
-}
-
-static void tda80xx_release(struct dvb_frontend* fe)
-{
-	struct tda80xx_state* state = fe->demodulator_priv;
-
-	if (state->config->irq)
-		free_irq(state->config->irq, &state->worklet);
-
-	kfree(state);
-}
-
-static struct dvb_frontend_ops tda80xx_ops;
-
-struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
-				    struct i2c_adapter* i2c)
-{
-	struct tda80xx_state* state = NULL;
-	int ret;
-
-	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	memcpy(&state->ops, &tda80xx_ops, sizeof(struct dvb_frontend_ops));
-	state->spectral_inversion = INVERSION_AUTO;
-	state->code_rate = FEC_AUTO;
-	state->status = 0;
-	state->afc_loop = 0;
-
-	/* check if the demod is there */
-	if (tda80xx_writereg(state, 0x89, 0x00) < 0) goto error;
-	state->id = tda80xx_readreg(state, 0x00);
-
-	switch (state->id) {
-	case ID_TDA8044:
-		state->clk = 96000000;
-		printk("tda80xx: Detected tda8044\n");
-		break;
-
-	case ID_TDA8083:
-		state->clk = 64000000;
-		printk("tda80xx: Detected tda8083\n");
-		break;
-
-	default:
-		goto error;
-	}
-
-	/* setup IRQ */
-	if (state->config->irq) {
-		INIT_WORK(&state->worklet, tda80xx_worklet, state);
-		if ((ret = request_irq(state->config->irq, tda80xx_irq, SA_ONESHOT, "tda80xx", &state->worklet)) < 0) {
-			printk(KERN_ERR "tda80xx: request_irq failed (%d)\n", ret);
-			goto error;
-		}
-	}
-
-	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops tda80xx_ops = {
-
-	.info = {
-		.name = "Philips TDA80xx DVB-S",
-		.type = FE_QPSK,
-		.frequency_min = 500000,
-		.frequency_max = 2700000,
-		.frequency_stepsize = 125,
-		.symbol_rate_min = 4500000,
-		.symbol_rate_max = 45000000,
-		.caps =	FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK |
-			FE_CAN_MUTE_TS
-	},
-
-	.release = tda80xx_release,
-
-	.init = tda80xx_init,
-	.sleep = tda80xx_sleep,
-
-	.set_frontend = tda80xx_set_frontend,
-	.get_frontend = tda80xx_get_frontend,
-
-	.read_status = tda80xx_read_status,
-	.read_ber = tda80xx_read_ber,
-	.read_signal_strength = tda80xx_read_signal_strength,
-	.read_snr = tda80xx_read_snr,
-	.read_ucblocks = tda80xx_read_ucblocks,
-
-	.diseqc_send_master_cmd = tda80xx_send_diseqc_msg,
-	.diseqc_send_burst = tda80xx_send_diseqc_burst,
-	.set_tone = tda80xx_set_tone,
-	.set_voltage = tda80xx_set_voltage,
-};
-
-module_param(debug, int, 0644);
-
-MODULE_DESCRIPTION("Philips TDA8044 / TDA8083 DVB-S Demodulator driver");
-MODULE_AUTHOR("Felix Domke, Andreas Oberritter");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(tda80xx_attach);
diff --git a/drivers/media/dvb/frontends/tda80xx.h b/drivers/media/dvb/frontends/tda80xx.h
deleted file mode 100644
index cd639a0..0000000
--- a/drivers/media/dvb/frontends/tda80xx.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * tda80xx.c
- *
- * Philips TDA8044 / TDA8083 QPSK demodulator driver
- *
- * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net>
- * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef TDA80XX_H
-#define TDA80XX_H
-
-#include <linux/dvb/frontend.h>
-
-struct tda80xx_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* IRQ to use (0=>no IRQ used) */
-	u32 irq;
-
-	/* Register setting to use for 13v */
-	u8 volt13setting;
-
-	/* Register setting to use for 18v */
-	u8 volt18setting;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-};
-
-extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
-					   struct i2c_adapter* i2c);
-
-#endif // TDA80XX_H
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 2749490..d36369e 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -2329,6 +2329,17 @@
 			av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
 			break;
 
+		case 0x0004: // Galaxis DVB-S rev1.3
+			/* ALPS BSRV2 */
+			av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
+			if (av7110->fe) {
+				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
+				av7110->fe->ops->set_tone = av7110_set_tone;
+				av7110->recover = dvb_s_recover;
+			}
+			break;
+
 		case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
 			/* Grundig 29504-451 */
 			av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
@@ -2930,6 +2941,7 @@
 MAKE_AV7110_INFO(ttt,        "Technotrend/Hauppauge DVB-T");
 MAKE_AV7110_INFO(fsc,        "Fujitsu Siemens DVB-C");
 MAKE_AV7110_INFO(fss,        "Fujitsu Siemens DVB-S rev1.6");
+MAKE_AV7110_INFO(gxs_1_3,    "Galaxis DVB-S rev1.3");
 
 static struct pci_device_id pci_tbl[] = {
 	MAKE_EXTENSION_PCI(fsc,         0x110a, 0x0000),
@@ -2937,13 +2949,13 @@
 	MAKE_EXTENSION_PCI(ttt_1_X,     0x13c2, 0x0001),
 	MAKE_EXTENSION_PCI(ttc_2_X,     0x13c2, 0x0002),
 	MAKE_EXTENSION_PCI(tts_2_X,     0x13c2, 0x0003),
+	MAKE_EXTENSION_PCI(gxs_1_3,     0x13c2, 0x0004),
 	MAKE_EXTENSION_PCI(fss,         0x13c2, 0x0006),
 	MAKE_EXTENSION_PCI(ttt,         0x13c2, 0x0008),
 	MAKE_EXTENSION_PCI(ttc_1_X,     0x13c2, 0x000a),
 	MAKE_EXTENSION_PCI(tts_2_3,     0x13c2, 0x000e),
 	MAKE_EXTENSION_PCI(tts_1_3se,   0x13c2, 0x1002),
 
-/*	MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
 /*	MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
 /*	MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
 
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 6ea30df..fafd25f 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -273,8 +273,6 @@
 extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
 		       u16 subpid, u16 pcrpid);
 
-extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
-
 extern int av7110_ir_init(struct av7110 *av7110);
 extern void av7110_ir_exit(struct av7110 *av7110);
 
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 9138132..617e4f6 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -155,6 +155,19 @@
 }
 
 
+static int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
+{
+	int ret = 0;
+
+	dprintk(4, "%p\n", av7110);
+	if (av7110) {
+		ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
+		av7110->ir_config = ir_config;
+	}
+	return ret;
+}
+
+
 static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
 				unsigned long count, void *data)
 {
@@ -187,19 +200,6 @@
 }
 
 
-int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
-{
-	int ret = 0;
-
-	dprintk(4, "%p\n", av7110);
-	if (av7110) {
-		ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
-		av7110->ir_config = ir_config;
-	}
-	return ret;
-}
-
-
 static void ir_handler(struct av7110 *av7110, u32 ircom)
 {
 	dprintk(4, "ircommand = %08x\n", ircom);
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index aa4c4c5..578b200 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -214,7 +214,7 @@
 		   we can capture, of the first and second field. */
 		.vbistart	= { 7,320 },
 	},{
-		.v4l2_id        = V4L2_STD_NTSC_M,
+		.v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
 		.name           = "NTSC",
 		.Fsc            = 28636363,
 		.swidth         = 768,
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index 297c32a..840fe01 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -167,29 +167,32 @@
 	if (kp->clipcount > 2048)
 		return -EINVAL;
 	if (kp->clipcount) {
-		struct v4l2_clip32 *uclips = compat_ptr(up->clips);
-		struct v4l2_clip *kclips;
+		struct v4l2_clip32 __user *uclips;
+		struct v4l2_clip __user *kclips;
 		int n = kp->clipcount;
+		compat_caddr_t p;
 
+		if (get_user(p, &up->clips))
+			return -EFAULT;
+		uclips = compat_ptr(p);
 		kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
 		kp->clips = kclips;
 		while (--n >= 0) {
-			if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) ||
-				copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+			if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
 				return -EFAULT;
-			kclips->next = n ? kclips + 1 : 0;
+			if (put_user(n ? kclips + 1 : NULL, &kclips->next))
+				return -EFAULT;
 			uclips += 1;
 			kclips += 1;
 		}
 	} else
-		kp->clips = 0;
+		kp->clips = NULL;
 	return 0;
 }
 
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) ||
-		copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
+	if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
 		put_user(kp->field, &up->field) ||
 		put_user(kp->chromakey, &up->chromakey) ||
 		put_user(kp->clipcount, &up->clipcount))
@@ -199,33 +202,29 @@
 
 static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) ||
-		copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
-			return -EFAULT;
+	if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
+		return -EFAULT;
 	return 0;
 }
 
 static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) ||
-		copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
-			return -EFAULT;
+	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
+		return -EFAULT;
 	return 0;
 }
 
 static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) ||
-		copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
-			return -EFAULT;
+	if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
+		return -EFAULT;
 	return 0;
 }
 
 static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) ||
-		copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
-			return -EFAULT;
+	if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -279,18 +278,16 @@
 
 static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) ||
-		copy_from_user(kp, up, sizeof(struct v4l2_standard)))
-			return -EFAULT;
+	if (copy_from_user(kp, up, sizeof(struct v4l2_standard)))
+		return -EFAULT;
 	return 0;
 
 }
 
 static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) ||
-		copy_to_user(up, kp, sizeof(struct v4l2_standard)))
-			return -EFAULT;
+	if (copy_to_user(up, kp, sizeof(struct v4l2_standard)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -328,18 +325,16 @@
 
 static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) ||
-		copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
-			return -EFAULT;
+	if (copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
+		return -EFAULT;
 	return 0;
 
 }
 
 static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) ||
-		copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
-			return -EFAULT;
+	if (copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -380,11 +375,13 @@
 		break;
 	case V4L2_MEMORY_USERPTR:
 		{
-		unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr);
+		compat_long_t tmp;
 
-		if(get_user(kp->length, &up->length) ||
-			get_user(kp->m.userptr, &tmp))
-				return -EFAULT;
+		if (get_user(kp->length, &up->length) ||
+		    get_user(tmp, &up->m.userptr))
+			return -EFAULT;
+
+		kp->m.userptr = (unsigned long)compat_ptr(tmp);
 		}
 		break;
 	case V4L2_MEMORY_OVERLAY:
@@ -468,33 +465,29 @@
 
 static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) ||
-		copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
-			return -EFAULT;
+	if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
+		return -EFAULT;
 	return 0;
 }
 
 static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) ||
-		copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
-			return -EFAULT;
+	if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
+		return -EFAULT;
 	return 0;
 }
 
 static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) ||
-		copy_from_user(kp, up, sizeof(struct v4l2_input)))
-			return -EFAULT;
+	if (copy_from_user(kp, up, sizeof(struct v4l2_input)))
+		return -EFAULT;
 	return 0;
 }
 
 static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) ||
-		copy_to_user(up, kp, sizeof(struct v4l2_input)))
-			return -EFAULT;
+	if (copy_to_user(up, kp, sizeof(struct v4l2_input)))
+		return -EFAULT;
 	return 0;
 }
 
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index c66c2c1..08ffd1f 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -220,33 +220,23 @@
 		cx25840_write(client, 0x808, 0xff);
 		cx25840_write(client, 0x80b, 0x10);
 	} else if (std & V4L2_STD_NTSC) {
-		/* NTSC */
-		if (state->pvr150_workaround) {
-			/* Certain Hauppauge PVR150 models have a hardware bug
-			   that causes audio to drop out. For these models the
-			   audio standard must be set explicitly.
-			   To be precise: it affects cards with tuner models
-			   85, 99 and 112 (model numbers from tveeprom). */
-			if (std == V4L2_STD_NTSC_M_JP) {
-				/* Japan uses EIAJ audio standard */
-				cx25840_write(client, 0x808, 0x2f);
-			} else {
-				/* Others use the BTSC audio standard */
-				cx25840_write(client, 0x808, 0x1f);
-			}
-			/* South Korea uses the A2-M (aka Zweiton M) audio
-			   standard, and should set 0x808 to 0x3f, but I don't
-			   know how to detect this. */
-		} else if (std == V4L2_STD_NTSC_M_JP) {
+		/* Certain Hauppauge PVR150 models have a hardware bug
+		   that causes audio to drop out. For these models the
+		   audio standard must be set explicitly.
+		   To be precise: it affects cards with tuner models
+		   85, 99 and 112 (model numbers from tveeprom). */
+		int hw_fix = state->pvr150_workaround;
+
+		if (std == V4L2_STD_NTSC_M_JP) {
 			/* Japan uses EIAJ audio standard */
-			cx25840_write(client, 0x808, 0xf7);
+			cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7);
+		} else if (std == V4L2_STD_NTSC_M_KR) {
+			/* South Korea uses A2 audio standard */
+			cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8);
 		} else {
 			/* Others use the BTSC audio standard */
-			cx25840_write(client, 0x808, 0xf6);
+			cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
 		}
-		/* South Korea uses the A2-M (aka Zweiton M) audio standard,
-		   and should set 0x808 to 0xf8, but I don't know how to
-		   detect this. */
 		cx25840_write(client, 0x80b, 0x00);
 	}
 
@@ -330,17 +320,17 @@
 	u8 fmt=0; 	/* zero is autodetect */
 
 	/* First tests should be against specific std */
-	if (std & V4L2_STD_NTSC_M_JP) {
+	if (std == V4L2_STD_NTSC_M_JP) {
 		fmt=0x2;
-	} else if (std & V4L2_STD_NTSC_443) {
+	} else if (std == V4L2_STD_NTSC_443) {
 		fmt=0x3;
-	} else if (std & V4L2_STD_PAL_M) {
+	} else if (std == V4L2_STD_PAL_M) {
 		fmt=0x5;
-	} else if (std & V4L2_STD_PAL_N) {
+	} else if (std == V4L2_STD_PAL_N) {
 		fmt=0x6;
-	} else if (std & V4L2_STD_PAL_Nc) {
+	} else if (std == V4L2_STD_PAL_Nc) {
 		fmt=0x7;
-	} else if (std & V4L2_STD_PAL_60) {
+	} else if (std == V4L2_STD_PAL_60) {
 		fmt=0x8;
 	} else {
 		/* Then, test against generic ones */
@@ -369,7 +359,7 @@
 	}
 
 	switch (fmt) {
-	case 0x1: return V4L2_STD_NTSC_M;
+	case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR;
 	case 0x2: return V4L2_STD_NTSC_M_JP;
 	case 0x3: return V4L2_STD_NTSC_443;
 	case 0x4: return V4L2_STD_PAL;
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 5330891..e99dfbb 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -32,6 +32,7 @@
 config VIDEO_CX88_ALSA
 	tristate "ALSA DMA audio support"
 	depends on VIDEO_CX88 && SND && EXPERIMENTAL
+	select SND_PCM
 	---help---
 	  This is a video4linux driver for direct (DMA) audio on
 	  Conexant 2388x based TV cards.
@@ -48,6 +49,7 @@
 	default y
 	depends on VIDEO_CX88_DVB
 	select DVB_MT352
+	select VIDEO_CX88_VP3054
 	select DVB_OR51132
 	select DVB_CX22702
 	select DVB_LGDT330X
@@ -69,6 +71,16 @@
 	  This adds DVB-T support for cards based on the
 	  Connexant 2388x chip and the MT352 demodulator.
 
+config VIDEO_CX88_VP3054
+	tristate "VP-3054 Secondary I2C Bus Support"
+	default m
+	depends on DVB_MT352
+	---help---
+	  This adds DVB-T support for cards based on the
+	  Connexant 2388x chip and the MT352 demodulator,
+	  which also require support for the VP-3054
+	  Secondary I2C bus, such at DNTV Live! DVB-T Pro.
+
 config VIDEO_CX88_DVB_OR51132
 	bool "OR51132 ATSC Support"
 	default y
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 6e5eaa2..2b90278 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -4,8 +4,9 @@
 cx8802-objs	:= cx88-mpeg.o
 
 obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
-obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o
+obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
 obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
+obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
 
 EXTRA_CFLAGS += -I$(src)/..
 EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
@@ -18,6 +19,6 @@
 extra-cflags-$(CONFIG_DVB_MT352)     += -DHAVE_MT352=1
 extra-cflags-$(CONFIG_DVB_NXT200X)   += -DHAVE_NXT200X=1
 extra-cflags-$(CONFIG_DVB_CX24123)   += -DHAVE_CX24123=1
-extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1
+extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1
 
 EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index a2e36a1..2acccd6 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -128,7 +128,7 @@
  * BOARD Specific: Sets audio DMA
  */
 
-int _cx88_start_audio_dma(snd_cx88_card_t *chip)
+static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
 {
 	struct cx88_buffer   *buf = chip->buf;
 	struct cx88_core *core=chip->core;
@@ -173,7 +173,7 @@
 /*
  * BOARD Specific: Resets audio DMA
  */
-int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
+static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
 {
 	struct cx88_core *core=chip->core;
 	dprintk(1, "Stopping audio DMA\n");
@@ -613,7 +613,7 @@
  * Only boards with eeprom and byte 1 at eeprom=1 have it
  */
 
-struct pci_device_id cx88_audio_pci_tbl[] = {
+static struct pci_device_id cx88_audio_pci_tbl[] = {
 	{0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
 	{0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
 	{0, }
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index ad2f565..1bc9992 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1246,6 +1246,11 @@
 		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
 	},{
 		.subvendor = 0x18ac,
+		.subdevice = 0xdb54,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+		/* Re-branded DViCO: DigitalNow DVB-T Dual */
+	},{
+		.subvendor = 0x18ac,
 		.subdevice = 0xdb11,
 		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
 		/* Re-branded DViCO: UltraView DVB-T Plus */
@@ -1293,6 +1298,7 @@
 	switch (tv.model)
 	{
 	case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
+	case 34519: /* WinTV-PCI-FM */
 	case 90002: /* Nova-T-PCI (9002) */
 	case 92001: /* Nova-S-Plus (Video and IR) */
 	case 92002: /* Nova-S-Plus (Video and IR) */
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 8d6d6a6..3720f24 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -787,12 +787,14 @@
 
 int cx88_start_audio_dma(struct cx88_core *core)
 {
+	/* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
+	int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
 	/* setup fifo + format */
-	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
-	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
 
-	cx_write(MO_AUDD_LNGTH,    128); /* fifo bpl size */
-	cx_write(MO_AUDR_LNGTH,    128); /* fifo bpl size */
+	cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
+	cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */
 
 	/* start dma */
 	cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index da2ad5c..165d948 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -482,6 +482,7 @@
 	switch (core->board) {
 	case CX88_BOARD_DNTV_LIVE_DVB_T:
 	case CX88_BOARD_KWORLD_DVB_T:
+	case CX88_BOARD_KWORLD_DVB_T_CX22702:
 		ir_codes = ir_codes_dntv_live_dvb_t;
 		ir->gpio_addr = MO_GP1_IO;
 		ir->mask_keycode = 0x1f;
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index dff3893..e5ee8bc 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -139,6 +139,9 @@
 {
 	int ret, byte;
 
+	if (dev->state & DEV_DISCONNECTED)
+		return(-ENODEV);
+
 	em28xx_regdbg("req=%02x, reg=%02x ", req, reg);
 
 	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
@@ -165,6 +168,9 @@
 	u8 val;
 	int ret;
 
+	if (dev->state & DEV_DISCONNECTED)
+		return(-ENODEV);
+
 	em28xx_regdbg("req=%02x, reg=%02x:", req, reg);
 
 	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
@@ -195,7 +201,12 @@
 	int ret;
 
 	/*usb_control_msg seems to expect a kmalloced buffer */
-	unsigned char *bufs = kmalloc(len, GFP_KERNEL);
+	unsigned char *bufs;
+
+	if (dev->state & DEV_DISCONNECTED)
+		return(-ENODEV);
+
+	bufs = kmalloc(len, GFP_KERNEL);
 
 	em28xx_regdbg("req=%02x reg=%02x:", req, reg);
 
@@ -212,7 +223,7 @@
 	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0x0000, reg, bufs, len, HZ);
-	mdelay(5);		/* FIXME: magic number */
+	msleep(5);		/* FIXME: magic number */
 	kfree(bufs);
 	return ret;
 }
@@ -253,7 +264,7 @@
 	if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
 		return ret;
 	else if (((u8) ret) & 0x01) {
-		em28xx_warn ("AC97 command still being exectuted: not handled properly!\n");
+		em28xx_warn ("AC97 command still being executed: not handled properly!\n");
 	}
 	return 0;
 }
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 0591a70..6ca8631 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -78,7 +78,7 @@
 		ret = dev->em28xx_read_reg(dev, 0x05);
 		if (ret == 0x80 + len - 1)
 			return len;
-		mdelay(5);
+		msleep(5);
 	}
 	em28xx_warn("i2c write timed out\n");
 	return -EIO;
@@ -138,7 +138,7 @@
 			return -ENODEV;
 		else if (msg == 0x84)
 			return 0;
-		mdelay(5);
+		msleep(5);
 	}
 	return -ENODEV;
 }
@@ -278,9 +278,9 @@
 							   msgs[i].buf,
 							   msgs[i].len,
 							   i == num - 1);
-			if (rc < 0)
-				goto err;
 		}
+		if (rc < 0)
+			goto err;
 		if (i2c_debug>=2)
 			printk("\n");
 	}
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index eea304f..94a14a2 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -6,6 +6,9 @@
 		      Mauro Carvalho Chehab <mchehab@brturbo.com.br>
 		      Sascha Sommer <saschasommer@freenet.de>
 
+	Some parts based on SN9C10x PC Camera Controllers GPL driver made
+		by Luca Risolia <luca.risolia@studio.unibo.it>
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
index 0b6c209..aad4a18 100644
--- a/drivers/media/video/hexium_orion.c
+++ b/drivers/media/video/hexium_orion.c
@@ -484,7 +484,7 @@
 };
 
 static struct saa7146_extension extension = {
-	.name = "hexium HV-PCI6/Orion",
+	.name = "hexium HV-PCI6 Orion",
 	.flags = 0,		// SAA7146_USE_I2C_IRQ,
 
 	.pci_tbl = &pci_tbl[0],
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index c64718a..5a35d3b 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -136,7 +136,7 @@
 	},
 	[SAA7134_BOARD_FLYVIDEO2000] = {
 		/* "TC Wan" <tcwan@cs.usm.my> */
-		.name           = "LifeView FlyVIDEO2000",
+		.name           = "LifeView/Typhoon FlyVIDEO2000",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
 		.radio_type     = UNSET,
@@ -1884,44 +1884,38 @@
 			.gpio = 0x000,
 		},
 	},
-	[SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS] = {
-		.name		= "Typhoon DVB-T Duo Digital/Analog Cardbus",
+	[SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = {
+		.name		= "LifeView/Typhoon FlyDVB-T Duo Cardbus",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_TDA8290,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
 		.mpeg           = SAA7134_MPEG_DVB,
-		/* .gpiomask       = 0xe000, */
+		.gpiomask	= 0x00200000,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
 			.amux = TV,
-		/*	.gpio = 0x0000,      */
+			.gpio = 0x200000,	/* GPIO21=High for TV input */
 			.tv   = 1,
 		},{
-			.name = name_comp1,	/* Composite signal on S-Video input */
-			.vmux = 0,
-			.amux = LINE2,
-		/*	.gpio = 0x4000,      */
-		},{
-			.name = name_comp2,	/* Composite input */
-			.vmux = 3,
-			.amux = LINE2,
-		/*	.gpio = 0x4000,      */
-		},{
 			.name = name_svideo,	/* S-Video signal on S-Video input */
 			.vmux = 8,
 			.amux = LINE2,
-		/*	.gpio = 0x4000,      */
+		},{
+			.name = name_comp1,	/* Composite signal on S-Video input */
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
 		}},
 		.radio = {
 			.name = name_radio,
-			.amux = LINE2,
-		},
-		.mute = {
-			.name = name_mute,
-			.amux = LINE1,
+			.amux = TV,
+			.gpio = 0x000000,	/* GPIO21=Low for FM radio antenna */
 		},
 	},
 	[SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = {
@@ -2701,6 +2695,12 @@
 		.driver_data  = SAA7134_BOARD_FLYVIDEO2000,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x4e42,		/* Typhoon */
+		.subdevice    = 0x0138,		/* LifeView FlyTV Prime30 OEM */
+		.driver_data  = SAA7134_BOARD_FLYVIDEO2000,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x5168,
 		.subdevice    = 0x0212, /* minipci, LR212 */
@@ -2935,7 +2935,7 @@
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x5168,
 		.subdevice    = 0x0502,                /* Cardbus version */
-		.driver_data  = SAA7134_BOARD_FLYDVBTDUO,
+		.driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -2980,12 +2980,12 @@
 		.subdevice    = 0x1370,        /* cardbus version */
 		.driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
 
-	},{     /* Typhoon DVB-T Duo Digital/Analog Cardbus */
+	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-		.subvendor    = 0x4e42,
-		.subdevice    = 0x0502,
-		.driver_data  = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS,
+		.subvendor    = 0x4e42,		/* Typhoon */
+		.subdevice    = 0x0502,		/* LifeView LR502 OEM */
+		.driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -3206,8 +3206,7 @@
 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00040000, 0x00040000);
 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004);
 		break;
-	case SAA7134_BOARD_FLYDVBTDUO:
-	case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS:
+	case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
 		/* turn the fan on */
 		saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
 		saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 399f995..1a536e86 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -861,7 +861,7 @@
 		dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
 						    &dev->i2c_adap);
 		break;
-	case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS:
+	case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
 		dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
 						    &dev->i2c_adap);
 		break;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index e70eae8..3261d8b 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -185,7 +185,7 @@
 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
 #define SAA7134_BOARD_ADS_INSTANT_TV 58
 #define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
-#define SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS 60
+#define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60
 #define SAA7134_BOARD_PHILIPS_TOUGH 61
 #define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
 #define SAA7134_BOARD_KWORLD_XPERT 63
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 54fc330..9d76926 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -2012,7 +2012,6 @@
 {
 	struct saa7146 *saa = pci_get_drvdata(pdev);
 
-	memset(saa, 0, sizeof(*saa));
 	saa->user = 0;
 	/* reset the saa7146 */
 	saawrite(0xffff0000, SAA7146_MC1);
@@ -2062,16 +2061,16 @@
 	}
 	if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
 		dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
-		goto errvid;
+		goto errfree;
 	}
 	if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
 		dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
-		goto erraud;
+		goto errfree;
 	}
 	/* allocate 81920 byte buffer for clipping */
 	if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
 		dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
-		goto errosd;
+		goto errfree;
 	}
 	/* setup clipping registers */
 	saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
@@ -2085,15 +2084,11 @@
 	I2CBusScan(saa);
 
 	return 0;
-errosd:
+errfree:
 	vfree(saa->osdbuf);
-	saa->osdbuf = NULL;
-erraud:
 	vfree(saa->audbuf);
-	saa->audbuf = NULL;
-errvid:
 	vfree(saa->vidbuf);
-	saa->vidbuf = NULL;
+	saa->audbuf = saa->osdbuf = saa->vidbuf = NULL;
 err:
 	return -ENOMEM;
 }
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 5815649..0d54f6c 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -231,7 +231,7 @@
 			   cAudioIF_6_5   |
 			   cVideoIF_38_90 ),
 	},{
-		.std   = V4L2_STD_NTSC_M,
+		.std   = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
 		.name  = "NTSC-M",
 		.b     = ( cNegativeFmTV  |
 			   cQSS           ),
@@ -619,6 +619,11 @@
 			tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
 			t->std = V4L2_STD_NTSC_M_JP;
 			break;
+		case 'k':
+		case 'K':
+			tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
+			t->std = V4L2_STD_NTSC_M_KR;
+			break;
 		case '-':
 			/* default parameter, do nothing */
 			break;
@@ -876,7 +881,7 @@
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver driver = {
-	.id             = -1, /* FIXME */
+	.id             = I2C_DRIVERID_TDA9887,
 	.attach_adapter = tda9887_probe,
 	.detach_client  = tda9887_detach,
 	.command        = tda9887_command,
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 2995b22..e7ee619 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -216,6 +216,7 @@
 		buffer[3] = 0xa4;
 		i2c_master_send(c,buffer,4);
 		default_tuner_init(c);
+		break;
 	default:
 		default_tuner_init(c);
 		break;
@@ -365,6 +366,11 @@
 			tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
 			t->std = V4L2_STD_NTSC_M_JP;
 			break;
+		case 'k':
+		case 'K':
+			tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
+			t->std = V4L2_STD_NTSC_M_KR;
+			break;
 		case '-':
 			/* default parameter, do nothing */
 			break;
@@ -448,7 +454,7 @@
 			printk("%02x ",buffer[i]);
 		printk("\n");
 	}
-	/* TEA5767 autodetection code - only for addr = 0xc0 */
+	/* autodetection code based on the i2c addr */
 	if (!no_autodetect) {
 		switch (addr) {
 		case 0x42:
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 6d03b9b..c8e5ad0 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -390,6 +390,14 @@
 		chip_write(chip, TDA9840_SW, t);
 }
 
+static int tda9840_checkit(struct CHIPSTATE *chip)
+{
+	int rc;
+	rc = chip_read(chip);
+	/* lower 5 bits should be 0 */
+	return ((rc & 0x1f) == 0) ? 1 : 0;
+}
+
 /* ---------------------------------------------------------------------- */
 /* audio chip descriptions - defines+functions for tda985x                */
 
@@ -1264,6 +1272,7 @@
 		.addr_hi    = I2C_TDA9840 >> 1,
 		.registers  = 5,
 
+		.checkit    = tda9840_checkit,
 		.getmode    = tda9840_getmode,
 		.setmode    = tda9840_setmode,
 		.checkmode  = generic_checkmode,
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index fad9ea0..1864423 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -746,24 +746,27 @@
 
 static inline void tvp5150_reset(struct i2c_client *c)
 {
-	u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom;
+	u8 msb_id, lsb_id, msb_rom, lsb_rom;
 	struct tvp5150 *decoder = i2c_get_clientdata(c);
 
-	type=tvp5150_read(c,TVP5150_AUTOSW_MSK);
 	msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID);
 	lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID);
 	msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER);
 	lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER);
 
-	if (type==0xdc) {
-		ver_656=tvp5150_read(c,TVP5150_REV_SELECT);
-		tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656);
-	} else if (type==0xfc) {
-		tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id);
+	if ((msb_rom==4)&&(lsb_rom==0)) { /* Is TVP5150AM1 */
+		tvp5150_info("tvp%02x%02xam1 detected.\n",msb_id, lsb_id);
+
+		/* ITU-T BT.656.4 timing */
+		tvp5150_write(c,TVP5150_REV_SELECT,0);
 	} else {
-		tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type);
+		if ((msb_rom==3)||(lsb_rom==0x21)) { /* Is TVP5150A */
+			tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id);
+		} else {
+			tvp5150_info("*** unknown tvp%02x%02x chip detected.\n",msb_id,lsb_id);
+			tvp5150_info("*** Rom ver is %d.%d\n",msb_rom,lsb_rom);
+		}
 	}
-	tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom);
 
 	/* Initializes TVP5150 to its default values */
 	tvp5150_write_inittab(c, tvp5150_init_default);
@@ -893,6 +896,17 @@
 		}
 	case DECODER_GET_STATUS:
 		{
+			int *iarg = arg;
+			int status;
+			int res=0;
+			status = tvp5150_read(c, 0x88);
+			if(status&0x08){
+				res |= DECODER_STATUS_COLOR;
+			}
+			if(status&0x04 && status&0x02){
+				res |= DECODER_STATUS_GOOD;
+			}
+			*iarg=res;
 			break;
 		}
 
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index 8a2e265..33ace37 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -29,6 +29,8 @@
 #  For mptctl:
 #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
 #
+#  For mptfc:
+#CFLAGS_mptfc.o += -DMPT_DEBUG_FC
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
 
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index d890b2b..9a2c760 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -81,6 +81,10 @@
 /*
  *  cmd line parameters
  */
+static int mpt_msi_enable;
+module_param(mpt_msi_enable, int, 0);
+MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+
 #ifdef MFCNT
 static int mfcounter = 0;
 #define PRINT_MF_COUNT 20000
@@ -174,7 +178,7 @@
 static int	ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
 static void	mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
 static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
-static void	mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static void	mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
 
 /* module entry point */
@@ -313,7 +317,7 @@
 		if (ioc->bus_type == FC)
 			mpt_fc_log_info(ioc, log_info);
 		else if (ioc->bus_type == SPI)
-			mpt_sp_log_info(ioc, log_info);
+			mpt_spi_log_info(ioc, log_info);
 		else if (ioc->bus_type == SAS)
 			mpt_sas_log_info(ioc, log_info);
 	}
@@ -1444,6 +1448,9 @@
 
 	ioc->pci_irq = -1;
 	if (pdev->irq) {
+		if (mpt_msi_enable && !pci_enable_msi(pdev))
+			printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name);
+
 		r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
 
 		if (r < 0) {
@@ -1483,6 +1490,10 @@
 
 		list_del(&ioc->list);
 		free_irq(ioc->pci_irq, ioc);
+		if (mpt_msi_enable)
+			pci_disable_msi(pdev);
+		if (ioc->alt_ioc)
+			ioc->alt_ioc->alt_ioc = NULL;
 		iounmap(mem);
 		kfree(ioc);
 		pci_set_drvdata(pdev, NULL);
@@ -2136,6 +2147,8 @@
 
 	if (ioc->pci_irq != -1) {
 		free_irq(ioc->pci_irq, ioc);
+		if (mpt_msi_enable)
+			pci_disable_msi(ioc->pcidev);
 		ioc->pci_irq = -1;
 	}
 
@@ -2157,6 +2170,10 @@
 	sz_last = ioc->alloc_total;
 	dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
 			ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+
+	if (ioc->alt_ioc)
+		ioc->alt_ioc->alt_ioc = NULL;
+
 	kfree(ioc);
 }
 
@@ -2770,13 +2787,16 @@
 
 	/* RAID FW may take a long time to enable
 	 */
-	if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
-			> MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) {
-		rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
-				reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
+	if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+	    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
+	    (ioc->bus_type == SAS)) {
+		rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+		(u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+		300 /*seconds*/, sleepFlag);
 	} else {
-		rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
-				reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag);
+		rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+		(u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+		30 /*seconds*/, sleepFlag);
 	}
 	return rc;
 }
@@ -4387,6 +4407,138 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+static void
+mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
+    MpiEventDataRaid_t * pRaidEventData)
+{
+	int 	volume;
+	int 	reason;
+	int 	disk;
+	int 	status;
+	int 	flags;
+	int 	state;
+
+	volume	= pRaidEventData->VolumeID;
+	reason	= pRaidEventData->ReasonCode;
+	disk	= pRaidEventData->PhysDiskNum;
+	status	= le32_to_cpu(pRaidEventData->SettingsStatus);
+	flags	= (status >> 0) & 0xff;
+	state	= (status >> 8) & 0xff;
+
+	if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
+		return;
+	}
+
+	if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
+	     reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
+	    (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
+		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
+			ioc->name, disk);
+	} else {
+		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
+			ioc->name, volume);
+	}
+
+	switch(reason) {
+	case MPI_EVENT_RAID_RC_VOLUME_CREATED:
+		printk(MYIOC_s_INFO_FMT "  volume has been created\n",
+			ioc->name);
+		break;
+
+	case MPI_EVENT_RAID_RC_VOLUME_DELETED:
+
+		printk(MYIOC_s_INFO_FMT "  volume has been deleted\n",
+			ioc->name);
+		break;
+
+	case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
+		printk(MYIOC_s_INFO_FMT "  volume settings have been changed\n",
+			ioc->name);
+		break;
+
+	case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
+		printk(MYIOC_s_INFO_FMT "  volume is now %s%s%s%s\n",
+			ioc->name,
+			state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
+			 ? "optimal"
+			 : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
+			  ? "degraded"
+			  : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
+			   ? "failed"
+			   : "state unknown",
+			flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
+			 ? ", enabled" : "",
+			flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
+			 ? ", quiesced" : "",
+			flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
+			 ? ", resync in progress" : "" );
+		break;
+
+	case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
+		printk(MYIOC_s_INFO_FMT "  volume membership of PhysDisk %d has changed\n",
+			ioc->name, disk);
+		break;
+
+	case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+		printk(MYIOC_s_INFO_FMT "  PhysDisk has been created\n",
+			ioc->name);
+		break;
+
+	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+		printk(MYIOC_s_INFO_FMT "  PhysDisk has been deleted\n",
+			ioc->name);
+		break;
+
+	case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
+		printk(MYIOC_s_INFO_FMT "  PhysDisk settings have been changed\n",
+			ioc->name);
+		break;
+
+	case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
+		printk(MYIOC_s_INFO_FMT "  PhysDisk is now %s%s%s\n",
+			ioc->name,
+			state == MPI_PHYSDISK0_STATUS_ONLINE
+			 ? "online"
+			 : state == MPI_PHYSDISK0_STATUS_MISSING
+			  ? "missing"
+			  : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
+			   ? "not compatible"
+			   : state == MPI_PHYSDISK0_STATUS_FAILED
+			    ? "failed"
+			    : state == MPI_PHYSDISK0_STATUS_INITIALIZING
+			     ? "initializing"
+			     : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
+			      ? "offline requested"
+			      : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
+			       ? "failed requested"
+			       : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
+			        ? "offline"
+			        : "state unknown",
+			flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
+			 ? ", out of sync" : "",
+			flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
+			 ? ", quiesced" : "" );
+		break;
+
+	case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
+		printk(MYIOC_s_INFO_FMT "  Domain Validation needed for PhysDisk %d\n",
+			ioc->name, disk);
+		break;
+
+	case MPI_EVENT_RAID_RC_SMART_DATA:
+		printk(MYIOC_s_INFO_FMT "  SMART data received, ASC/ASCQ = %02xh/%02xh\n",
+			ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
+		break;
+
+	case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
+		printk(MYIOC_s_INFO_FMT "  replacement of PhysDisk %d has started\n",
+			ioc->name, disk);
+		break;
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	GetIoUnitPage2 - Retrieve BIOS version and boot order information.
  *	@ioc: Pointer to MPT_ADAPTER structure
@@ -4598,6 +4750,14 @@
 				SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
 				MpiDeviceInfo_t	*pdevice = NULL;
 
+				/*
+				 * Save "Set to Avoid SCSI Bus Resets" flag
+				 */
+				ioc->spi_data.bus_reset =
+				    (le32_to_cpu(pPP2->PortFlags) &
+			        MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
+				    0 : 1 ;
+
 				/* Save the Port Page 2 data
 				 * (reformat into a 32bit quantity)
 				 */
@@ -5967,6 +6127,10 @@
 			}
 		}
 		break;
+	case MPI_EVENT_INTEGRATED_RAID:
+		mptbase_raid_process_event_data(ioc,
+		    (MpiEventDataRaid_t *)pEventReply->Data);
+		break;
 	default:
 		break;
 	}
@@ -6046,7 +6210,7 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
+ *	mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@mr: Pointer to MPT reply frame
  *	@log_info: U32 LogInfo word from the IOC
@@ -6054,7 +6218,7 @@
  *	Refer to lsi/sp_log.h.
  */
 static void
-mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
+mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
 {
 	u32 info = log_info & 0x00FF0000;
 	char *desc = "unknown";
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 47053ac..ea2649e 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.03.06"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.06"
+#define MPT_LINUX_VERSION_COMMON	"3.03.07"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.07"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -123,7 +123,7 @@
 #define  MPT_MAX_FRAME_SIZE		128
 #define  MPT_DEFAULT_FRAME_SIZE		128
 
-#define  MPT_REPLY_FRAME_SIZE		0x40  /* Must be a multiple of 8 */
+#define  MPT_REPLY_FRAME_SIZE		0x50  /* Must be a multiple of 8 */
 
 #define  MPT_SG_REQ_128_SCALE		1
 #define  MPT_SG_REQ_96_SCALE		2
@@ -510,9 +510,10 @@
 {
 	struct list_head list;
 	struct fc_rport *rport;
-	VirtDevice	*vdev;
+	struct scsi_target *starget;
 	FCDevicePage0_t pg0;
 	u8		flags;
+	u8		remap_needed;
 };
 
 /*
@@ -631,6 +632,7 @@
 	struct mutex		 sas_topology_mutex;
 	MPT_SAS_MGMT		 sas_mgmt;
 	int			 num_ports;
+	struct work_struct	 mptscsih_persistTask;
 
 	struct list_head	 fc_rports;
 	spinlock_t		 fc_rport_lock; /* list and ri flags */
@@ -803,6 +805,12 @@
 #define dreplyprintk(x)
 #endif
 
+#ifdef DMPT_DEBUG_FC
+#define dfcprintk(x) printk x
+#else
+#define dfcprintk(x)
+#endif
+
 #ifdef MPT_DEBUG_TM
 #define dtmprintk(x) printk x
 #define DBG_DUMP_TM_REQUEST_FRAME(mfp) \
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index b102c76..c3a3499 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -93,10 +93,11 @@
 static int	mptfcTaskCtx = -1;
 static int	mptfcInternalCtx = -1; /* Used only for internal commands */
 
-int mptfc_slave_alloc(struct scsi_device *device);
+static int mptfc_target_alloc(struct scsi_target *starget);
+static int mptfc_slave_alloc(struct scsi_device *sdev);
 static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
-    void (*done)(struct scsi_cmnd *));
-
+		      void (*done)(struct scsi_cmnd *));
+static void mptfc_target_destroy(struct scsi_target *starget);
 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
 static void __devexit mptfc_remove(struct pci_dev *pdev);
 
@@ -107,10 +108,10 @@
 	.name				= "MPT FC Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptfc_qcmd,
-	.target_alloc			= mptscsih_target_alloc,
+	.target_alloc			= mptfc_target_alloc,
 	.slave_alloc			= mptfc_slave_alloc,
 	.slave_configure		= mptscsih_slave_configure,
-	.target_destroy			= mptscsih_target_destroy,
+	.target_destroy			= mptfc_target_destroy,
 	.slave_destroy			= mptscsih_slave_destroy,
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
@@ -348,14 +349,33 @@
 }
 
 static void
+mptfc_remap_sdev(struct scsi_device *sdev, void *arg)
+{
+	VirtDevice		*vdev;
+	VirtTarget		*vtarget;
+	struct scsi_target	*starget;
+
+	starget = scsi_target(sdev);
+	if (starget->hostdata == arg) {
+		vtarget = arg;
+		vdev = sdev->hostdata;
+		if (vdev) {
+			vdev->bus_id = vtarget->bus_id;
+			vdev->target_id = vtarget->target_id;
+		}
+	}
+}
+
+static void
 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 {
 	struct fc_rport_identifiers rport_ids;
 	struct fc_rport		*rport;
 	struct mptfc_rport_info	*ri;
-	int			match = 0;
-	u64			port_name;
+	int			new_ri = 1;
+	u64			pn;
 	unsigned long		flags;
+	VirtTarget		*vtarget;
 
 	if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
 		return;
@@ -363,14 +383,14 @@
 	/* scan list looking for a match */
 	spin_lock_irqsave(&ioc->fc_rport_lock, flags);
 	list_for_each_entry(ri, &ioc->fc_rports, list) {
-		port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
-		if (port_name == rport_ids.port_name) {	/* match */
+		pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+		if (pn == rport_ids.port_name) {	/* match */
 			list_move_tail(&ri->list, &ioc->fc_rports);
-			match = 1;
+			new_ri = 0;
 			break;
 		}
 	}
-	if (!match) {	/* allocate one */
+	if (new_ri) {	/* allocate one */
 		spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
 		ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
 		if (!ri)
@@ -382,40 +402,43 @@
 	ri->pg0 = *pg0;	/* add/update pg0 data */
 	ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
 
+	/* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
 	if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
 		ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
 		spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
-		rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
+		rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
 		spin_lock_irqsave(&ioc->fc_rport_lock, flags);
 		if (rport) {
-			if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
-				ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
-				ri->vdev = NULL;
-				ri->rport = rport;
-				*((struct mptfc_rport_info **)rport->dd_data) = ri;
-			}
-			rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+			ri->rport = rport;
+			if (new_ri) /* may have been reset by user */
+				rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+			*((struct mptfc_rport_info **)rport->dd_data) = ri;
 			/*
 			 * if already mapped, remap here.  If not mapped,
-			 * slave_alloc will allocate vdev and map
+			 * target_alloc will allocate vtarget and map,
+			 * slave_alloc will fill in vdev from vtarget.
 			 */
-			if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
-				ri->vdev->target_id = ri->pg0.CurrentTargetID;
-				ri->vdev->bus_id = ri->pg0.CurrentBus;
-				ri->vdev->vtarget->target_id = ri->vdev->target_id;
-				ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
+			if (ri->starget) {
+				vtarget = ri->starget->hostdata;
+				if (vtarget) {
+					vtarget->target_id = pg0->CurrentTargetID;
+					vtarget->bus_id = pg0->CurrentBus;
+					starget_for_each_device(ri->starget,
+						vtarget,mptfc_remap_sdev);
+				}
+				ri->remap_needed = 0;
 			}
-			#ifdef MPT_DEBUG
-			printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
+			dfcprintk ((MYIOC_s_INFO_FMT
+				"mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
 				"rport tid %d, tmo %d\n",
-					ioc->sh->host_no,
+					ioc->name,
+					oc->sh->host_no,
 					pg0->PortIdentifier,
 					pg0->WWNN,
 					pg0->WWPN,
 					pg0->CurrentTargetID,
 					ri->rport->scsi_target_id,
-					ri->rport->dev_loss_tmo);
-			#endif
+					ri->rport->dev_loss_tmo));
 		} else {
 			list_del(&ri->list);
 			kfree(ri);
@@ -427,6 +450,65 @@
 }
 
 /*
+ *	OS entry point to allow for host driver to free allocated memory
+ *	Called if no device present or device being unloaded
+ */
+static void
+mptfc_target_destroy(struct scsi_target *starget)
+{
+	struct fc_rport		*rport;
+	struct mptfc_rport_info *ri;
+
+	rport = starget_to_rport(starget);
+	if (rport) {
+		ri = *((struct mptfc_rport_info **)rport->dd_data);
+		if (ri)	/* better be! */
+			ri->starget = NULL;
+	}
+	if (starget->hostdata)
+		kfree(starget->hostdata);
+	starget->hostdata = NULL;
+}
+
+/*
+ *	OS entry point to allow host driver to alloc memory
+ *	for each scsi target. Called once per device the bus scan.
+ *	Return non-zero if allocation fails.
+ */
+static int
+mptfc_target_alloc(struct scsi_target *starget)
+{
+	VirtTarget		*vtarget;
+	struct fc_rport		*rport;
+	struct mptfc_rport_info *ri;
+	int			rc;
+
+	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+	if (!vtarget)
+		return -ENOMEM;
+	starget->hostdata = vtarget;
+
+	rc = -ENODEV;
+	rport = starget_to_rport(starget);
+	if (rport) {
+		ri = *((struct mptfc_rport_info **)rport->dd_data);
+		if (ri) {	/* better be! */
+			vtarget->target_id = ri->pg0.CurrentTargetID;
+			vtarget->bus_id = ri->pg0.CurrentBus;
+			ri->starget = starget;
+			ri->remap_needed = 0;
+			rc = 0;
+		}
+	}
+	if (rc != 0) {
+		kfree(vtarget);
+		starget->hostdata = NULL;
+	}
+
+	return rc;
+}
+
+/*
  *	OS entry point to allow host driver to alloc memory
  *	for each scsi device. Called once per device the bus scan.
  *	Return non-zero if allocation fails.
@@ -440,7 +522,6 @@
 	VirtDevice		*vdev;
 	struct scsi_target	*starget;
 	struct fc_rport		*rport;
-	struct mptfc_rport_info *ri;
 	unsigned long		flags;
 
 
@@ -451,55 +532,44 @@
 
 	hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
 
-	vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
 	if (!vdev) {
 		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
 				hd->ioc->name, sizeof(VirtDevice));
 		return -ENOMEM;
 	}
-	memset(vdev, 0, sizeof(VirtDevice));
 
 	spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
 
-	if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
-		spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
-		kfree(vdev);
-		return -ENODEV;
-	}
-
 	sdev->hostdata = vdev;
 	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
+
 	if (vtarget->num_luns == 0) {
+		vtarget->ioc_id = hd->ioc->id;
 		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
 		    		  MPT_TARGET_FLAGS_VALID_INQUIRY;
 		hd->Targets[sdev->id] = vtarget;
 	}
 
-	vtarget->target_id = vdev->target_id;
-	vtarget->bus_id = vdev->bus_id;
-
 	vdev->vtarget = vtarget;
 	vdev->ioc_id = hd->ioc->id;
 	vdev->lun = sdev->lun;
-	vdev->target_id = ri->pg0.CurrentTargetID;
-	vdev->bus_id = ri->pg0.CurrentBus;
-
-	ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
-	ri->vdev = vdev;
+	vdev->target_id = vtarget->target_id;
+	vdev->bus_id = vtarget->bus_id;
 
 	spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
 
 	vtarget->num_luns++;
 
-#ifdef MPT_DEBUG
-	printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
+	dfcprintk ((MYIOC_s_INFO_FMT
+		"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
 	        "CurrentTargetID %d, %x %llx %llx\n",
-			sdev->host->host_no,
-			vtarget->num_luns,
-			sdev->id, ri->pg0.CurrentTargetID,
-			ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
-#endif
+		ioc->name,
+		sdev->host->host_no,
+		vtarget->num_luns,
+		sdev->id, ri->pg0.CurrentTargetID,
+		ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
 
 	return 0;
 }
@@ -507,6 +577,7 @@
 static int
 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
+	struct mptfc_rport_info	*ri;
 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
 	int		err;
 
@@ -516,6 +587,10 @@
 		done(SCpnt);
 		return 0;
 	}
+	ri = *((struct mptfc_rport_info **)rport->dd_data);
+	if (unlikely(ri->remap_needed))
+		return SCSI_MLQUEUE_HOST_BUSY;
+
 	return mptscsih_qcmd(SCpnt,done);
 }
 
@@ -591,16 +666,20 @@
 
 				ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
 					       MPT_RPORT_INFO_FLAGS_MISSING);
+				ri->remap_needed = 1;
 				fc_remote_port_delete(ri->rport);
 				/*
 				 * remote port not really deleted 'cause
 				 * binding is by WWPN and driver only
-				 * registers FCP_TARGETs
+				 * registers FCP_TARGETs but cannot trust
+				 * data structures.
 				 */
-				#ifdef MPT_DEBUG
-				printk ("mptfc_rescan.%d: %llx deleted\n",
-					ioc->sh->host_no, ri->pg0.WWPN);
-				#endif
+				ri->rport = NULL;
+				dfcprintk ((MYIOC_s_INFO_FMT
+					"mptfc_rescan.%d: %llx deleted\n",
+					ioc->name,
+					ioc->sh->host_no,
+					ri->pg0.WWPN));
 			}
 		}
 		spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
@@ -872,9 +951,8 @@
 	}
 
 	error = pci_register_driver(&mptfc_driver);
-	if (error) {
+	if (error)
 		fc_release_transport(mptfc_transport_template);
-	}
 
 	return error;
 }
@@ -885,7 +963,8 @@
  *	@pdev: Pointer to pci_dev structure
  *
  */
-static void __devexit mptfc_remove(struct pci_dev *pdev)
+static void __devexit
+mptfc_remove(struct pci_dev *pdev)
 {
 	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 	struct mptfc_rport_info *p, *n;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 5a06d8d..2512d0e 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -89,6 +89,8 @@
 enum mptsas_hotplug_action {
 	MPTSAS_ADD_DEVICE,
 	MPTSAS_DEL_DEVICE,
+	MPTSAS_ADD_RAID,
+	MPTSAS_DEL_RAID,
 };
 
 struct mptsas_hotplug_event {
@@ -114,6 +116,7 @@
 
 struct mptsas_devinfo {
 	u16	handle;		/* unique id to address this device */
+	u16	handle_parent;	/* unique id to address parent device */
 	u8	phy_id;		/* phy number of parent device */
 	u8	port_id;	/* sas physical port this device
 				   is assoc'd with */
@@ -301,9 +304,8 @@
 	}
 	mutex_unlock(&hd->ioc->sas_topology_mutex);
 
-	printk("No matching SAS device found!!\n");
 	kfree(vdev);
-	return -ENODEV;
+	return -ENXIO;
 
  out:
 	vtarget->ioc_id = vdev->ioc_id;
@@ -321,6 +323,7 @@
 	struct sas_rphy *rphy;
 	struct mptsas_portinfo *p;
 	int i;
+	VirtDevice *vdev;
 
 	/*
 	 * Handle hotplug removal case.
@@ -344,8 +347,29 @@
  out:
 	mutex_unlock(&hd->ioc->sas_topology_mutex);
 	/*
-	 * TODO: Issue target reset to flush firmware outstanding commands.
+	 * Issue target reset to flush firmware outstanding commands.
 	 */
+	vdev = sdev->hostdata;
+	if (vdev->configured_lun){
+		if (mptscsih_TMHandler(hd,
+		     MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+		     vdev->bus_id,
+		     vdev->target_id,
+		     0, 0, 5 /* 5 second timeout */)
+		     < 0){
+
+			/* The TM request failed!
+			 * Fatal error case.
+			 */
+			printk(MYIOC_s_WARN_FMT
+		       "Error processing TaskMgmt id=%d TARGET_RESET\n",
+				hd->ioc->name,
+				vdev->target_id);
+
+			hd->tmPending = 0;
+			hd->tmState = TM_STATE_NONE;
+		}
+	}
 	mptscsih_slave_destroy(sdev);
 }
 
@@ -714,6 +738,7 @@
 	mptsas_print_device_pg0(buffer);
 
 	device_info->handle = le16_to_cpu(buffer->DevHandle);
+	device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
 	device_info->phy_id = buffer->PhyNum;
 	device_info->port_id = buffer->PhysicalPort;
 	device_info->id = buffer->TargetID;
@@ -863,6 +888,26 @@
 	return error;
 }
 
+/*
+ * Returns true if there is a scsi end device
+ */
+static inline int
+mptsas_is_end_device(struct mptsas_devinfo * attached)
+{
+	if ((attached->handle) &&
+	    (attached->device_info &
+	    MPI_SAS_DEVICE_INFO_END_DEVICE) &&
+	    ((attached->device_info &
+	    MPI_SAS_DEVICE_INFO_SSP_TARGET) |
+	    (attached->device_info &
+	    MPI_SAS_DEVICE_INFO_STP_TARGET) |
+	    (attached->device_info &
+	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
+		return 1;
+	else
+		return 0;
+}
+
 static void
 mptsas_parse_device_info(struct sas_identify *identify,
 		struct mptsas_devinfo *device_info)
@@ -1227,7 +1272,7 @@
 }
 
 static struct mptsas_phyinfo *
-mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
+mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
 {
 	struct mptsas_portinfo *port_info;
 	struct mptsas_phyinfo *phy_info = NULL;
@@ -1239,12 +1284,12 @@
 	 */
 	mutex_lock(&ioc->sas_topology_mutex);
 	list_for_each_entry(port_info, &ioc->sas_topology, list) {
-		for (i = 0; i < port_info->num_phys; i++) {
-			if (port_info->phy_info[i].attached.handle == handle) {
-				phy_info = &port_info->phy_info[i];
-				break;
-			}
-		}
+		for (i = 0; i < port_info->num_phys; i++)
+			if (mptsas_is_end_device(&port_info->phy_info[i].attached))
+				if (port_info->phy_info[i].attached.id == id) {
+					phy_info = &port_info->phy_info[i];
+					break;
+				}
 	}
 	mutex_unlock(&ioc->sas_topology_mutex);
 
@@ -1258,36 +1303,58 @@
 	MPT_ADAPTER *ioc = ev->ioc;
 	struct mptsas_phyinfo *phy_info;
 	struct sas_rphy *rphy;
+	struct scsi_device *sdev;
 	char *ds = NULL;
-
-	if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
-		ds = "ssp";
-	if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
-		ds = "stp";
-	if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
-		ds = "sata";
+	struct mptsas_devinfo sas_device;
 
 	switch (ev->event_type) {
 	case MPTSAS_DEL_DEVICE:
-		printk(MYIOC_s_INFO_FMT
-		       "removing %s device, channel %d, id %d, phy %d\n",
-		       ioc->name, ds, ev->channel, ev->id, ev->phy_id);
 
-		phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
+		phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
 		if (!phy_info) {
 			printk("mptsas: remove event for non-existant PHY.\n");
 			break;
 		}
 
+		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+			ds = "ssp";
+		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+			ds = "stp";
+		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+			ds = "sata";
+
+		printk(MYIOC_s_INFO_FMT
+		       "removing %s device, channel %d, id %d, phy %d\n",
+		       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
+
 		if (phy_info->rphy) {
 			sas_rphy_delete(phy_info->rphy);
 			phy_info->rphy = NULL;
 		}
 		break;
 	case MPTSAS_ADD_DEVICE:
-		printk(MYIOC_s_INFO_FMT
-		       "attaching %s device, channel %d, id %d, phy %d\n",
-		       ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+		/*
+		 * When there is no sas address,
+		 * RAID volumes are being deleted,
+		 * and hidden phy disk are being added.
+		 * We don't know the SAS data yet,
+		 * so lookup sas device page to get
+		 * pertaining info
+		 */
+		if (!ev->sas_address) {
+			if (mptsas_sas_device_pg0(ioc,
+			    &sas_device, ev->id,
+			    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+			     MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))
+				break;
+			ev->handle = sas_device.handle;
+			ev->parent_handle = sas_device.handle_parent;
+			ev->channel = sas_device.channel;
+			ev->phy_id = sas_device.phy_id;
+			ev->sas_address = sas_device.sas_address;
+			ev->device_info = sas_device.device_info;
+		}
 
 		phy_info = mptsas_find_phyinfo_by_parent(ioc,
 				ev->parent_handle, ev->phy_id);
@@ -1310,10 +1377,23 @@
 		phy_info->attached.sas_address = ev->sas_address;
 		phy_info->attached.device_info = ev->device_info;
 
+		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+			ds = "ssp";
+		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+			ds = "stp";
+		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+			ds = "sata";
+
+		printk(MYIOC_s_INFO_FMT
+		       "attaching %s device, channel %d, id %d, phy %d\n",
+		       ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+
 		rphy = sas_rphy_alloc(phy_info->phy);
 		if (!rphy)
 			break; /* non-fatal: an rphy can be added later */
 
+		rphy->scsi_target_id = phy_info->attached.id;
 		mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
 		if (sas_rphy_add(rphy)) {
 			sas_rphy_free(rphy);
@@ -1322,6 +1402,40 @@
 
 		phy_info->rphy = rphy;
 		break;
+	case MPTSAS_ADD_RAID:
+		sdev = scsi_device_lookup(
+			ioc->sh,
+			ioc->num_ports,
+			ev->id,
+			0);
+		if (sdev) {
+			scsi_device_put(sdev);
+			break;
+		}
+		printk(MYIOC_s_INFO_FMT
+		       "attaching device, channel %d, id %d\n",
+		       ioc->name, ioc->num_ports, ev->id);
+		scsi_add_device(ioc->sh,
+			ioc->num_ports,
+			ev->id,
+			0);
+		mpt_findImVolumes(ioc);
+		break;
+	case MPTSAS_DEL_RAID:
+		sdev = scsi_device_lookup(
+			ioc->sh,
+			ioc->num_ports,
+			ev->id,
+			0);
+		if (!sdev)
+			break;
+		printk(MYIOC_s_INFO_FMT
+		       "removing device, channel %d, id %d\n",
+		       ioc->name, ioc->num_ports, ev->id);
+		scsi_remove_device(sdev);
+		scsi_device_put(sdev);
+		mpt_findImVolumes(ioc);
+		break;
 	}
 
 	kfree(ev);
@@ -1372,23 +1486,94 @@
 	schedule_work(&ev->work);
 }
 
+static void
+mptscsih_send_raid_event(MPT_ADAPTER *ioc,
+		EVENT_DATA_RAID *raid_event_data)
+{
+	struct mptsas_hotplug_event *ev;
+	RAID_VOL0_STATUS * volumeStatus;
+
+	if (ioc->bus_type != SAS)
+		return;
+
+	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev) {
+		printk(KERN_WARNING "mptsas: lost hotplug event\n");
+		return;
+	}
+
+	memset(ev,0,sizeof(struct mptsas_hotplug_event));
+	INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+	ev->ioc = ioc;
+	ev->id = raid_event_data->VolumeID;
+
+	switch (raid_event_data->ReasonCode) {
+	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+		ev->event_type = MPTSAS_ADD_DEVICE;
+		break;
+	case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+		ev->event_type = MPTSAS_DEL_DEVICE;
+		break;
+	case MPI_EVENT_RAID_RC_VOLUME_DELETED:
+		ev->event_type = MPTSAS_DEL_RAID;
+		break;
+	case MPI_EVENT_RAID_RC_VOLUME_CREATED:
+		ev->event_type = MPTSAS_ADD_RAID;
+		break;
+	case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
+		volumeStatus = (RAID_VOL0_STATUS *) &
+		    raid_event_data->SettingsStatus;
+		ev->event_type = (volumeStatus->State ==
+		    MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
+		    MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
+		break;
+	default:
+		break;
+	}
+	schedule_work(&ev->work);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* work queue thread to clear the persitency table */
+static void
+mptscsih_sas_persist_clear_table(void * arg)
+{
+	MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+
+	mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
+}
+
 static int
 mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 {
+	int rc=1;
 	u8 event = le32_to_cpu(reply->Event) & 0xFF;
 
 	if (!ioc->sh)
-		return 1;
+		goto out;
 
 	switch (event) {
 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
 		mptscsih_send_sas_event(ioc,
 			(EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
-		return 1;		/* currently means nothing really */
-
+		break;
+	case MPI_EVENT_INTEGRATED_RAID:
+		mptscsih_send_raid_event(ioc,
+			(EVENT_DATA_RAID *)reply->Data);
+		break;
+	case MPI_EVENT_PERSISTENT_TABLE_FULL:
+		INIT_WORK(&ioc->mptscsih_persistTask,
+		    mptscsih_sas_persist_clear_table,
+		    (void *)ioc);
+		schedule_work(&ioc->mptscsih_persistTask);
+		break;
 	default:
-		return mptscsih_event_process(ioc, reply);
+		rc = mptscsih_event_process(ioc, reply);
+		break;
 	}
+ out:
+
+	return rc;
 }
 
 static int
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index cdac557..05789e5 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -144,7 +144,6 @@
 static int	mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
 static u32	SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
 
-static int	mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
 static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
 
 int		mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
@@ -159,11 +158,9 @@
 int		mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static int	mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
 static void	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
-static void	mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget);
+static void	mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
 static int	mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
 
-static struct work_struct   mptscsih_persistTask;
-
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 static int	mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
 static void	mptscsih_domainValidation(void *hd);
@@ -563,11 +560,24 @@
 	MPT_SCSI_HOST	*hd;
 	SCSIIORequest_t	*pScsiReq;
 	SCSIIOReply_t	*pScsiReply;
-	u16		 req_idx;
+	u16		 req_idx, req_idx_MR;
 
 	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
 
 	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+	req_idx_MR = (mr != NULL) ?
+	    le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
+	if ((req_idx != req_idx_MR) ||
+	    (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
+		printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
+		    ioc->name);
+		printk (MYIOC_s_ERR_FMT
+		    "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
+		    ioc->name, req_idx, req_idx_MR, mf, mr,
+		    hd->ScsiLookup[req_idx_MR]);
+		return 0;
+	}
+
 	sc = hd->ScsiLookup[req_idx];
 	if (sc == NULL) {
 		MPIHeader_t *hdr = (MPIHeader_t *)mf;
@@ -730,6 +740,8 @@
 
 			break;
 
+		case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		/* 0x0044 */
+			sc->resid=0;
 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
 		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
 			if (scsi_status == MPI_SCSI_STATUS_BUSY)
@@ -789,7 +801,6 @@
 		case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:	/* 0x0006 */
 		case MPI_IOCSTATUS_INVALID_FIELD:		/* 0x0007 */
 		case MPI_IOCSTATUS_INVALID_STATE:		/* 0x0008 */
-		case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		/* 0x0044 */
 		case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:		/* 0x0046 */
 		case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:	/* 0x004A */
 		default:
@@ -1530,7 +1541,7 @@
  *
  *	Returns 0 for SUCCESS or -1 if FAILED.
  */
-static int
+int
 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
 {
 	MPT_ADAPTER	*ioc;
@@ -1721,6 +1732,20 @@
 	return retval;
 }
 
+static int
+mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
+{
+	switch (ioc->bus_type) {
+	case FC:
+		return 40;
+	case SAS:
+		return 10;
+	case SPI:
+	default:
+		return 2;
+	}
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
@@ -1792,7 +1817,7 @@
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
 		vdev->bus_id, vdev->target_id, vdev->lun,
-		ctx2abort, 2 /* 2 second timeout */);
+		ctx2abort, mptscsih_get_tm_timeout(ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -1843,7 +1868,7 @@
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
 		vdev->bus_id, vdev->target_id,
-		0, 0, 5 /* 5 second timeout */);
+		0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -1893,7 +1918,7 @@
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-		vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */);
+		vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -2016,6 +2041,42 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static void
+mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
+{
+	char *desc;
+
+	switch (response_code) {
+	case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
+		desc = "The task completed.";
+		break;
+	case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
+		desc = "The IOC received an invalid frame status.";
+		break;
+	case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
+		desc = "The task type is not supported.";
+		break;
+	case MPI_SCSITASKMGMT_RSP_TM_FAILED:
+		desc = "The requested task failed.";
+		break;
+	case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
+		desc = "The task completed successfully.";
+		break;
+	case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
+		desc = "The LUN request is invalid.";
+		break;
+	case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
+		desc = "The task is in the IOC queue and has not been sent to target.";
+		break;
+	default:
+		desc = "unknown";
+		break;
+	}
+	printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
+		ioc->name, response_code, desc);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
  *	@ioc: Pointer to MPT_ADAPTER structure
@@ -2064,6 +2125,11 @@
 		/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
 		tmType = pScsiTmReq->TaskType;
 
+		if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
+		    pScsiTmReply->ResponseCode)
+			mptscsih_taskmgmt_response_code(ioc,
+			    pScsiTmReply->ResponseCode);
+
 		dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
 				ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
 		DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
@@ -2255,7 +2321,7 @@
 	vtarget->luns[0] &= ~(1 << vdevice->lun);
 	vtarget->num_luns--;
 	if (vtarget->num_luns == 0) {
-		mptscsih_negotiate_to_asyn_narrow(hd, vtarget);
+		mptscsih_negotiate_to_asyn_narrow(hd, vdevice);
 		if (hd->ioc->bus_type == SPI) {
 			if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) {
 				hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
@@ -2585,16 +2651,6 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* work queue thread to clear the persitency table */
-static void
-mptscsih_sas_persist_clear_table(void * arg)
-{
-	MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
-
-	mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 int
 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
@@ -2656,13 +2712,6 @@
 		break;
 	}
 
-	/* Persistent table is full. */
-	case MPI_EVENT_PERSISTENT_TABLE_FULL:
-		INIT_WORK(&mptscsih_persistTask,
-		    mptscsih_sas_persist_clear_table,(void *)ioc);
-		schedule_work(&mptscsih_persistTask);
-		break;
-
 	case MPI_EVENT_NONE:				/* 00 */
 	case MPI_EVENT_LOG_DATA:			/* 01 */
 	case MPI_EVENT_STATE_CHANGE:			/* 02 */
@@ -3863,8 +3912,9 @@
  *
  */
 static void
-mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
+mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 {
+	VirtTarget		*vtarget = vdevice->vtarget;
 	MPT_ADAPTER		*ioc= hd->ioc;
 	SCSIDevicePage1_t	*pcfg1Data;
 	CONFIGPARMS		 cfg;
@@ -3874,7 +3924,8 @@
 	int			 requested, configuration, data,i;
 	u8			 flags, factor;
 
-	if (ioc->bus_type != SPI)
+	if ((ioc->bus_type != SPI) ||
+		(!vdevice->configured_lun))
 		return;
 
 	if (!ioc->spi_data.sdp1length)
@@ -3910,7 +3961,7 @@
 			}
 			mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
 				&configuration, flags);
-			dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+			dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC "
 				"offset=0 negoFlags=%x request=%x config=%x\n",
 				id, flags, requested, configuration));
 			pcfg1Data->RequestedParameters = cpu_to_le32(requested);
@@ -3923,7 +3974,7 @@
 		flags = vtarget->negoFlags;
 		mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
 				&configuration, flags);
-		dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+		dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC "
 			"offset=0 negoFlags=%x request=%x config=%x\n",
 			vtarget->target_id, flags, requested, configuration));
 		pcfg1Data->RequestedParameters = cpu_to_le32(requested);
@@ -5620,5 +5671,6 @@
 EXPORT_SYMBOL(mptscsih_ioc_reset);
 EXPORT_SYMBOL(mptscsih_change_queue_depth);
 EXPORT_SYMBOL(mptscsih_timer_expired);
+EXPORT_SYMBOL(mptscsih_TMHandler);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index d3cba12..44b248d 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -108,3 +108,4 @@
 extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
 extern void mptscsih_timer_expired(unsigned long data);
+extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 7dce292..f148dfa 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -384,6 +384,14 @@
 		goto out_mptspi_probe;
 	}
 
+	/*
+	 * issue internal bus reset
+	 */
+	if (ioc->spi_data.bus_reset)
+		mptscsih_TMHandler(hd,
+		    MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+		    0, 0, 0, 0, 5);
+
 	scsi_scan_host(sh);
 	return 0;
 
@@ -445,7 +453,7 @@
 mptspi_exit(void)
 {
 	pci_unregister_driver(&mptspi_driver);
-	
+
 	mpt_reset_deregister(mptspiDoneCtx);
 	dprintk((KERN_INFO MYNAM
 	  ": Deregistered for IOC reset notifications\n"));
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index 9062856..184974c 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -60,4 +60,7 @@
 #define I2O_IN_PORT	0x40
 #define I2O_OUT_PORT	0x44
 
+/* Motorola/Freescale specific register offset */
+#define I2O_MOTOROLA_PORT_OFFSET	0x10400
+
 #define I2O_IRQ_OUTBOUND_POST	0x00000008
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index f9e5a23..c08ddac 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -732,7 +732,7 @@
 	    cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid);
 	msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt));
 
-	if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
+	if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
 		status = SUCCESS;
 
 	return status;
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index d698d77..4f1515c 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -88,6 +88,11 @@
 	struct device *dev = &pdev->dev;
 	int i;
 
+	if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
+		printk(KERN_ERR "%s: device already claimed\n", c->name);
+		return -ENODEV;
+	}
+
 	for (i = 0; i < 6; i++) {
 		/* Skip I/O spaces */
 		if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
@@ -163,6 +168,24 @@
 	c->in_port = c->base.virt + I2O_IN_PORT;
 	c->out_port = c->base.virt + I2O_OUT_PORT;
 
+	/* Motorola/Freescale chip does not follow spec */
+	if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) {
+		/* Check if CPU is enabled */
+		if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) {
+			printk(KERN_INFO "%s: MPC82XX needs CPU running to "
+			       "service I2O.\n", c->name);
+			i2o_pci_free(c);
+			return -ENODEV;
+		} else {
+			c->irq_status += I2O_MOTOROLA_PORT_OFFSET;
+			c->irq_mask += I2O_MOTOROLA_PORT_OFFSET;
+			c->in_port += I2O_MOTOROLA_PORT_OFFSET;
+			c->out_port += I2O_MOTOROLA_PORT_OFFSET;
+			printk(KERN_INFO "%s: MPC82XX workarounds activated.\n",
+			       c->name);
+		}
+	}
+
 	if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
 		i2o_pci_free(c);
 		return -ENOMEM;
@@ -298,7 +321,7 @@
 	struct i2o_controller *c;
 	int rc;
 	struct pci_dev *i960 = NULL;
-	int pci_dev_busy = 0;
+	int enabled = pdev->is_enabled;
 
 	printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
 
@@ -308,16 +331,12 @@
 		return -ENODEV;
 	}
 
-	if ((rc = pci_enable_device(pdev))) {
-		printk(KERN_WARNING "i2o: couldn't enable device %s\n",
-		       pci_name(pdev));
-		return rc;
-	}
-
-	if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
-		printk(KERN_ERR "i2o: device already claimed\n");
-		return -ENODEV;
-	}
+	if (!enabled)
+		if ((rc = pci_enable_device(pdev))) {
+			printk(KERN_WARNING "i2o: couldn't enable device %s\n",
+			       pci_name(pdev));
+			return rc;
+		}
 
 	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
 		printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
@@ -395,9 +414,7 @@
 
 	if ((rc = i2o_pci_alloc(c))) {
 		printk(KERN_ERR "%s: DMA / IO allocation for I2O controller "
-		       " failed\n", c->name);
-		if (rc == -ENODEV)
-			pci_dev_busy = 1;
+		       "failed\n", c->name);
 		goto free_controller;
 	}
 
@@ -425,7 +442,7 @@
 	i2o_iop_free(c);
 
       disable:
-	if (!pci_dev_busy)
+	if (!enabled)
 		pci_disable_device(pdev);
 
 	return rc;
diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c
index 7e98434..9783caf 100644
--- a/drivers/misc/ibmasm/uart.c
+++ b/drivers/misc/ibmasm/uart.c
@@ -50,7 +50,7 @@
 	memset(&uport, 0, sizeof(struct uart_port));
 	uport.irq	= sp->irq;
 	uport.uartclk	= 3686400;
-	uport.flags	= UPF_AUTOPROBE | UPF_SHARE_IRQ;
+	uport.flags	= UPF_SHARE_IRQ;
 	uport.iotype	= UPIO_MEM;
 	uport.membase	= iomem_base;
 
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c483a86..5d397b7 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -65,7 +65,7 @@
 	depends on SOC_AU1X00 && MMC
 	help
 	  This selects the AMD Alchemy(R) Multimedia card interface.
-	  iIf you have a Alchemy platform with a MMC slot, say Y or M here.
+	  If you have a Alchemy platform with a MMC slot, say Y or M here.
 
 	  If unsure, say N.
 
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index aaf0463..227c39a 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -194,7 +194,7 @@
 
 	u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
 
-	switch(cmd->flags) {
+	switch (mmc_rsp_type(cmd->flags)) {
 	case MMC_RSP_R1:
 		mmccmd |= SD_CMD_RT_1;
 		break;
@@ -483,34 +483,35 @@
 	cmd = mrq->cmd;
 	cmd->error = MMC_ERR_NONE;
 
-	if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) {
+	if (cmd->flags & MMC_RSP_PRESENT) {
+		if (cmd->flags & MMC_RSP_136) {
+			u32 r[4];
+			int i;
 
-		/* Techincally, we should be getting all 48 bits of the response
-		 * (SD_RESP1 + SD_RESP2), but because our response omits the CRC,
-		 * our data ends up being shifted 8 bits to the right.  In this case,
-		 * that means that the OSR data starts at bit 31, so we can just
-		 * read RESP0 and return that
-		 */
+			r[0] = au_readl(host->iobase + SD_RESP3);
+			r[1] = au_readl(host->iobase + SD_RESP2);
+			r[2] = au_readl(host->iobase + SD_RESP1);
+			r[3] = au_readl(host->iobase + SD_RESP0);
 
-		cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
-	}
-	else if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
-		u32 r[4];
-		int i;
+			/* The CRC is omitted from the response, so really
+			 * we only got 120 bytes, but the engine expects
+			 * 128 bits, so we have to shift things up
+			 */
 
-		r[0] = au_readl(host->iobase + SD_RESP3);
-		r[1] = au_readl(host->iobase + SD_RESP2);
-		r[2] = au_readl(host->iobase + SD_RESP1);
-		r[3] = au_readl(host->iobase + SD_RESP0);
-
-		/* The CRC is omitted from the response, so really we only got
-		 * 120 bytes, but the engine expects 128 bits, so we have to shift
-		 * things up
-		 */
-
-		for(i = 0; i < 4; i++) {
-			cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
-			if (i != 3) cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
+			for(i = 0; i < 4; i++) {
+				cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
+				if (i != 3)
+					cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
+			}
+		} else {
+			/* Techincally, we should be getting all 48 bits of
+			 * the response (SD_RESP1 + SD_RESP2), but because
+			 * our response omits the CRC, our data ends up
+			 * being shifted 8 bits to the right.  In this case,
+			 * that means that the OSR data starts at bit 31,
+			 * so we can just read RESP0 and return that
+			 */
+			cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
 		}
 	}
 
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index bfca5c1..1888060 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -211,7 +211,7 @@
 
 		appcmd.opcode = MMC_APP_CMD;
 		appcmd.arg = rca << 16;
-		appcmd.flags = MMC_RSP_R1;
+		appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 		appcmd.retries = 0;
 		memset(appcmd.resp, 0, sizeof(appcmd.resp));
 		appcmd.data = NULL;
@@ -331,7 +331,7 @@
 
 	cmd.opcode = MMC_SELECT_CARD;
 	cmd.arg = card->rca << 16;
-	cmd.flags = MMC_RSP_R1;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 
 	err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 	if (err != MMC_ERR_NONE)
@@ -358,7 +358,7 @@
 			struct mmc_command cmd;
 			cmd.opcode = SD_APP_SET_BUS_WIDTH;
 			cmd.arg = SD_BUS_WIDTH_4;
-			cmd.flags = MMC_RSP_R1;
+			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 
 			err = mmc_wait_for_app_cmd(host, card->rca, &cmd,
 				CMD_RETRIES);
@@ -386,7 +386,7 @@
 
 		cmd.opcode = MMC_SELECT_CARD;
 		cmd.arg = 0;
-		cmd.flags = MMC_RSP_NONE;
+		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
 
 		mmc_wait_for_cmd(host, &cmd, 0);
 	}
@@ -677,7 +677,7 @@
 
 	cmd.opcode = MMC_GO_IDLE_STATE;
 	cmd.arg = 0;
-	cmd.flags = MMC_RSP_NONE;
+	cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
 
 	mmc_wait_for_cmd(host, &cmd, 0);
 
@@ -738,7 +738,7 @@
 
 	cmd.opcode = MMC_SEND_OP_COND;
 	cmd.arg = ocr;
-	cmd.flags = MMC_RSP_R3;
+	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
 
 	for (i = 100; i; i--) {
 		err = mmc_wait_for_cmd(host, &cmd, 0);
@@ -766,7 +766,7 @@
 
 	cmd.opcode = SD_APP_OP_COND;
 	cmd.arg = ocr;
-	cmd.flags = MMC_RSP_R3;
+	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
 
 	for (i = 100; i; i--) {
 		err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
@@ -805,7 +805,7 @@
 
 		cmd.opcode = MMC_ALL_SEND_CID;
 		cmd.arg = 0;
-		cmd.flags = MMC_RSP_R2;
+		cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
 
 		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 		if (err == MMC_ERR_TIMEOUT) {
@@ -835,7 +835,7 @@
 
 			cmd.opcode = SD_SEND_RELATIVE_ADDR;
 			cmd.arg = 0;
-			cmd.flags = MMC_RSP_R6;
+			cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
 
 			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 			if (err != MMC_ERR_NONE)
@@ -856,7 +856,7 @@
 		} else {
 			cmd.opcode = MMC_SET_RELATIVE_ADDR;
 			cmd.arg = card->rca << 16;
-			cmd.flags = MMC_RSP_R1;
+			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 
 			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 			if (err != MMC_ERR_NONE)
@@ -878,7 +878,7 @@
 
 		cmd.opcode = MMC_SEND_CSD;
 		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R2;
+		cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
 
 		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 		if (err != MMC_ERR_NONE) {
@@ -920,7 +920,7 @@
 
 		cmd.opcode = MMC_APP_CMD;
 		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R1;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 
 		err = mmc_wait_for_cmd(host, &cmd, 0);
 		if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
@@ -932,7 +932,7 @@
 
 		cmd.opcode = SD_APP_SEND_SCR;
 		cmd.arg = 0;
-		cmd.flags = MMC_RSP_R1;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
 
 		memset(&data, 0, sizeof(struct mmc_data));
 
@@ -1003,7 +1003,7 @@
 
 		cmd.opcode = MMC_SEND_STATUS;
 		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R1;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 
 		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 		if (err == MMC_ERR_NONE)
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 5b014c3..8eb2a2e 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -171,14 +171,14 @@
 		brq.mrq.data = &brq.data;
 
 		brq.cmd.arg = req->sector << 9;
-		brq.cmd.flags = MMC_RSP_R1;
+		brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
 		brq.data.timeout_ns = card->csd.tacc_ns * 10;
 		brq.data.timeout_clks = card->csd.tacc_clks * 10;
 		brq.data.blksz_bits = md->block_bits;
 		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
 		brq.stop.opcode = MMC_STOP_TRANSMISSION;
 		brq.stop.arg = 0;
-		brq.stop.flags = MMC_RSP_R1B;
+		brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
 
 		if (rq_data_dir(req) == READ) {
 			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
@@ -223,7 +223,7 @@
 
 			cmd.opcode = MMC_SEND_STATUS;
 			cmd.arg = card->rca << 16;
-			cmd.flags = MMC_RSP_R1;
+			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 			err = mmc_wait_for_cmd(card->host, &cmd, 5);
 			if (err) {
 				printk(KERN_ERR "%s: error %d requesting status\n",
@@ -430,7 +430,7 @@
 	mmc_card_claim_host(card);
 	cmd.opcode = MMC_SET_BLOCKLEN;
 	cmd.arg = 1 << md->block_bits;
-	cmd.flags = MMC_RSP_R1;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 	err = mmc_wait_for_cmd(card->host, &cmd, 5);
 	mmc_card_release_host(card);
 
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 634ef53..37ee7f8 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -124,15 +124,10 @@
 	}
 
 	c |= cmd->opcode | MCI_CPSM_ENABLE;
-	switch (cmd->flags & MMC_RSP_MASK) {
-	case MMC_RSP_NONE:
-	default:
-		break;
-	case MMC_RSP_LONG:
-		c |= MCI_CPSM_LONGRSP;
-	case MMC_RSP_SHORT:
+	if (cmd->flags & MMC_RSP_PRESENT) {
+		if (cmd->flags & MMC_RSP_136)
+			c |= MCI_CPSM_LONGRSP;
 		c |= MCI_CPSM_RESPONSE;
-		break;
 	}
 	if (/*interrupt*/0)
 		c |= MCI_CPSM_INTERRUPT;
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index ee8f8a0..285d7d0 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -178,14 +178,15 @@
 	if (cmd->flags & MMC_RSP_BUSY)
 		cmdat |= CMDAT_BUSY;
 
-	switch (cmd->flags & (MMC_RSP_MASK | MMC_RSP_CRC)) {
-	case MMC_RSP_SHORT | MMC_RSP_CRC:
+#define RSP_TYPE(x)	((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
+	switch (RSP_TYPE(mmc_resp_type(cmd))) {
+	case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6 */
 		cmdat |= CMDAT_RESP_SHORT;
 		break;
-	case MMC_RSP_SHORT:
+	case RSP_TYPE(MMC_RSP_R3):
 		cmdat |= CMDAT_RESP_R3;
 		break;
-	case MMC_RSP_LONG | MMC_RSP_CRC:
+	case RSP_TYPE(MMC_RSP_R2):
 		cmdat |= CMDAT_RESP_R2;
 		break;
 	default:
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index f257576..3be397d 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -459,7 +459,7 @@
 	/*
 	 * Do we expect a reply?
 	 */
-	if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) {
+	if (cmd->flags & MMC_RSP_PRESENT) {
 		/*
 		 * Read back status.
 		 */
@@ -476,10 +476,10 @@
 			cmd->error = MMC_ERR_BADCRC;
 		/* All ok */
 		else {
-			if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT)
-				wbsd_get_short_reply(host, cmd);
-			else
+			if (cmd->flags & MMC_RSP_136)
 				wbsd_get_long_reply(host, cmd);
+			else
+				wbsd_get_short_reply(host, cmd);
 		}
 	}
 
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index effa0d7..205bb70 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -301,7 +301,7 @@
 
 config MTD_XIP
 	bool "XIP aware MTD support"
-	depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARM
+	depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP
 	default y if XIP_KERNEL
 	help
 	  This allows MTD support to work with flash memory which is also
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c
index 701620b..8b3784e 100644
--- a/drivers/mtd/maps/dc21285.c
+++ b/drivers/mtd/maps/dc21285.c
@@ -110,8 +110,9 @@
 {
 	while (len > 0) {
 		map_word d;
-		d.x[0] = *((uint32_t*)from)++;
+		d.x[0] = *((uint32_t*)from);
 		dc21285_write32(map, d, to);
+		from += 4;
 		to += 4;
 		len -= 4;
 	}
@@ -121,8 +122,9 @@
 {
 	while (len > 0) {
 		map_word d;
-		d.x[0] = *((uint16_t*)from)++;
+		d.x[0] = *((uint16_t*)from);
 		dc21285_write16(map, d, to);
+		from += 2;
 		to += 2;
 		len -= 2;
 	}
@@ -131,8 +133,9 @@
 static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len)
 {
 	map_word d;
-	d.x[0] = *((uint8_t*)from)++;
+	d.x[0] = *((uint8_t*)from);
 	dc21285_write8(map, d, to);
+	from++;
 	to++;
 	len--;
 }
diff --git a/drivers/mtd/maps/tsunami_flash.c b/drivers/mtd/maps/tsunami_flash.c
index 9e21e6c..0f915ac 100644
--- a/drivers/mtd/maps/tsunami_flash.c
+++ b/drivers/mtd/maps/tsunami_flash.c
@@ -62,7 +62,7 @@
 static struct map_info tsunami_flash_map = {
 	.name = "flash chip on the Tsunami TIG bus",
 	.size = MAX_TIG_FLASH_SIZE,
-	.phys = NO_XIP;
+	.phys = NO_XIP,
 	.bankwidth = 1,
 	.read = tsunami_flash_read8,
 	.copy_from = tsunami_flash_copy_from,
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 7488ee7..7f47124 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -753,9 +753,11 @@
 enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };
 
 struct vortex_extra_stats {
-        unsigned long tx_deferred;
-        unsigned long tx_multiple_collisions;
-        unsigned long rx_bad_ssd;
+	unsigned long tx_deferred;
+	unsigned long tx_max_collisions;
+	unsigned long tx_multiple_collisions;
+	unsigned long tx_single_collisions;
+	unsigned long rx_bad_ssd;
 };
 
 struct vortex_private {
@@ -863,12 +865,14 @@
 	const char str[ETH_GSTRING_LEN];
 } ethtool_stats_keys[] = {
 	{ "tx_deferred" },
+	{ "tx_max_collisions" },
 	{ "tx_multiple_collisions" },
+	{ "tx_single_collisions" },
 	{ "rx_bad_ssd" },
 };
 
 /* number of ETHTOOL_GSTATS u64's */
-#define VORTEX_NUM_STATS     3
+#define VORTEX_NUM_STATS    5
 
 static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
 				   int chip_idx, int card_idx);
@@ -2108,9 +2112,12 @@
 		iowrite8(0, ioaddr + TxStatus);
 		if (tx_status & 0x30) {			/* txJabber or txUnderrun */
 			do_tx_reset = 1;
-		} else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) {	/* maxCollisions */
-			do_tx_reset = 1;
-			reset_mask = 0x0108;		/* Reset interface logic, but not download logic */
+		} else if (tx_status & 0x08) {	/* maxCollisions */
+			vp->xstats.tx_max_collisions++;
+			if (vp->drv_flags & MAX_COLLISION_RESET) {
+				do_tx_reset = 1;
+				reset_mask = 0x0108;		/* Reset interface logic, but not download logic */
+			}
 		} else {						/* Merely re-enable the transmitter. */
 			iowrite16(TxEnable, ioaddr + EL3_CMD);
 		}
@@ -2926,7 +2933,6 @@
 	EL3WINDOW(6);
 	vp->stats.tx_carrier_errors		+= ioread8(ioaddr + 0);
 	vp->stats.tx_heartbeat_errors		+= ioread8(ioaddr + 1);
-	vp->stats.collisions			+= ioread8(ioaddr + 3);
 	vp->stats.tx_window_errors		+= ioread8(ioaddr + 4);
 	vp->stats.rx_fifo_errors		+= ioread8(ioaddr + 5);
 	vp->stats.tx_packets			+= ioread8(ioaddr + 6);
@@ -2939,10 +2945,15 @@
 	vp->stats.tx_bytes 			+= ioread16(ioaddr + 12);
 	/* Extra stats for get_ethtool_stats() */
 	vp->xstats.tx_multiple_collisions	+= ioread8(ioaddr + 2);
+	vp->xstats.tx_single_collisions         += ioread8(ioaddr + 3);
 	vp->xstats.tx_deferred			+= ioread8(ioaddr + 8);
 	EL3WINDOW(4);
 	vp->xstats.rx_bad_ssd			+= ioread8(ioaddr + 12);
 
+	vp->stats.collisions = vp->xstats.tx_multiple_collisions
+		+ vp->xstats.tx_single_collisions
+		+ vp->xstats.tx_max_collisions;
+
 	{
 		u8 up = ioread8(ioaddr + 13);
 		vp->stats.rx_bytes += (up & 0x0f) << 16;
@@ -3036,8 +3047,10 @@
 	spin_unlock_irqrestore(&vp->lock, flags);
 
 	data[0] = vp->xstats.tx_deferred;
-	data[1] = vp->xstats.tx_multiple_collisions;
-	data[2] = vp->xstats.rx_bad_ssd;
+	data[1] = vp->xstats.tx_max_collisions;
+	data[2] = vp->xstats.tx_multiple_collisions;
+	data[3] = vp->xstats.tx_single_collisions;
+	data[4] = vp->xstats.rx_bad_ssd;
 }
 
 
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index adfba44..2beac55 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -586,6 +586,7 @@
 	dma_addr_t tx_bufs_dma;
 	signed char phys[4];		/* MII device addresses. */
 	char twistie, twist_row, twist_col;	/* Twister tune state. */
+	unsigned int watchdog_fired : 1;
 	unsigned int default_port : 4;	/* Last dev->if_port value. */
 	unsigned int have_thread : 1;
 	spinlock_t lock;
@@ -638,6 +639,7 @@
 static void __set_rx_mode (struct net_device *dev);
 static void rtl8139_hw_start (struct net_device *dev);
 static void rtl8139_thread (void *_data);
+static void rtl8139_tx_timeout_task(void *_data);
 static struct ethtool_ops rtl8139_ethtool_ops;
 
 /* write MMIO register, with flush */
@@ -1598,13 +1600,14 @@
 {
 	struct net_device *dev = _data;
 	struct rtl8139_private *tp = netdev_priv(dev);
-	unsigned long thr_delay;
+	unsigned long thr_delay = next_tick;
 
-	if (rtnl_shlock_nowait() == 0) {
+	if (tp->watchdog_fired) {
+		tp->watchdog_fired = 0;
+		rtl8139_tx_timeout_task(_data);
+	} else if (rtnl_shlock_nowait() == 0) {
 		rtl8139_thread_iter (dev, tp, tp->mmio_addr);
 		rtnl_unlock ();
-
-		thr_delay = next_tick;
 	} else {
 		/* unlikely race.  mitigate with fast poll. */
 		thr_delay = HZ / 2;
@@ -1631,7 +1634,8 @@
 	if (tp->have_thread) {
 		cancel_rearming_delayed_work(&tp->thread);
 		tp->have_thread = 0;
-	}
+	} else
+		flush_scheduled_work();
 }
 
 static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
@@ -1642,14 +1646,13 @@
 	/* XXX account for unsent Tx packets in tp->stats.tx_dropped */
 }
 
-
-static void rtl8139_tx_timeout (struct net_device *dev)
+static void rtl8139_tx_timeout_task (void *_data)
 {
+	struct net_device *dev = _data;
 	struct rtl8139_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
 	int i;
 	u8 tmp8;
-	unsigned long flags;
 
 	printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x "
 		"media %2.2x.\n", dev->name, RTL_R8 (ChipCmd),
@@ -1670,23 +1673,34 @@
 	if (tmp8 & CmdTxEnb)
 		RTL_W8 (ChipCmd, CmdRxEnb);
 
-	spin_lock(&tp->rx_lock);
+	spin_lock_bh(&tp->rx_lock);
 	/* Disable interrupts by clearing the interrupt mask. */
 	RTL_W16 (IntrMask, 0x0000);
 
 	/* Stop a shared interrupt from scavenging while we are. */
-	spin_lock_irqsave (&tp->lock, flags);
+	spin_lock_irq(&tp->lock);
 	rtl8139_tx_clear (tp);
-	spin_unlock_irqrestore (&tp->lock, flags);
+	spin_unlock_irq(&tp->lock);
 
 	/* ...and finally, reset everything */
 	if (netif_running(dev)) {
 		rtl8139_hw_start (dev);
 		netif_wake_queue (dev);
 	}
-	spin_unlock(&tp->rx_lock);
+	spin_unlock_bh(&tp->rx_lock);
 }
 
+static void rtl8139_tx_timeout (struct net_device *dev)
+{
+	struct rtl8139_private *tp = netdev_priv(dev);
+
+	if (!tp->have_thread) {
+		INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev);
+		schedule_delayed_work(&tp->thread, next_tick);
+	} else
+		tp->watchdog_fired = 1;
+
+}
 
 static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 1421941..47c72a6 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -4,9 +4,10 @@
 #
 
 menu "Network device support"
+	depends on NET
 
 config NETDEVICES
-	depends on NET
+	default y if UML
 	bool "Network device support"
 	---help---
 	  You can say N here if you don't intend to connect your Linux box to
@@ -23,9 +24,6 @@
 
 	  If unsure, say Y.
 
-# All the following symbols are dependent on NETDEVICES - do not repeat
-# that for each of the symbols.
-if NETDEVICES
 
 config IFB
 	tristate "Intermediate Functional Block support"
@@ -1914,6 +1912,15 @@
 
 	  If in doubt, say N.
 
+config E1000_DISABLE_PACKET_SPLIT
+	bool "Disable Packet Split for PCI express adapters"
+	depends on E1000
+	help
+	  Say Y here if you want to use the legacy receive path for PCI express
+	  hadware.
+
+	  If in doubt, say N.
+
 source "drivers/net/ixp2000/Kconfig"
 
 config MYRI_SBUS
@@ -2024,13 +2031,28 @@
 	  It does not support the link failover and network management 
 	  features that "portable" vendor supplied sk98lin driver does.
 
+	  This driver supports adapters based on the original Yukon chipset:
+	  Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
+	  Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872.
+
+	  It does not support the newer Yukon2 chipset: a separate driver,
+	  sky2, is provided for Yukon2-based adapters.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called skge.  This is recommended.
 
 config SKY2
 	tristate "SysKonnect Yukon2 support (EXPERIMENTAL)"
 	depends on PCI && EXPERIMENTAL
 	select CRC32
 	---help---
-	  This driver support the Marvell Yukon 2 Gigabit Ethernet adapter.
+	  This driver supports Gigabit Ethernet adapters based on the the
+	  Marvell Yukon 2 chipset:
+	  Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/
+	  88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
+
+	  This driver does not support the original Yukon chipset: a seperate
+	  driver, skge, is provided for Yukon-based adapters.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called sky2.  This is recommended.
@@ -2040,8 +2062,15 @@
 	depends on PCI
 	---help---
 	  Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
-	  compliant Gigabit Ethernet Adapter. The following adapters are supported
-	  by this driver:
+	  compliant Gigabit Ethernet Adapter.
+
+	  This driver supports the original Yukon chipset. A cleaner driver is 
+	  also available (skge) which seems to work better than this one.
+
+	  This driver does not support the newer Yukon2 chipset. A seperate
+	  driver, sky2, is provided to support Yukon2-based adapters.
+
+	  The following adapters are supported by this driver:
 	    - 3Com 3C940 Gigabit LOM Ethernet Adapter
 	    - 3Com 3C941 Gigabit LOM Ethernet Adapter
 	    - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
@@ -2686,8 +2715,6 @@
 	If you want to log kernel messages over the network, enable this.
 	See <file:Documentation/networking/netconsole.txt> for details.
 
-endif #NETDEVICES
-
 config NETPOLL
 	def_bool NETCONSOLE
 
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index b8953de..b508812 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -1002,6 +1002,8 @@
 
 	mac1 = 0;
 	for(i = 0; i < 4; i++) {
+		int tmp;
+
 		mac1 = mac1 << 8;
 		tmp = read_eeprom_byte(dev, 0x8c+i);
 		if (tmp < 0) {
@@ -1012,6 +1014,8 @@
 	}
 	mac2 = 0;
 	for(i = 4; i < 8; i++) {
+		int tmp;
+
 		mac2 = mac2 << 8;
 		tmp = read_eeprom_byte(dev, 0x8c+i);
 		if (tmp < 0) {
diff --git a/drivers/net/appletalk/cops.h b/drivers/net/appletalk/cops.h
index c68ba9c..fd2750b 100644
--- a/drivers/net/appletalk/cops.h
+++ b/drivers/net/appletalk/cops.h
@@ -51,7 +51,7 @@
 struct ltfirmware
 {
         unsigned int length;
-        unsigned char * data;
+        const unsigned char *data;
 };
 
 #define DAYNA 1
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index df9d6e8..c3267e4 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1399,7 +1399,6 @@
 	b44_init_rings(bp);
 	b44_init_hw(bp);
 
-	netif_carrier_off(dev);
 	b44_check_phy(bp);
 
 	err = request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev);
@@ -1464,7 +1463,7 @@
 #endif
 	b44_halt(bp);
 	b44_free_rings(bp);
-	netif_carrier_off(bp->dev);
+	netif_carrier_off(dev);
 
 	spin_unlock_irq(&bp->lock);
 
@@ -2000,6 +1999,8 @@
 	dev->irq = pdev->irq;
 	SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
 
+	netif_carrier_off(dev);
+
 	err = b44_get_invariants(bp);
 	if (err) {
 		printk(KERN_ERR PFX "Problem fetching invariants of chip, "
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 49fa1e4..a24200d 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -1,6 +1,6 @@
 /* bnx2.c: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004, 2005 Broadcom Corporation
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.4.30"
-#define DRV_MODULE_RELDATE	"October 11, 2005"
+#define DRV_MODULE_VERSION	"1.4.31"
+#define DRV_MODULE_RELDATE	"January 19, 2006"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -316,6 +316,10 @@
 	u32 val;
 
 	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+	       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+	       BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx);
+
+	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
 	       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx);
 
 	val = REG_RD(bp, BNX2_HC_COMMAND);
@@ -1171,7 +1175,8 @@
 	}
 
 	if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
-	    (CHIP_ID(bp) == CHIP_ID_5708_B0)) {
+	    (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
+	    (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
 		/* increase tx signal amplitude */
 		bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
 			       BCM5708S_BLK_ADDR_TX_MISC);
@@ -1326,44 +1331,78 @@
 	return 0;
 }
 
+static int bnx2_test_link(struct bnx2 *);
+
 static int
-bnx2_fw_sync(struct bnx2 *bp, u32 msg_data)
+bnx2_set_phy_loopback(struct bnx2 *bp)
+{
+	u32 mac_mode;
+	int rc, i;
+
+	spin_lock_bh(&bp->phy_lock);
+	rc = bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
+			    BMCR_SPEED1000);
+	spin_unlock_bh(&bp->phy_lock);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < 10; i++) {
+		if (bnx2_test_link(bp) == 0)
+			break;
+		udelay(10);
+	}
+
+	mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
+	mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
+		      BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
+		      BNX2_EMAC_MODE_25G);
+
+	mac_mode |= BNX2_EMAC_MODE_PORT_GMII;
+	REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
+	bp->link_up = 1;
+	return 0;
+}
+
+static int
+bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
 {
 	int i;
 	u32 val;
 
-	if (bp->fw_timed_out)
-		return -EBUSY;
-
 	bp->fw_wr_seq++;
 	msg_data |= bp->fw_wr_seq;
 
 	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
 
 	/* wait for an acknowledgement. */
-	for (i = 0; i < (FW_ACK_TIME_OUT_MS * 1000)/5; i++) {
-		udelay(5);
+	for (i = 0; i < (FW_ACK_TIME_OUT_MS / 10); i++) {
+		msleep(10);
 
 		val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB);
 
 		if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ))
 			break;
 	}
+	if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0)
+		return 0;
 
 	/* If we timed out, inform the firmware that this is the case. */
-	if (((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) &&
-		((msg_data & BNX2_DRV_MSG_DATA) != BNX2_DRV_MSG_DATA_WAIT0)) {
+	if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
+		if (!silent)
+			printk(KERN_ERR PFX "fw sync timeout, reset code = "
+					    "%x\n", msg_data);
 
 		msg_data &= ~BNX2_DRV_MSG_CODE;
 		msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
 
 		REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
 
-		bp->fw_timed_out = 1;
-
 		return -EBUSY;
 	}
 
+	if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK)
+		return -EIO;
+
 	return 0;
 }
 
@@ -1657,7 +1696,7 @@
 	rmb();
 	while (sw_cons != hw_cons) {
 		unsigned int len;
-		u16 status;
+		u32 status;
 		struct sw_bd *rx_buf;
 		struct sk_buff *skb;
 
@@ -1673,7 +1712,7 @@
 		rx_hdr = (struct l2_fhdr *) skb->data;
 		len = rx_hdr->l2_fhdr_pkt_len - 4;
 
-		if (rx_hdr->l2_fhdr_errors &
+		if ((status = rx_hdr->l2_fhdr_status) &
 			(L2_FHDR_ERRORS_BAD_CRC |
 			L2_FHDR_ERRORS_PHY_DECODE |
 			L2_FHDR_ERRORS_ALIGNMENT |
@@ -1732,15 +1771,13 @@
 
 		}
 
-		status = rx_hdr->l2_fhdr_status;
 		skb->ip_summed = CHECKSUM_NONE;
 		if (bp->rx_csum &&
 			(status & (L2_FHDR_STATUS_TCP_SEGMENT |
 			L2_FHDR_STATUS_UDP_DATAGRAM))) {
 
-			u16 cksum = rx_hdr->l2_fhdr_tcp_udp_xsum;
-
-			if (cksum == 0xffff)
+			if (likely((status & (L2_FHDR_ERRORS_TCP_XSUM |
+					      L2_FHDR_ERRORS_UDP_XSUM)) == 0))
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
 		}
 
@@ -1794,7 +1831,7 @@
 bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_instance;
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	prefetch(bp->status_blk);
 	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
@@ -1814,7 +1851,7 @@
 bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_instance;
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	/* When using INTx, it is possible for the interrupt to arrive
 	 * at the CPU before the status block posted prior to the
@@ -1859,7 +1896,7 @@
 static int
 bnx2_poll(struct net_device *dev, int *budget)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	if ((bp->status_blk->status_attn_bits &
 		STATUS_ATTN_BITS_LINK_STATE) !=
@@ -1891,9 +1928,20 @@
 
 	if (!bnx2_has_work(bp)) {
 		netif_rx_complete(dev);
+		if (likely(bp->flags & USING_MSI_FLAG)) {
+			REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+			       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+			       bp->last_status_idx);
+			return 0;
+		}
 		REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-			BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-			bp->last_status_idx);
+		       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+		       BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+		       bp->last_status_idx);
+
+		REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+		       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+		       bp->last_status_idx);
 		return 0;
 	}
 
@@ -1906,7 +1954,7 @@
 static void
 bnx2_set_rx_mode(struct net_device *dev)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	u32 rx_mode, sort_mode;
 	int i;
 
@@ -1916,11 +1964,11 @@
 				  BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
 	sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
 #ifdef BCM_VLAN
-	if (!bp->vlgrp) {
+	if (!bp->vlgrp && !(bp->flags & ASF_ENABLE_FLAG))
 		rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
-	}
 #else
-	rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
+	if (!(bp->flags & ASF_ENABLE_FLAG))
+		rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
 #endif
 	if (dev->flags & IFF_PROMISC) {
 		/* Promiscuous mode. */
@@ -2338,7 +2386,6 @@
 			val |= BNX2_EMAC_MODE_PORT_MII |
 			       BNX2_EMAC_MODE_MPKT_RCVD |
 			       BNX2_EMAC_MODE_ACPI_RCVD |
-			       BNX2_EMAC_MODE_FORCE_LINK |
 			       BNX2_EMAC_MODE_MPKT;
 
 			REG_WR(bp, BNX2_EMAC_MODE, val);
@@ -2374,7 +2421,8 @@
 			wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
 		}
 
-		bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg);
+		if (!(bp->flags & NO_WOL_FLAG))
+			bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 0);
 
 		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
 		if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
@@ -2708,9 +2756,16 @@
 	if (j == entry_count) {
 		bp->flash_info = NULL;
 		printk(KERN_ALERT PFX "Unknown flash/EEPROM type.\n");
-		rc = -ENODEV;
+		return -ENODEV;
 	}
 
+	val = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG2);
+	val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK;
+	if (val)
+		bp->flash_size = val;
+	else
+		bp->flash_size = bp->flash_info->total_size;
+
 	return rc;
 }
 
@@ -3014,16 +3069,14 @@
 	val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
 	udelay(5);
 
+	/* Wait for the firmware to tell us it is ok to issue a reset. */
+	bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1);
+
 	/* Deposit a driver reset signature so the firmware knows that
 	 * this is a soft reset. */
 	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE,
 		   BNX2_DRV_RESET_SIGNATURE_MAGIC);
 
-	bp->fw_timed_out = 0;
-
-	/* Wait for the firmware to tell us it is ok to issue a reset. */
-	bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code);
-
 	/* Do a dummy read to force the chip to complete all current transaction
 	 * before we issue a reset. */
 	val = REG_RD(bp, BNX2_MISC_ID);
@@ -3062,10 +3115,10 @@
 		return -ENODEV;
 	}
 
-	bp->fw_timed_out = 0;
-
 	/* Wait for the firmware to finish its initialization. */
-	bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code);
+	rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 0);
+	if (rc)
+		return rc;
 
 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
 		/* Adjust the voltage regular to two steps lower.  The default
@@ -3083,6 +3136,7 @@
 bnx2_init_chip(struct bnx2 *bp)
 {
 	u32 val;
+	int rc;
 
 	/* Make sure the interrupt is not active. */
 	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
@@ -3098,7 +3152,7 @@
 
 	val |= (0x2 << 20) | (1 << 11);
 
-	if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz = 133))
+	if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz == 133))
 		val |= (1 << 23);
 
 	if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
@@ -3218,17 +3272,22 @@
 
 	REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
 
+	if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) &
+	    BNX2_PORT_FEATURE_ASF_ENABLED)
+		bp->flags |= ASF_ENABLE_FLAG;
+
 	/* Initialize the receive filter. */
 	bnx2_set_rx_mode(bp->dev);
 
-	bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET);
+	rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
+			  0);
 
 	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff);
 	REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
 
 	udelay(20);
 
-	return 0;
+	return rc;
 }
 
 
@@ -3880,26 +3939,33 @@
 	return ret;
 }
 
+#define BNX2_MAC_LOOPBACK	0
+#define BNX2_PHY_LOOPBACK	1
+
 static int
-bnx2_test_loopback(struct bnx2 *bp)
+bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 {
 	unsigned int pkt_size, num_pkts, i;
 	struct sk_buff *skb, *rx_skb;
 	unsigned char *packet;
-	u16 rx_start_idx, rx_idx, send_idx;
-	u32 send_bseq, val;
+	u16 rx_start_idx, rx_idx;
+	u32 val;
 	dma_addr_t map;
 	struct tx_bd *txbd;
 	struct sw_bd *rx_buf;
 	struct l2_fhdr *rx_hdr;
 	int ret = -ENODEV;
 
-	if (!netif_running(bp->dev))
-		return -ENODEV;
-
-	bp->loopback = MAC_LOOPBACK;
-	bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_DIAG);
-	bnx2_set_mac_loopback(bp);
+	if (loopback_mode == BNX2_MAC_LOOPBACK) {
+		bp->loopback = MAC_LOOPBACK;
+		bnx2_set_mac_loopback(bp);
+	}
+	else if (loopback_mode == BNX2_PHY_LOOPBACK) {
+		bp->loopback = 0;
+		bnx2_set_phy_loopback(bp);
+	}
+	else
+		return -EINVAL;
 
 	pkt_size = 1514;
 	skb = dev_alloc_skb(pkt_size);
@@ -3921,11 +3987,9 @@
 	udelay(5);
 	rx_start_idx = bp->status_blk->status_rx_quick_consumer_index0;
 
-	send_idx = 0;
-	send_bseq = 0;
 	num_pkts = 0;
 
-	txbd = &bp->tx_desc_ring[send_idx];
+	txbd = &bp->tx_desc_ring[TX_RING_IDX(bp->tx_prod)];
 
 	txbd->tx_bd_haddr_hi = (u64) map >> 32;
 	txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff;
@@ -3933,13 +3997,11 @@
 	txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
 
 	num_pkts++;
-	send_idx = NEXT_TX_BD(send_idx);
+	bp->tx_prod = NEXT_TX_BD(bp->tx_prod);
+	bp->tx_prod_bseq += pkt_size;
 
-	send_bseq += pkt_size;
-
-	REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, send_idx);
-	REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, send_bseq);
-
+	REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, bp->tx_prod);
+	REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
 
 	udelay(100);
 
@@ -3952,7 +4014,7 @@
 	pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE);
 	dev_kfree_skb_irq(skb);
 
-	if (bp->status_blk->status_tx_quick_consumer_index0 != send_idx) {
+	if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_prod) {
 		goto loopback_test_done;
 	}
 
@@ -3971,7 +4033,7 @@
 		pci_unmap_addr(rx_buf, mapping),
 		bp->rx_buf_size, PCI_DMA_FROMDEVICE);
 
-	if (rx_hdr->l2_fhdr_errors &
+	if (rx_hdr->l2_fhdr_status &
 		(L2_FHDR_ERRORS_BAD_CRC |
 		L2_FHDR_ERRORS_PHY_DECODE |
 		L2_FHDR_ERRORS_ALIGNMENT |
@@ -3998,6 +4060,30 @@
 	return ret;
 }
 
+#define BNX2_MAC_LOOPBACK_FAILED	1
+#define BNX2_PHY_LOOPBACK_FAILED	2
+#define BNX2_LOOPBACK_FAILED		(BNX2_MAC_LOOPBACK_FAILED |	\
+					 BNX2_PHY_LOOPBACK_FAILED)
+
+static int
+bnx2_test_loopback(struct bnx2 *bp)
+{
+	int rc = 0;
+
+	if (!netif_running(bp->dev))
+		return BNX2_LOOPBACK_FAILED;
+
+	bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
+	spin_lock_bh(&bp->phy_lock);
+	bnx2_init_phy(bp);
+	spin_unlock_bh(&bp->phy_lock);
+	if (bnx2_run_loopback(bp, BNX2_MAC_LOOPBACK))
+		rc |= BNX2_MAC_LOOPBACK_FAILED;
+	if (bnx2_run_loopback(bp, BNX2_PHY_LOOPBACK))
+		rc |= BNX2_PHY_LOOPBACK_FAILED;
+	return rc;
+}
+
 #define NVRAM_SIZE 0x200
 #define CRC32_RESIDUAL 0xdebb20e3
 
@@ -4167,7 +4253,7 @@
 static int
 bnx2_open(struct net_device *dev)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	int rc;
 
 	bnx2_set_power_state(bp, PCI_D0);
@@ -4280,7 +4366,7 @@
 static void
 bnx2_tx_timeout(struct net_device *dev)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	/* This allows the netif to be shutdown gracefully before resetting */
 	schedule_work(&bp->reset_task);
@@ -4291,7 +4377,7 @@
 static void
 bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	bnx2_netif_stop(bp);
 
@@ -4305,7 +4391,7 @@
 static void
 bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	bnx2_netif_stop(bp);
 
@@ -4326,7 +4412,7 @@
 static int
 bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	dma_addr_t mapping;
 	struct tx_bd *txbd;
 	struct sw_bd *tx_buf;
@@ -4455,7 +4541,7 @@
 static int
 bnx2_close(struct net_device *dev)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	u32 reset_code;
 
 	/* Calling flush_scheduled_work() may deadlock because
@@ -4467,7 +4553,9 @@
 
 	bnx2_netif_stop(bp);
 	del_timer_sync(&bp->timer);
-	if (bp->wol)
+	if (bp->flags & NO_WOL_FLAG)
+		reset_code = BNX2_DRV_MSG_CODE_UNLOAD;
+	else if (bp->wol)
 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
 	else
 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
@@ -4501,7 +4589,7 @@
 static struct net_device_stats *
 bnx2_get_stats(struct net_device *dev)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	struct statistics_block *stats_blk = bp->stats_blk;
 	struct net_device_stats *net_stats = &bp->net_stats;
 
@@ -4575,7 +4663,7 @@
 static int
 bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	cmd->supported = SUPPORTED_Autoneg;
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
@@ -4622,7 +4710,7 @@
 static int
 bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	u8 autoneg = bp->autoneg;
 	u8 req_duplex = bp->req_duplex;
 	u16 req_line_speed = bp->req_line_speed;
@@ -4694,7 +4782,7 @@
 static void
 bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	strcpy(info->driver, DRV_MODULE_NAME);
 	strcpy(info->version, DRV_MODULE_VERSION);
@@ -4702,15 +4790,14 @@
 	info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0';
 	info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0';
 	info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0';
-	info->fw_version[6] = (bp->fw_ver & 0xff) + '0';
-	info->fw_version[1] = info->fw_version[3] = info->fw_version[5] = '.';
-	info->fw_version[7] = 0;
+	info->fw_version[1] = info->fw_version[3] = '.';
+	info->fw_version[5] = 0;
 }
 
 static void
 bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	if (bp->flags & NO_WOL_FLAG) {
 		wol->supported = 0;
@@ -4729,7 +4816,7 @@
 static int
 bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
@@ -4749,7 +4836,7 @@
 static int
 bnx2_nway_reset(struct net_device *dev)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	u32 bmcr;
 
 	if (!(bp->autoneg & AUTONEG_SPEED)) {
@@ -4785,19 +4872,19 @@
 static int
 bnx2_get_eeprom_len(struct net_device *dev)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
-	if (bp->flash_info == 0)
+	if (bp->flash_info == NULL)
 		return 0;
 
-	return (int) bp->flash_info->total_size;
+	return (int) bp->flash_size;
 }
 
 static int
 bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 		u8 *eebuf)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	int rc;
 
 	/* parameters already validated in ethtool_get_eeprom */
@@ -4811,7 +4898,7 @@
 bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 		u8 *eebuf)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	int rc;
 
 	/* parameters already validated in ethtool_set_eeprom */
@@ -4824,7 +4911,7 @@
 static int
 bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	memset(coal, 0, sizeof(struct ethtool_coalesce));
 
@@ -4846,7 +4933,7 @@
 static int
 bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	bp->rx_ticks = (u16) coal->rx_coalesce_usecs;
 	if (bp->rx_ticks > 0x3ff) bp->rx_ticks = 0x3ff;
@@ -4890,7 +4977,7 @@
 static void
 bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	ering->rx_max_pending = MAX_RX_DESC_CNT;
 	ering->rx_mini_max_pending = 0;
@@ -4907,7 +4994,7 @@
 static int
 bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	if ((ering->rx_pending > MAX_RX_DESC_CNT) ||
 		(ering->tx_pending > MAX_TX_DESC_CNT) ||
@@ -4930,7 +5017,7 @@
 static void
 bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	epause->autoneg = ((bp->autoneg & AUTONEG_FLOW_CTRL) != 0);
 	epause->rx_pause = ((bp->flow_ctrl & FLOW_CTRL_RX) != 0);
@@ -4940,7 +5027,7 @@
 static int
 bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	bp->req_flow_ctrl = 0;
 	if (epause->rx_pause)
@@ -4967,7 +5054,7 @@
 static u32
 bnx2_get_rx_csum(struct net_device *dev)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	return bp->rx_csum;
 }
@@ -4975,7 +5062,7 @@
 static int
 bnx2_set_rx_csum(struct net_device *dev, u32 data)
 {
-  	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	bp->rx_csum = data;
 	return 0;
@@ -5124,7 +5211,7 @@
 static void
 bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS);
 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
@@ -5140,10 +5227,8 @@
 			buf[1] = 1;
 			etest->flags |= ETH_TEST_FL_FAILED;
 		}
-		if (bnx2_test_loopback(bp) != 0) {
-			buf[2] = 1;
+		if ((buf[2] = bnx2_test_loopback(bp)) != 0)
 			etest->flags |= ETH_TEST_FL_FAILED;
-		}
 
 		if (!netif_running(bp->dev)) {
 			bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
@@ -5200,7 +5285,7 @@
 bnx2_get_ethtool_stats(struct net_device *dev,
 		struct ethtool_stats *stats, u64 *buf)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	int i;
 	u32 *hw_stats = (u32 *) bp->stats_blk;
 	u8 *stats_len_arr = NULL;
@@ -5240,7 +5325,7 @@
 static int
 bnx2_phys_id(struct net_device *dev, u32 data)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	int i;
 	u32 save;
 
@@ -5312,7 +5397,7 @@
 bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct mii_ioctl_data *data = if_mii(ifr);
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	int err;
 
 	switch(cmd) {
@@ -5354,7 +5439,7 @@
 bnx2_change_mac_addr(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr = p;
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EINVAL;
@@ -5370,7 +5455,7 @@
 static int
 bnx2_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
 		((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE))
@@ -5391,7 +5476,7 @@
 static void
 poll_bnx2(struct net_device *dev)
 {
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	disable_irq(bp->pdev->irq);
 	bnx2_interrupt(bp->pdev->irq, dev, NULL);
@@ -5409,7 +5494,7 @@
 
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
-	bp = dev->priv;
+	bp = netdev_priv(dev);
 
 	bp->flags = 0;
 	bp->phy_flags = 0;
@@ -5629,6 +5714,9 @@
 		}
 	}
 
+	if (CHIP_NUM(bp) == CHIP_NUM_5708)
+		bp->flags |= NO_WOL_FLAG;
+
 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
 		bp->tx_quick_cons_trip_int =
 			bp->tx_quick_cons_trip;
@@ -5725,7 +5813,7 @@
 	dev->ethtool_ops = &bnx2_ethtool_ops;
 	dev->weight = 64;
 
-	bp = dev->priv;
+	bp = netdev_priv(dev);
 
 #if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
 	dev->poll_controller = poll_bnx2;
@@ -5784,7 +5872,7 @@
 bnx2_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	flush_scheduled_work();
 
@@ -5803,7 +5891,7 @@
 bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 	u32 reset_code;
 
 	if (!netif_running(dev))
@@ -5812,7 +5900,9 @@
 	bnx2_netif_stop(bp);
 	netif_device_detach(dev);
 	del_timer_sync(&bp->timer);
-	if (bp->wol)
+	if (bp->flags & NO_WOL_FLAG)
+		reset_code = BNX2_DRV_MSG_CODE_UNLOAD;
+	else if (bp->wol)
 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
 	else
 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
@@ -5826,7 +5916,7 @@
 bnx2_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2 *bp = dev->priv;
+	struct bnx2 *bp = netdev_priv(dev);
 
 	if (!netif_running(dev))
 		return 0;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 76bb5f1..9f691cb 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -1,6 +1,6 @@
 /* bnx2.h: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004, 2005 Broadcom Corporation
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -277,19 +277,7 @@
  *  l2_fhdr definition
  */
 struct l2_fhdr {
-#if defined(__BIG_ENDIAN)
-	u16 l2_fhdr_errors;
-	u16 l2_fhdr_status;
-#elif defined(__LITTLE_ENDIAN)
-	u16 l2_fhdr_status;
-	u16 l2_fhdr_errors;
-#endif
-		#define L2_FHDR_ERRORS_BAD_CRC		(1<<1)
-		#define L2_FHDR_ERRORS_PHY_DECODE	(1<<2)
-		#define L2_FHDR_ERRORS_ALIGNMENT	(1<<3)
-		#define L2_FHDR_ERRORS_TOO_SHORT	(1<<4)
-		#define L2_FHDR_ERRORS_GIANT_FRAME	(1<<5)
-
+	u32 l2_fhdr_status;
 		#define L2_FHDR_STATUS_RULE_CLASS	(0x7<<0)
 		#define L2_FHDR_STATUS_RULE_P2		(1<<3)
 		#define L2_FHDR_STATUS_RULE_P3		(1<<4)
@@ -301,6 +289,14 @@
 		#define L2_FHDR_STATUS_TCP_SEGMENT	(1<<14)
 		#define L2_FHDR_STATUS_UDP_DATAGRAM	(1<<15)
 
+		#define L2_FHDR_ERRORS_BAD_CRC		(1<<17)
+		#define L2_FHDR_ERRORS_PHY_DECODE	(1<<18)
+		#define L2_FHDR_ERRORS_ALIGNMENT	(1<<19)
+		#define L2_FHDR_ERRORS_TOO_SHORT	(1<<20)
+		#define L2_FHDR_ERRORS_GIANT_FRAME	(1<<21)
+		#define L2_FHDR_ERRORS_TCP_XSUM		(1<<28)
+		#define L2_FHDR_ERRORS_UDP_XSUM		(1<<31)
+
 	u32 l2_fhdr_hash;
 #if defined(__BIG_ENDIAN)
 	u16 l2_fhdr_pkt_len;
@@ -3956,6 +3952,7 @@
 #define NO_WOL_FLAG			8
 #define USING_DAC_FLAG			0x10
 #define USING_MSI_FLAG			0x20
+#define ASF_ENABLE_FLAG			0x40
 
 	u32			phy_flags;
 #define PHY_SERDES_FLAG			1
@@ -3986,6 +3983,7 @@
 #define CHIP_ID_5706_A2			0x57060020
 #define CHIP_ID_5708_A0			0x57080000
 #define CHIP_ID_5708_B0			0x57081000
+#define CHIP_ID_5708_B1			0x57081010
 
 #define CHIP_BOND_ID(bp)		(((bp)->chip_id) & 0xf)
 
@@ -3998,7 +3996,7 @@
 	u16			bus_speed_mhz;
 	u8			wol;
 
-	u8			fw_timed_out;
+	u8			pad;
 
 	u16			fw_wr_seq;
 	u16			fw_drv_pulse_wr_seq;
@@ -4074,6 +4072,7 @@
 	struct net_device_stats net_stats;
 
 	struct flash_spec	*flash_info;
+	u32			flash_size;
 };
 
 static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
@@ -4172,7 +4171,7 @@
  * the firmware has timed out, the driver will assume there is no firmware
  * running and there won't be any firmware-driver synchronization during a
  * driver reset. */
-#define FW_ACK_TIME_OUT_MS                  50
+#define FW_ACK_TIME_OUT_MS                  100
 
 
 #define BNX2_DRV_RESET_SIGNATURE		0x00000000
@@ -4275,6 +4274,9 @@
 #define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1	 0x100
 #define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2	 0x200
 
+#define BNX2_SHARED_HW_CFG_CONFIG2		0x00000040
+#define BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK	 0x00fff000
+
 #define BNX2_DEV_INFO_BC_REV			0x0000004c
 
 #define BNX2_PORT_HW_CFG_MAC_UPPER		0x00000050
diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h
index ab07a49..0c21bd8 100644
--- a/drivers/net/bnx2_fw.h
+++ b/drivers/net/bnx2_fw.h
@@ -1,6 +1,6 @@
 /* bnx2_fw.h: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004, 2005 Broadcom Corporation
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -978,20 +978,20 @@
 static int bnx2_RXP_b06FwReleaseMajor = 0x1;
 static int bnx2_RXP_b06FwReleaseMinor = 0x0;
 static int bnx2_RXP_b06FwReleaseFix = 0x0;
-static u32 bnx2_RXP_b06FwStartAddr = 0x08003104;
+static u32 bnx2_RXP_b06FwStartAddr = 0x08003184;
 static u32 bnx2_RXP_b06FwTextAddr = 0x08000000;
-static int bnx2_RXP_b06FwTextLen = 0x562c;
-static u32 bnx2_RXP_b06FwDataAddr = 0x08005660;
+static int bnx2_RXP_b06FwTextLen = 0x588c;
+static u32 bnx2_RXP_b06FwDataAddr = 0x080058e0;
 static int bnx2_RXP_b06FwDataLen = 0x0;
-static u32 bnx2_RXP_b06FwRodataAddr = 0x00000000;
-static int bnx2_RXP_b06FwRodataLen = 0x0;
-static u32 bnx2_RXP_b06FwBssAddr = 0x08005680;
-static int bnx2_RXP_b06FwBssLen = 0x1394;
-static u32 bnx2_RXP_b06FwSbssAddr = 0x08005660;
-static int bnx2_RXP_b06FwSbssLen = 0x18;
-static u32 bnx2_RXP_b06FwText[(0x562c/4) + 1] = {
-	0x0a000c41, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e352e,
-	0x38000000, 0x02050803, 0x00000000, 0x0000000d, 0x00000000, 0x00000000,
+static u32 bnx2_RXP_b06FwRodataAddr = 0x08005890;
+static int bnx2_RXP_b06FwRodataLen = 0x28;
+static u32 bnx2_RXP_b06FwBssAddr = 0x08005900;
+static int bnx2_RXP_b06FwBssLen = 0x13a4;
+static u32 bnx2_RXP_b06FwSbssAddr = 0x080058e0;
+static int bnx2_RXP_b06FwSbssLen = 0x1c;
+static u32 bnx2_RXP_b06FwText[(0x588c/4) + 1] = {
+	0x0a000c61, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e362e,
+	0x31000000, 0x02060103, 0x00000000, 0x0000000d, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -1513,408 +1513,435 @@
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24425660,
-	0x3c030800, 0x24636a14, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004,
-	0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x26103104, 0x3c1c0800,
-	0x279c5660, 0x0e001035, 0x00000000, 0x0000000d, 0x3c080800, 0x8d023100,
-	0x2c420080, 0x50400001, 0xad003100, 0x8d073100, 0x3c040800, 0x24840100,
-	0x8f460100, 0x00071840, 0x00671821, 0x00031940, 0x00641021, 0xac460000,
-	0x8f450104, 0x00831021, 0xac450004, 0x8f460108, 0xac460008, 0x8f45010c,
-	0xac45000c, 0x8f460114, 0xac460010, 0x8f450118, 0xac450014, 0x8f460124,
-	0xac460018, 0x8f450128, 0xac45001c, 0x8f464010, 0xac460020, 0x8f454014,
-	0xac450024, 0x8f464018, 0xac460028, 0x8f45401c, 0xac45002c, 0x8f464020,
-	0xac460030, 0x8f454024, 0xac450034, 0x8f464028, 0xac460038, 0x8f45402c,
-	0xac45003c, 0x8f464030, 0xac460040, 0x8f454034, 0xac450044, 0x8f464038,
-	0xac460048, 0x8f45403c, 0xac45004c, 0x8f464040, 0xac460050, 0x8f454044,
-	0xac450054, 0x8f464048, 0xac460058, 0x8f45404c, 0x24e70001, 0x00402021,
-	0xad073100, 0x03e00008, 0xac85005c, 0x8f820004, 0x9743010c, 0x00804821,
-	0x00403021, 0x30421000, 0x10400010, 0x306affff, 0x30c20020, 0x1440000e,
-	0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff, 0x3463ffff,
-	0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001, 0x0a000cb1,
-	0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d, 0x00405821,
-	0x8f820010, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01, 0x00c24024,
-	0x3c031000, 0x15030015, 0x3c020001, 0x31420200, 0x54400012, 0x3c020001,
-	0x9744010e, 0x24020003, 0xa342018b, 0x97850012, 0x24020002, 0x34e30002,
-	0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff, 0xa744018e,
-	0xa74501a6, 0xaf4801b8, 0x03e00008, 0x00001021, 0x3c020001, 0x00c21024,
-	0x10400039, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c,
-	0x24020080, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005,
-	0xa7440190, 0x9743011c, 0x9742011e, 0x0a000cec, 0x00021400, 0x9743011e,
-	0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x24020003,
-	0x30838000, 0x1060000d, 0xa7420188, 0x93420116, 0x304200fc, 0x005a1021,
-	0x24424004, 0x8c430000, 0x3063ffff, 0x14600005, 0x00000000, 0x3c02ffff,
-	0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104,
-	0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
-	0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f820010, 0x30434000,
-	0x10600016, 0x00404021, 0x3c020f00, 0x00c21024, 0x14400012, 0x00000000,
-	0x93420116, 0x34424000, 0x03421821, 0x94650002, 0x2ca21389, 0x1040000b,
-	0x3c020800, 0x24425680, 0x00051942, 0x00031880, 0x00621821, 0x30a5001f,
-	0x8c640000, 0x24020001, 0x00a21004, 0x00822024, 0x01244825, 0x11200039,
-	0x3c021000, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3046ffff,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006,
-	0x8f85000c, 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e,
-	0x10a00005, 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000d41, 0x00021400,
-	0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010,
-	0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021,
-	0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
-	0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff,
-	0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
-	0xaf4201b8, 0x03e00008, 0x00001021, 0x00c21024, 0x104000e3, 0x3c020800,
-	0x8c430030, 0x10600040, 0x31024000, 0x1040003e, 0x3c030f00, 0x00c31824,
-	0x3c020100, 0x0043102b, 0x1440003a, 0x3c030800, 0x9742010e, 0x34e70002,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d,
+	0x3c020800, 0x244258e0, 0x3c030800, 0x24636ca4, 0xac400000, 0x0043202b,
+	0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800,
+	0x26103184, 0x3c1c0800, 0x279c58e0, 0x0e00104a, 0x00000000, 0x0000000d,
+	0x27bdffe8, 0xafb00010, 0xafbf0014, 0x0e000f1d, 0x00808021, 0x1440000d,
+	0x00000000, 0x8f820010, 0x10400005, 0x00000000, 0x9743011c, 0x9742011e,
+	0x0a000c89, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825,
+	0xaf830004, 0x8f840008, 0x3c020020, 0x34424000, 0x00821824, 0x54620004,
+	0x3c020020, 0x8f820014, 0x0a000c9a, 0x34421000, 0x34428000, 0x00821824,
+	0x14620004, 0x00000000, 0x8f820014, 0x34428000, 0xaf820014, 0x8f820008,
+	0x9743010c, 0x00403021, 0x30421000, 0x10400010, 0x3069ffff, 0x30c20020,
+	0x1440000e, 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff,
+	0x3463ffff, 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001,
+	0x0a000cb2, 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d,
+	0x00405821, 0x8f820014, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01,
+	0x00c24024, 0x3c031000, 0x15030015, 0x3c020001, 0x31220200, 0x14400012,
+	0x3c020001, 0x9744010e, 0x24020003, 0xa342018b, 0x97850016, 0x24020002,
+	0x34e30002, 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff,
+	0xa744018e, 0xa74501a6, 0xaf4801b8, 0x0a000f19, 0x00001021, 0x3c020001,
+	0x00c21024, 0x1040002f, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff,
+	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9784000a,
+	0x8f850004, 0x8f870014, 0x24020080, 0x24030002, 0xaf420180, 0x24020003,
+	0xa743018c, 0xa746018e, 0xa7420188, 0x30e28000, 0xa7440190, 0x1040000c,
+	0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000,
+	0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014,
+	0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff,
+	0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19,
+	0x00001021, 0x8f820014, 0x30434000, 0x10600016, 0x00404021, 0x3c020f00,
+	0x00c21024, 0x14400012, 0x00000000, 0x93420116, 0x34424000, 0x03421821,
+	0x94650002, 0x2ca21389, 0x1040000b, 0x3c020800, 0x24425900, 0x00051942,
+	0x00031880, 0x00621821, 0x30a5001f, 0x8c640000, 0x24020001, 0x00a21004,
+	0x00822024, 0x02048025, 0x12000030, 0x3c021000, 0x9742010e, 0x34e80002,
 	0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, 0x24020080, 0x24030002,
-	0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, 0xa7440190, 0x9743011c,
-	0x9742011e, 0x0a000d86, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400,
-	0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188,
-	0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff,
-	0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, 0x97820012,
-	0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825,
-	0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021,
-	0x3c030800, 0x8c620024, 0x30420008, 0x1040003e, 0x34e80002, 0x3c020f00,
-	0x00c21024, 0x1440003b, 0x8d620034, 0x31420200, 0x10400038, 0x8d620034,
-	0x9742010e, 0x30e7fffb, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c,
-	0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005,
-	0xa7440190, 0x9743011c, 0x9742011e, 0x0a000dca, 0x00021400, 0x9743011e,
-	0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000,
-	0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
-	0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024,
-	0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
-	0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
-	0x8d620034, 0x8f860004, 0x1040001a, 0x30c20100, 0x10400018, 0x3c020f00,
-	0x00c21024, 0x3c030200, 0x10430014, 0x00000000, 0x8f82000c, 0x10400004,
-	0x00000000, 0x9742011c, 0x0a000df8, 0x3044ffff, 0x9742011e, 0x3044ffff,
-	0x3c030800, 0x8c620038, 0x3c030800, 0x2463003c, 0x2442ffff, 0x00822024,
-	0x00831821, 0x90620000, 0x24420004, 0x0a000e0d, 0x000229c0, 0x00000000,
-	0x00061602, 0x3042000f, 0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300,
-	0x0062182b, 0x50600001, 0x24050800, 0x9742010e, 0x3107ffff, 0x3c038000,
+	0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180,
+	0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
+	0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
+	0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+	0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
+	0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+	0xaf4201b8, 0x0a000f19, 0x00001021, 0x00c21024, 0x104000c0, 0x3c020800,
+	0x8c430030, 0x10600037, 0x31024000, 0x10400035, 0x3c030f00, 0x00c31824,
+	0x3c020100, 0x0043102b, 0x14400031, 0x3c030800, 0x9742010e, 0x34e80002,
+	0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+	0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020080,
+	0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
+	0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
+	0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+	0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
+	0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+	0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008,
+	0x10400035, 0x34ea0002, 0x3c020f00, 0x00c21024, 0x14400032, 0x8d620034,
+	0x31220200, 0x1040002f, 0x8d620034, 0x9742010e, 0x30e8fffb, 0x3c038000,
 	0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
-	0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf450180, 0xa742018c,
-	0xa746018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a000e26,
-	0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8,
-	0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc,
-	0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
-	0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104,
-	0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
-	0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f424000, 0x30420100,
-	0x104000f9, 0x3c020800, 0x8c440024, 0x24030001, 0x14830038, 0x00404821,
-	0x9742010e, 0x34e60002, 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97830006, 0x8f84000c,
-	0x24020002, 0xaf400180, 0xa742018c, 0xa745018e, 0x10800005, 0xa7430190,
-	0x9743011c, 0x9742011e, 0x0a000e65, 0x00021400, 0x9743011e, 0x9742011c,
-	0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c,
-	0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000,
-	0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010,
-	0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff,
-	0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008,
-	0x00001021, 0x30820001, 0x10400037, 0x30ea0004, 0x9742010e, 0x30e8fffb,
-	0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x24020003, 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf400180,
-	0xa742018c, 0xa745018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e,
-	0x0a000e9f, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825,
-	0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116,
-	0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
-	0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c,
-	0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
-	0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3107ffff, 0x8d220024, 0x30420004,
-	0x10400039, 0x8d220024, 0x9742010e, 0x30e8fffb, 0x3c038000, 0x24420004,
-	0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b,
-	0x97840006, 0x8f85000c, 0x24020100, 0x24030002, 0xaf420180, 0xa743018c,
-	0xa746018e, 0x10a00005, 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000eda,
-	0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8,
-	0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc,
-	0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
-	0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104,
-	0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
-	0x3c021000, 0xaf4201b8, 0x3107ffff, 0x8d220024, 0x30420008, 0x10400036,
-	0x00000000, 0x9742010e, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c,
-	0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005,
-	0xa7440190, 0x9743011c, 0x9742011e, 0x0a000f14, 0x00021400, 0x9743011e,
-	0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000,
-	0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
-	0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024,
-	0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+	0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180, 0x24030002,
+	0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, 0xa7440190,
+	0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+	0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024,
+	0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
 	0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
-	0x1540004a, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024,
-	0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b, 0xa4800010,
-	0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x3c030800, 0x8c620024,
-	0x30420001, 0x10400037, 0x00001021, 0x9742010e, 0x34e60002, 0x3c038000,
-	0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
-	0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf400180, 0xa742018c,
-	0xa745018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a000f5e,
-	0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8,
-	0x8f840010, 0x30828000, 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc,
+	0x8d620034, 0x8f860008, 0x10400012, 0x30c20100, 0x10400010, 0x3c020f00,
+	0x00c21024, 0x3c030200, 0x1043000c, 0x3c020800, 0x8c430038, 0x8f840004,
+	0x3c020800, 0x2442003c, 0x2463ffff, 0x00832024, 0x00822021, 0x90830000,
+	0x24630004, 0x0a000de1, 0x000329c0, 0x00000000, 0x00061602, 0x3042000f,
+	0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300, 0x0062182b, 0x50600001,
+	0x24050800, 0x9742010e, 0x3148ffff, 0x3c038000, 0x24420004, 0x3046ffff,
+	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
+	0x8f840004, 0x8f870014, 0x24020002, 0xaf450180, 0xa742018c, 0xa746018e,
+	0xa7480188, 0x30e28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
+	0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
+	0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c,
+	0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
+	0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x8f424000,
+	0x30420100, 0x104000d5, 0x3c020800, 0x8c440024, 0x24030001, 0x1483002f,
+	0x00405021, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3045ffff,
+	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
+	0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e,
+	0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
+	0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
+	0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016, 0x9743010c,
+	0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
+	0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x30820001,
+	0x1040002e, 0x30eb0004, 0x9742010e, 0x30e9fffb, 0x3c038000, 0x24420004,
+	0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b,
+	0x9783000a, 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c,
+	0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8,
+	0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff,
+	0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016,
+	0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825,
+	0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3127ffff, 0x8d420024,
+	0x30420004, 0x10400030, 0x8d420024, 0x9742010e, 0x30e9fffb, 0x3c038000,
+	0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
+	0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020100, 0x24030002,
+	0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000, 0xa7440190,
+	0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+	0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x01021024,
+	0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+	0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
+	0x3127ffff, 0x8d420024, 0x30420008, 0x1040002d, 0x00000000, 0x9742010e,
+	0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+	0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020180,
+	0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000,
+	0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
+	0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+	0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
+	0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+	0xaf4201b8, 0x15600041, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8,
+	0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b,
+	0xa4800010, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800,
+	0x8c620024, 0x30420001, 0x1040002e, 0x00001021, 0x9742010e, 0x34e70002,
+	0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+	0x24020003, 0xa342018b, 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002,
+	0xaf400180, 0xa742018c, 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190,
+	0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+	0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024,
+	0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+	0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
+	0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x8f4b0070,
+	0x93420112, 0x8f840008, 0x00022882, 0x30820100, 0x14400003, 0x24a30003,
+	0x03e00008, 0x00001021, 0x30824000, 0x10400010, 0x27424000, 0x00031880,
+	0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
+	0x8c490000, 0x93430116, 0x27424000, 0x306300fc, 0x00431021, 0x8c4a0000,
+	0x0a000f45, 0x3c030800, 0x30822000, 0x1040ffea, 0x00031880, 0x27424000,
+	0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
+	0x8c490000, 0x00005021, 0x3c030800, 0x24680100, 0x00071602, 0x00021080,
+	0x00481021, 0x8c460000, 0x00071b82, 0x306303fc, 0x01031821, 0x8c640400,
+	0x00071182, 0x304203fc, 0x01021021, 0x8c450800, 0x30e300ff, 0x00031880,
+	0x01031821, 0x00091602, 0x00021080, 0x01021021, 0x00c43026, 0x8c640c00,
+	0x8c431000, 0x00c53026, 0x00091382, 0x304203fc, 0x01021021, 0x8c451400,
+	0x312200ff, 0x00021080, 0x01021021, 0x00c43026, 0x00c33026, 0x00091982,
+	0x306303fc, 0x01031821, 0x8c641800, 0x8c431c00, 0x00c53026, 0x00c43026,
+	0x11400015, 0x00c33026, 0x000a1602, 0x00021080, 0x01021021, 0x8c432000,
+	0x000a1382, 0x304203fc, 0x01021021, 0x8c452400, 0x314200ff, 0x00021080,
+	0x01021021, 0x00c33026, 0x000a1982, 0x306303fc, 0x01031821, 0x8c642800,
+	0x8c432c00, 0x00c53026, 0x00c43026, 0x00c33026, 0x8f430070, 0x3c050800,
+	0x8ca43100, 0x2c820020, 0x10400008, 0x006b5823, 0x3c020800, 0x24423104,
+	0x00041880, 0x00621821, 0x24820001, 0xac6b0000, 0xaca23100, 0xaf860004,
+	0x03e00008, 0x24020001, 0x27bdffe8, 0xafbf0010, 0x8f460128, 0x8f840010,
+	0xaf460020, 0x8f450104, 0x8f420100, 0x24030800, 0xaf850008, 0xaf820014,
+	0xaf4301b8, 0x1080000a, 0x3c020800, 0x8c430034, 0x10600007, 0x30a22000,
+	0x10400005, 0x34a30100, 0x8f82000c, 0xaf830008, 0x24420001, 0xaf82000c,
+	0x3c020800, 0x8c4300c0, 0x10600006, 0x3c030800, 0x8c6200c4, 0x24040001,
+	0x24420001, 0x0a000fd5, 0xac6200c4, 0x8f820008, 0x3c030010, 0x00431024,
+	0x14400009, 0x3c02001f, 0x3c030800, 0x8c620020, 0x00002021, 0x24420001,
+	0x0e000c78, 0xac620020, 0x0a000fd5, 0x00402021, 0x3442ff00, 0x14c20009,
+	0x2403bfff, 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e000c78,
+	0xac620020, 0x0a000fd5, 0x00402021, 0x8f820014, 0x00431024, 0x14400006,
+	0x00000000, 0xaf400048, 0x0e0011a9, 0xaf400040, 0x0a000fd5, 0x00402021,
+	0x0e001563, 0x00000000, 0x00402021, 0x10800005, 0x3c024000, 0x8f430124,
+	0x3c026020, 0xac430014, 0x3c024000, 0xaf420138, 0x00000000, 0x8fbf0010,
+	0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
+	0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000, 0x00621824, 0x3c023000,
+	0x10620021, 0x0043102b, 0x14400006, 0x3c024000, 0x3c022000, 0x10620009,
+	0x3c024000, 0x0a001040, 0x00000000, 0x10620045, 0x3c025000, 0x10620047,
+	0x3c024000, 0x0a001040, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8,
+	0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, 0x24030002, 0xa083000b,
+	0x00021402, 0xa4820008, 0x8f430148, 0xa4830010, 0x8f420144, 0x3c031000,
+	0xac820024, 0xaf4301b8, 0x0a001040, 0x3c024000, 0x8f420148, 0x24030002,
+	0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
+	0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001027, 0x3c038000,
+	0x12020007, 0x00000000, 0x0a001034, 0x00000000, 0x0e00112c, 0x00000000,
+	0x0a001025, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
+	0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
+	0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
+	0x0a001040, 0x3c024000, 0x0000000d, 0x00000000, 0x240002bf, 0x0a001040,
+	0x3c024000, 0x0e001441, 0x00000000, 0x0a001040, 0x3c024000, 0x0e0015ea,
+	0x00000000, 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014,
+	0x8fb00010, 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8,
+	0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
+	0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
+	0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
+	0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
+	0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
+	0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
+	0x8e021980, 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd,
+	0x32020001, 0x10400004, 0x32020002, 0x0e000f92, 0x00000000, 0x32020002,
+	0x1040fff6, 0x00000000, 0x0e000fe0, 0x00000000, 0x0a001071, 0x00000000,
+	0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
+	0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
+	0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
+	0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
+	0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
+	0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
+	0x8e021980, 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008,
+	0x27bd0018, 0x00804821, 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000,
+	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
+	0x8f840004, 0x8f880014, 0xaf490180, 0xa745018c, 0xa746018e, 0xa7470188,
+	0x31028000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc,
 	0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
-	0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104,
+	0x34427fff, 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104,
 	0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
-	0x3c021000, 0xaf4201b8, 0x00001021, 0x03e00008, 0x00000000, 0x27bdffe8,
-	0xafbf0010, 0x8f460128, 0x8f84000c, 0xaf460020, 0x8f450104, 0x8f420100,
-	0x24030800, 0xaf850004, 0xaf820010, 0xaf4301b8, 0x1080000a, 0x3c020800,
-	0x8c430034, 0x10600007, 0x30a22000, 0x10400005, 0x34a30100, 0x8f820008,
-	0xaf830004, 0x24420001, 0xaf820008, 0x3c020800, 0x8c4300c0, 0x10600006,
-	0x3c030800, 0x8c6200c4, 0x24040001, 0x24420001, 0x0a000fc0, 0xac6200c4,
-	0x8f820004, 0x3c030010, 0x00431024, 0x14400009, 0x3c02001f, 0x3c030800,
-	0x8c620020, 0x00002021, 0x24420001, 0x0e000c99, 0xac620020, 0x0a000fc0,
-	0x00402021, 0x3442ff00, 0x14c20009, 0x2403bfff, 0x3c030800, 0x8c620020,
-	0x24040001, 0x24420001, 0x0e000c99, 0xac620020, 0x0a000fc0, 0x00402021,
-	0x8f820010, 0x00431024, 0x14400006, 0x00000000, 0xaf400048, 0x0e001144,
-	0xaf400040, 0x0a000fc0, 0x00402021, 0x0e0014c9, 0x00000000, 0x00402021,
-	0x10800005, 0x3c024000, 0x8f430124, 0x3c026020, 0xac430014, 0x3c024000,
-	0xaf420138, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0,
-	0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420140, 0xaf420020, 0x8f430148,
-	0x3c027000, 0x00621824, 0x3c023000, 0x10620021, 0x0043102b, 0x14400006,
-	0x3c024000, 0x3c022000, 0x10620009, 0x3c024000, 0x0a00102b, 0x00000000,
-	0x10620045, 0x3c025000, 0x10620047, 0x3c024000, 0x0a00102b, 0x00000000,
+	0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000,
+	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008,
+	0xa083000b, 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000,
 	0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
 	0x8f420148, 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148,
-	0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0xaf4301b8, 0x0a00102b,
-	0x3c024000, 0x8f420148, 0x24030002, 0x3044ffff, 0x00021402, 0x305000ff,
-	0x1203000c, 0x27510180, 0x2a020003, 0x10400005, 0x24020003, 0x0600001d,
-	0x36053000, 0x0a001012, 0x3c038000, 0x12020007, 0x00000000, 0x0a00101f,
-	0x00000000, 0x0e00111f, 0x00000000, 0x0a001010, 0x00402021, 0x0e001131,
-	0x00000000, 0x00402021, 0x36053000, 0x3c038000, 0x8f4201b8, 0x00431024,
-	0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b, 0xa6240010, 0x8f420144,
-	0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00102b, 0x3c024000, 0x0000000d,
-	0x00000000, 0x24000295, 0x0a00102b, 0x3c024000, 0x0e0013a7, 0x00000000,
-	0x0a00102b, 0x3c024000, 0x0e001552, 0x00000000, 0x3c024000, 0xaf420178,
-	0x00000000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-	0x24020800, 0x03e00008, 0xaf4201b8, 0x27bdffe8, 0x3c04600c, 0xafbf0014,
-	0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x3c106000, 0x00431024,
-	0x3442380c, 0x24030003, 0xac825000, 0x3c020008, 0xaf430008, 0x8e040808,
-	0x0342d825, 0x8e020808, 0x3c030800, 0xac600020, 0x3084fff0, 0x2c840001,
-	0x3042fff0, 0x38420010, 0x2c420001, 0xaf84000c, 0xaf820000, 0x0e001574,
-	0x00000000, 0x0e0014c7, 0x00000000, 0x3c020400, 0x3442000c, 0x3c03ffff,
-	0x34630806, 0xae021948, 0xae03194c, 0x8e021980, 0x34420200, 0xae021980,
-	0x8f500000, 0x32020003, 0x1040fffd, 0x32020001, 0x10400004, 0x32020002,
-	0x0e000f7d, 0x00000000, 0x32020002, 0x1040fff6, 0x00000000, 0x0e000fcb,
-	0x00000000, 0x0a00105c, 0x00000000, 0x27bdffe8, 0x3c04600c, 0xafbf0014,
-	0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x3c106000, 0x00431024,
-	0x3442380c, 0x24030003, 0xac825000, 0x3c020008, 0xaf430008, 0x8e040808,
-	0x0342d825, 0x8e020808, 0x3c030800, 0xac600020, 0x3084fff0, 0x2c840001,
-	0x3042fff0, 0x38420010, 0x2c420001, 0xaf84000c, 0xaf820000, 0x0e001574,
-	0x00000000, 0x0e0014c7, 0x00000000, 0x3c020400, 0x3442000c, 0x3c03ffff,
-	0x34630806, 0xae021948, 0xae03194c, 0x8e021980, 0x8fbf0014, 0x34420200,
-	0xae021980, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x30a5ffff, 0x30c6ffff,
-	0x30e7ffff, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
-	0xa342018b, 0x97830006, 0x8f82000c, 0xaf440180, 0xa745018c, 0xa746018e,
-	0x10400005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a0010ad, 0x00021400,
-	0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010,
-	0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021,
-	0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
-	0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff,
-	0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
-	0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b,
-	0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180,
-	0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420148,
-	0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148, 0xa4830010,
-	0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8, 0x27bdffe0,
-	0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002, 0x3044ffff,
-	0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, 0x10400005,
-	0x24020003, 0x0600001d, 0x36053000, 0x0a00110a, 0x3c038000, 0x12020007,
-	0x00000000, 0x0a001117, 0x00000000, 0x0e00111f, 0x00000000, 0x0a001108,
-	0x00402021, 0x0e001131, 0x00000000, 0x00402021, 0x36053000, 0x3c038000,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b,
-	0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00111b,
-	0x8fbf0018, 0x0000000d, 0x00000000, 0x24000295, 0x8fbf0018, 0x8fb10014,
-	0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389, 0x1040000d,
-	0x00001021, 0x3c030800, 0x24635680, 0x00042942, 0x00052880, 0x00a32821,
-	0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025, 0x03e00008,
-	0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389, 0x1040000e,
-	0x00001021, 0x3c030800, 0x24635680, 0x00042942, 0x00052880, 0x00a32821,
-	0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827, 0x00832024,
-	0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x27bdffb0, 0xafbf0048,
-	0x93620023, 0x30420010, 0x1440025b, 0x24020001, 0x93420116, 0x93630005,
-	0x34424000, 0x30630001, 0x14600005, 0x03425821, 0x0e001548, 0x00000000,
-	0x0a0013a5, 0x8fbf0048, 0x93420112, 0x8f430104, 0x3c040020, 0x34424000,
-	0x00641824, 0x10600012, 0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8,
+	0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8,
+	0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002,
+	0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
+	0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001117, 0x3c038000,
+	0x12020007, 0x00000000, 0x0a001124, 0x00000000, 0x0e00112c, 0x00000000,
+	0x0a001115, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
+	0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
+	0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
+	0x0a001128, 0x8fbf0018, 0x0000000d, 0x00000000, 0x240002bf, 0x8fbf0018,
+	0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389,
+	0x1040000d, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
+	0x00a32821, 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025,
+	0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389,
+	0x1040000e, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
+	0x00a32821, 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827,
+	0x00832024, 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x9482000c,
+	0x24870014, 0x00021302, 0x00021080, 0x00824021, 0x00e8182b, 0x1060004f,
+	0x00000000, 0x90e30000, 0x2c620009, 0x10400047, 0x3c020800, 0x24425890,
+	0x00031880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000, 0x0a0011a4,
+	0x24e70001, 0x90e30001, 0x2402000a, 0x54620024, 0x01003821, 0x01071023,
+	0x2c42000a, 0x54400020, 0x01003821, 0x3c050800, 0x8ca26c98, 0x24e70002,
+	0x34420100, 0xaca26c98, 0x90e30000, 0x90e20001, 0x90e40002, 0x90e60003,
+	0x24e70004, 0x24a56c98, 0x00031e00, 0x00021400, 0x00621825, 0x00042200,
+	0x00641825, 0x00661825, 0xaca30004, 0x90e20000, 0x90e30001, 0x90e40002,
+	0x90e60003, 0x24e70004, 0x00021600, 0x00031c00, 0x00431025, 0x00042200,
+	0x00441025, 0x00461025, 0x0a0011a4, 0xaca20008, 0x90e30001, 0x24020004,
+	0x1062000e, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020003,
+	0x10620008, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020002,
+	0x14620003, 0x01001021, 0x00601021, 0x00e21021, 0x0a0011a4, 0x00403821,
+	0x90e20001, 0x0a0011a4, 0x00e23821, 0x01003821, 0x00e8102b, 0x5440ffb4,
+	0x90e30000, 0x03e00008, 0x24020001, 0x27bdff90, 0x3c030800, 0xafbf006c,
+	0xafbe0068, 0xafb70064, 0xafb60060, 0xafb5005c, 0xafb40058, 0xafb30054,
+	0xafb20050, 0xafb1004c, 0xafb00048, 0xac606c98, 0x93620023, 0x30420010,
+	0x1440027c, 0x24020001, 0x93420116, 0x93630005, 0x34424000, 0x30630001,
+	0x14600005, 0x0342b021, 0x0e0015e0, 0x00000000, 0x0a001436, 0x8fbf006c,
+	0x93420112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x10600012,
+	0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
+	0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1,
+	0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, 0x0a0011f1, 0xa0a3000a,
+	0x8f420104, 0x3c030040, 0x00431024, 0x1040001d, 0x3c038000, 0x27450180,
+	0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
+	0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a3000a,
+	0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010, 0xa0a00012, 0xa0a00013,
+	0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x0e0015e0,
+	0xaf4201b8, 0x0a001436, 0x8fbf006c, 0x8f820000, 0x10400016, 0x00000000,
+	0x8f420104, 0x3c030001, 0x00431024, 0x10400011, 0x00000000, 0x8ca3000c,
+	0x8f620030, 0x1462022d, 0x24020001, 0x8ca30010, 0x8f62002c, 0x14620229,
+	0x24020001, 0x9763003a, 0x96c20000, 0x14430225, 0x24020001, 0x97630038,
+	0x96c20002, 0x14430221, 0x24020001, 0xaf400048, 0xaf400054, 0xaf400040,
+	0x8f740040, 0x8f650048, 0x00b43023, 0x04c10004, 0x00000000, 0x0000000d,
+	0x00000000, 0x240001af, 0x9742011a, 0x3052ffff, 0x12400004, 0x8ed30004,
+	0x02721021, 0x0a001228, 0x2451ffff, 0x02608821, 0x92d7000d, 0xa7a00020,
+	0xa3a0001a, 0xafa00028, 0x9362003f, 0x32e30004, 0x1060003a, 0x305000ff,
+	0x24040012, 0x16040006, 0x24020001, 0x3c040800, 0x8c830028, 0x24630001,
+	0x0a001328, 0xac830028, 0x8f620044, 0x16620010, 0x27a60010, 0x27450180,
+	0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020, 0xafb40028, 0xa3b00022,
+	0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
+	0x0a00130d, 0x00000000, 0x8f620044, 0x02621023, 0x0440001a, 0x02651023,
+	0x044100d9, 0x24020001, 0x3c020800, 0x8c4300d8, 0x10600004, 0x24020001,
+	0xa7a20020, 0x0a00125e, 0xafb40028, 0x2402001a, 0xa7a20020, 0x24020020,
+	0xafb40028, 0xa3b00022, 0xa3a40023, 0xa3a2001a, 0x27a60010, 0x27450180,
+	0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d,
+	0x00000000, 0x0a001328, 0x24020001, 0x0293f023, 0x1bc00016, 0x025e102a,
+	0x54400007, 0x32f700fe, 0x57d2000f, 0x027e9821, 0x32e20001, 0x5440000c,
+	0x027e9821, 0x32f700fe, 0x0240f021, 0x3c040800, 0x8c8300c8, 0x00009021,
+	0x24020001, 0xa7a20020, 0xafb40028, 0x24630001, 0x0a001282, 0xac8300c8,
+	0x025e1023, 0x0a001282, 0x3052ffff, 0x0000f021, 0x24a2ffff, 0x02221823,
+	0x1860001f, 0x0072102a, 0x54400019, 0x00a08821, 0x97a20020, 0x3c040800,
+	0x8c8300cc, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020, 0x02741026,
+	0x2c420001, 0xac8300cc, 0x2cc30001, 0x00431024, 0x1440000a, 0x02401821,
+	0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
+	0x00000000, 0x0a00130d, 0x00000000, 0x00a08821, 0x02431023, 0x3052ffff,
+	0x0a0012ae, 0x32f700f6, 0x02741023, 0x18400008, 0x97a20020, 0x3c040800,
+	0x8c8300d4, 0xafb30028, 0x34420400, 0x24630001, 0xa7a20020, 0xac8300d4,
+	0x32e20002, 0x1040001c, 0x32e20010, 0x8f620044, 0x1662000d, 0x27a60010,
+	0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
+	0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
+	0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
+	0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
+	0x54400003, 0x8ed50008, 0x0a001328, 0x24020001, 0x8f630054, 0x26a2ffff,
+	0x00431023, 0x18400011, 0x27a60010, 0x97a20020, 0x3c040800, 0x8c8300d0,
+	0x27450180, 0x3c078000, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020,
+	0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000, 0x0a00130d,
+	0x00000000, 0x32e20020, 0x10400011, 0x00000000, 0x96c20012, 0x0052102b,
+	0x10400008, 0x97a20020, 0x96d20012, 0x12400003, 0x02721021, 0x0a0012f2,
+	0x2451ffff, 0x02608821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004,
+	0xa7a20020, 0xa3a3001a, 0x8f420104, 0x3c030080, 0x00431024, 0x10400037,
+	0x3a03000a, 0x0e001151, 0x02c02021, 0x24030002, 0x1443002b, 0x3c030800,
+	0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001,
+	0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128,
+	0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a,
+	0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012,
+	0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024,
+	0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000,
+	0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a001436, 0x8fbf006c,
+	0x8c626c98, 0x30420100, 0x10400003, 0x24636c98, 0x8c620004, 0xaf62017c,
+	0x3a03000a, 0x2c630001, 0x3a02000c, 0x2c420001, 0x00621825, 0x14600003,
+	0x2402000e, 0x56020030, 0x00009021, 0x52400008, 0x96c4000e, 0x12400004,
+	0xa7b20040, 0x02721021, 0x0a001343, 0x2451ffff, 0x02608821, 0x96c4000e,
+	0x93630035, 0x8f62004c, 0x00642004, 0x00952021, 0x00821023, 0x18400015,
+	0x00000000, 0x8f620018, 0x02621023, 0x1c400015, 0x97a20020, 0x8f620018,
+	0x1662001c, 0x00000000, 0x8f62001c, 0x02a21023, 0x1c40000e, 0x97a20020,
+	0x8f62001c, 0x16a20015, 0x00000000, 0x8f620058, 0x00821023, 0x18400011,
+	0x97a20020, 0x0a001364, 0xafb10028, 0x8f620058, 0x00821023, 0x0441000b,
+	0x97a20020, 0xafb10028, 0xafb30034, 0xafb50038, 0xafa4003c, 0x34420020,
+	0x0a00136d, 0xa7a20020, 0x02809821, 0x02608821, 0x8f640058, 0x8f62004c,
+	0x02a21023, 0x18400009, 0x00000000, 0x8f620054, 0x02a21023, 0x1c400005,
+	0x97a20020, 0xafb10028, 0xafb50024, 0x0a001385, 0x34420040, 0x9742011a,
+	0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c,
+	0x8f620054, 0x10620004, 0x97a20020, 0xafb10028, 0x34420080, 0xa7a20020,
+	0x24020014, 0x1202000a, 0x2a020015, 0x10400005, 0x2402000c, 0x12020006,
+	0x32e20001, 0x0a0013c6, 0x00000000, 0x24020016, 0x16020035, 0x32e20001,
+	0x8f620084, 0x24420001, 0x16a20031, 0x32e20001, 0x24020014, 0x12020021,
+	0x2a020015, 0x10400005, 0x2402000c, 0x12020008, 0x32e20001, 0x0a0013c6,
+	0x00000000, 0x24020016, 0x1202000c, 0x32e20001, 0x0a0013c6, 0x00000000,
+	0x97a30020, 0x2402000e, 0xafb10028, 0xa3b00022, 0xa3a20023, 0xafb50024,
+	0x34630054, 0x0a0013c5, 0xa7a30020, 0x97a20020, 0x93a4001a, 0x24030010,
+	0xafb10028, 0xa3b00022, 0xa3a30023, 0xafb50024, 0x3442005d, 0x34840002,
+	0xa7a20020, 0x0a0013c5, 0xa3a4001a, 0x97a20020, 0x24030012, 0xa3a30023,
+	0x93a3001a, 0xafb10028, 0xa3b00022, 0xafb50024, 0x3042fffe, 0x3442005c,
+	0x34630002, 0xa7a20020, 0xa3a3001a, 0x32e20001, 0x10400030, 0x2402000c,
+	0x12020013, 0x2a02000d, 0x10400005, 0x2402000a, 0x12020008, 0x97a20020,
+	0x0a0013f8, 0x32e20009, 0x2402000e, 0x1202001b, 0x32e20009, 0x0a0013f9,
+	0x0002102b, 0x93a4001a, 0x24030008, 0xafb10028, 0xa3b00022, 0xa3a30023,
+	0x0a0013f4, 0x34420013, 0x97a30020, 0x30620004, 0x14400005, 0x93a2001a,
+	0x3463001b, 0xa7a30020, 0x0a0013e7, 0x24030016, 0x3463001b, 0xa7a30020,
+	0x24030010, 0xafb10028, 0xa3b00022, 0xa3a30023, 0x34420002, 0x0a0013f7,
+	0xa3a2001a, 0x97a20020, 0x93a4001a, 0x24030010, 0xafb10028, 0xa3b00022,
+	0xa3a30023, 0x3442001b, 0x34840002, 0xa7a20020, 0xa3a4001a, 0x32e20009,
+	0x0002102b, 0x00021023, 0x30420007, 0x12400015, 0x34450003, 0x8f820018,
+	0x24030800, 0x27440180, 0x24420001, 0xaf820018, 0x24020004, 0xaf4301b8,
+	0xa4850008, 0xa082000b, 0x93430120, 0x00003021, 0x3c021000, 0xa492000e,
+	0xac950024, 0xac930028, 0x007e1821, 0xa483000c, 0xaf4201b8, 0x0a001413,
+	0x97a20020, 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000,
+	0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
+	0x8fa30028, 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002,
+	0xa0a2000b, 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012,
+	0x93a20023, 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024,
+	0x8fa30038, 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8,
+	0x00c01021, 0x8fbf006c, 0x8fbe0068, 0x8fb70064, 0x8fb60060, 0x8fb5005c,
+	0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 0x03e00008,
+	0x27bd0070, 0x8f470140, 0x8f460148, 0x3c028000, 0x00c24024, 0x00062c02,
+	0x30a300ff, 0x24020019, 0x106200e7, 0x27440180, 0x2862001a, 0x1040001f,
+	0x24020008, 0x106200be, 0x28620009, 0x1040000d, 0x24020001, 0x10620046,
+	0x28620002, 0x50400005, 0x24020006, 0x1060002e, 0x00a01821, 0x0a00155e,
+	0x00000000, 0x1062005b, 0x00a01821, 0x0a00155e, 0x00000000, 0x2402000b,
+	0x10620084, 0x2862000c, 0x10400005, 0x24020009, 0x106200bc, 0x00061c02,
+	0x0a00155e, 0x00000000, 0x2402000e, 0x106200b7, 0x00061c02, 0x0a00155e,
+	0x00000000, 0x28620021, 0x10400009, 0x2862001f, 0x104000c1, 0x2402001b,
+	0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02, 0x0a00155e, 0x00000000,
+	0x240200c2, 0x106200ca, 0x286200c3, 0x10400005, 0x24020080, 0x1062005a,
+	0x00a01821, 0x0a00155e, 0x00000000, 0x240200c9, 0x106200cd, 0x30c5ffff,
+	0x0a00155e, 0x00000000, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
+	0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a,
+	0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024,
+	0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, 0x11000009, 0x00a01821,
+	0x3c020800, 0x24030002, 0xa0436c88, 0x24426c88, 0xac470008, 0x8f430144,
+	0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
+	0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b,
+	0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x3c026000,
+	0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800, 0x3c058000, 0x8f4201b8,
+	0x00451024, 0x1440fffd, 0x00000000, 0xac870000, 0x91026c88, 0x00002821,
+	0x10400002, 0x25076c88, 0x8ce50008, 0xac850004, 0xa4830008, 0x91036c88,
+	0x24020002, 0xa082000b, 0xa4860010, 0x34630001, 0xa083000a, 0x8f420144,
+	0xac820024, 0x91036c88, 0x10600002, 0x00001021, 0x8ce20004, 0xac820028,
+	0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006c88, 0x03e00008, 0xac400808,
+	0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b,
+	0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008,
+	0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02, 0x93620005, 0x30420004,
+	0x14400020, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020, 0x3c038000,
+	0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000,
+	0x34630001, 0x00e31825, 0x34420004, 0xa3620005, 0xaf430020, 0x93620005,
+	0x30420004, 0x14400003, 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8,
+	0x00431024, 0x1440fffd, 0x24020005, 0x3c031000, 0xac870000, 0xa082000b,
+	0xaf4301b8, 0x0a00150d, 0x00061c02, 0x0000000d, 0x03e00008, 0x00000000,
+	0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
+	0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a, 0xa083000b,
+	0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, 0x03e00008,
+	0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
+	0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4860010,
+	0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8,
+	0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
+	0xa4830008, 0x24030002, 0xa082000a, 0x3c021000, 0xac870000, 0xac800004,
+	0xa083000b, 0xa4860010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8,
+	0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
+	0xac870000, 0xac800004, 0xa4830008, 0xa080000a, 0x0a001518, 0xa082000b,
+	0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
+	0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4401a4,
+	0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8, 0x0000000d, 0x03e00008,
+	0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011,
+	0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000,
+	0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040,
+	0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008,
+	0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
+	0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4501a4,
+	0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8, 0x3c029000, 0x34420001,
+	0x00822025, 0xaf440020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+	0x00000000, 0x03e00008, 0x00000000, 0x3c028000, 0x34420001, 0x00822025,
+	0x03e00008, 0xaf440020, 0x308600ff, 0x27450180, 0x3c038000, 0x8f4201b8,
 	0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040,
 	0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000,
-	0x0a001181, 0xa0a3000a, 0x8f420104, 0x3c030040, 0x00431024, 0x1040001d,
-	0x3c038000, 0x27450180, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
-	0x8f420128, 0xaca20000, 0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008,
-	0x24020002, 0xa0a3000a, 0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010,
-	0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c,
-	0xaca40018, 0x0e001548, 0xaf4201b8, 0x0a0013a5, 0x8fbf0048, 0x8f820000,
-	0x10400016, 0x00000000, 0x8f420104, 0x3c030001, 0x00431024, 0x10400011,
-	0x00000000, 0x8ca3000c, 0x8f620030, 0x1462020c, 0x24020001, 0x8ca30010,
-	0x8f62002c, 0x14620208, 0x24020001, 0x9763003a, 0x95620000, 0x14430204,
-	0x24020001, 0x97630038, 0x95620002, 0x14430200, 0x24020001, 0xaf400048,
-	0xaf400054, 0xaf400040, 0x8f690040, 0x8f6a0048, 0x01497023, 0x05c10004,
-	0x00000000, 0x0000000d, 0x00000000, 0x24000169, 0x9742011a, 0x3046ffff,
-	0x10c00004, 0x8d680004, 0x01061021, 0x0a0011b8, 0x2445ffff, 0x01002821,
-	0x916c000d, 0xa7a00020, 0xa3a0001a, 0xafa00028, 0x9362003f, 0x31830004,
-	0x1060003a, 0x304700ff, 0x24040012, 0x14e40006, 0x24020001, 0x3c040800,
-	0x8c830028, 0x24630001, 0x0a00128d, 0xac830028, 0x8f620044, 0x15020010,
-	0x27a60010, 0x27450180, 0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020,
-	0xafa90028, 0xa3a70022, 0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024,
-	0x1440fffd, 0x00000000, 0x0a001272, 0x00000000, 0x8f620044, 0x01021023,
-	0x0440001a, 0x010a1023, 0x044100ae, 0x24020001, 0x3c020800, 0x8c4300d8,
-	0x10600004, 0x24020001, 0xa7a20020, 0x0a0011ee, 0xafa90028, 0x2402001a,
-	0xa7a20020, 0x24020020, 0xafa90028, 0xa3a70022, 0xa3a40023, 0xa3a2001a,
-	0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x00000000, 0x0a001272, 0x00000000, 0x0a00128d, 0x24020001, 0x01286823,
-	0x19a00016, 0x00cd102a, 0x54400007, 0x318c00fe, 0x55a6000f, 0x010d4021,
-	0x31820001, 0x5440000c, 0x010d4021, 0x318c00fe, 0x00c06821, 0x3c040800,
-	0x8c8300c8, 0x00003021, 0x24020001, 0xa7a20020, 0xafa90028, 0x24630001,
-	0x0a001212, 0xac8300c8, 0x00cd1023, 0x0a001212, 0x3046ffff, 0x00006821,
-	0x2542ffff, 0x00a21823, 0x1860001e, 0x0066102a, 0x14400018, 0x01402821,
-	0x97a20020, 0x3c040800, 0x8c8300cc, 0xafa90028, 0x34420001, 0x24630001,
-	0xa7a20020, 0x01091026, 0x2c420001, 0xac8300cc, 0x2dc30001, 0x00431024,
-	0x1440000a, 0x00c01821, 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x00000000, 0x0a001272, 0x00000000, 0x00c31023,
-	0x3046ffff, 0x0a00123d, 0x318c00f6, 0x01091023, 0x18400008, 0x97a20020,
-	0x3c040800, 0x8c8300d4, 0xafa80028, 0x34420400, 0x24630001, 0xa7a20020,
-	0xac8300d4, 0x31820002, 0x1040001c, 0x31820010, 0x8f620044, 0x1502000d,
-	0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafa90028, 0x34420001,
-	0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272,
-	0x00000000, 0x97a20020, 0x27450180, 0x3c038000, 0xafa90028, 0x34420001,
-	0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272,
-	0x00000000, 0x54400003, 0x8d6a0008, 0x0a00128d, 0x24020001, 0x8f630054,
-	0x2542ffff, 0x00431023, 0x1840002e, 0x97a20020, 0x27a60010, 0x3c040800,
-	0x8c8300d0, 0x27450180, 0x3c078000, 0xafa90028, 0x34420001, 0x24630001,
-	0xa7a20020, 0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000,
-	0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018,
-	0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010,
-	0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014,
-	0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001,
-	0x3c031000, 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a0013a5,
-	0x8fbf0048, 0x31820020, 0x10400011, 0x00000000, 0x95620012, 0x0046102b,
-	0x10400008, 0x97a20020, 0x95660012, 0x10c00003, 0x01061021, 0x0a00129e,
-	0x2445ffff, 0x01002821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004,
-	0xa7a20020, 0xa3a3001a, 0x8f420104, 0x38e3000a, 0x2c630001, 0x38e2000c,
-	0x2c420001, 0x00621825, 0x14600003, 0x2402000e, 0x54e2002a, 0x00003021,
-	0x50c00008, 0x9564000e, 0x10c00004, 0xa7a60040, 0x01061021, 0x0a0012b6,
-	0x2445ffff, 0x01002821, 0x9564000e, 0x93630035, 0x8f62004c, 0x00642004,
-	0x008a2021, 0x00821023, 0x1840001d, 0x00000000, 0x8f620018, 0x01021023,
-	0x1c40000f, 0x97a20020, 0x8f620018, 0x15020016, 0x00000000, 0x8f62001c,
-	0x01421023, 0x1c400008, 0x97a20020, 0x8f62001c, 0x1542000f, 0x00000000,
-	0x8f620058, 0x00821023, 0x1840000b, 0x97a20020, 0xafa50028, 0xafa80034,
-	0xafaa0038, 0xafa4003c, 0x34420020, 0x0a0012da, 0xa7a20020, 0x01204021,
-	0x01002821, 0x8f640058, 0x8f62004c, 0x01421023, 0x18400009, 0x00000000,
-	0x8f620054, 0x01421023, 0x1c400005, 0x97a20020, 0xafa50028, 0xafaa0024,
-	0x0a0012f2, 0x34420040, 0x9742011a, 0x1440000c, 0x24020014, 0x8f620058,
-	0x14820009, 0x24020014, 0x8f63004c, 0x8f620054, 0x10620004, 0x97a20020,
-	0xafa50028, 0x34420080, 0xa7a20020, 0x24020014, 0x10e2000a, 0x28e20015,
-	0x10400005, 0x2402000c, 0x10e20006, 0x31820001, 0x0a001333, 0x00000000,
-	0x24020016, 0x14e20035, 0x31820001, 0x8f620084, 0x24420001, 0x15420031,
-	0x31820001, 0x24020014, 0x10e20021, 0x28e20015, 0x10400005, 0x2402000c,
-	0x10e20008, 0x31820001, 0x0a001333, 0x00000000, 0x24020016, 0x10e2000c,
-	0x31820001, 0x0a001333, 0x00000000, 0x97a30020, 0x2402000e, 0xafa50028,
-	0xa3a70022, 0xa3a20023, 0xafaa0024, 0x34630054, 0x0a001332, 0xa7a30020,
-	0x97a20020, 0x93a4001a, 0x24030010, 0xafa50028, 0xa3a70022, 0xa3a30023,
-	0xafaa0024, 0x3442005d, 0x34840002, 0xa7a20020, 0x0a001332, 0xa3a4001a,
-	0x97a20020, 0x24030012, 0xa3a30023, 0x93a3001a, 0xafa50028, 0xa3a70022,
-	0xafaa0024, 0x3042fffe, 0x3442005c, 0x34630002, 0xa7a20020, 0xa3a3001a,
-	0x31820001, 0x10400030, 0x2402000c, 0x10e20013, 0x28e2000d, 0x10400005,
-	0x2402000a, 0x10e20008, 0x97a20020, 0x0a001365, 0x31820009, 0x2402000e,
-	0x10e2001b, 0x31820009, 0x0a001366, 0x0002102b, 0x93a4001a, 0x24030008,
-	0xafa50028, 0xa3a70022, 0xa3a30023, 0x0a001361, 0x34420013, 0x97a30020,
-	0x30620004, 0x14400005, 0x93a2001a, 0x3463001b, 0xa7a30020, 0x0a001354,
-	0x24030016, 0x3463001b, 0xa7a30020, 0x24030010, 0xafa50028, 0xa3a70022,
-	0xa3a30023, 0x34420002, 0x0a001364, 0xa3a2001a, 0x97a20020, 0x93a4001a,
-	0x24030010, 0xafa50028, 0xa3a70022, 0xa3a30023, 0x3442001b, 0x34840002,
-	0xa7a20020, 0xa3a4001a, 0x31820009, 0x0002102b, 0x00021023, 0x30420007,
-	0x10c00017, 0x34440003, 0x8f820014, 0x24030800, 0x27450180, 0x24420001,
-	0xaf820014, 0x24020004, 0xaf4301b8, 0xa4a40008, 0xa0a2000b, 0x93440120,
-	0x3c031000, 0xa4a6000e, 0xacaa0024, 0xaca80028, 0x008d2021, 0xa4a4000c,
-	0xaf4301b8, 0x97a20020, 0x00003021, 0x3042ffbf, 0x0a001381, 0xa7a20020,
-	0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8fa30028,
-	0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002, 0xa0a2000b,
-	0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012, 0x93a20023,
-	0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024, 0x8fa30038,
-	0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8, 0x00c01021,
-	0x8fbf0048, 0x03e00008, 0x27bd0050, 0x8f470140, 0x8f460148, 0x3c028000,
-	0x00c24024, 0x00062c02, 0x30a300ff, 0x24020019, 0x106200e7, 0x27440180,
-	0x2862001a, 0x1040001f, 0x24020008, 0x106200be, 0x28620009, 0x1040000d,
-	0x24020001, 0x10620046, 0x28620002, 0x50400005, 0x24020006, 0x1060002e,
-	0x00a01821, 0x0a0014c4, 0x00000000, 0x1062005b, 0x00a01821, 0x0a0014c4,
-	0x00000000, 0x2402000b, 0x10620084, 0x2862000c, 0x10400005, 0x24020009,
-	0x106200bc, 0x00061c02, 0x0a0014c4, 0x00000000, 0x2402000e, 0x106200b7,
-	0x00061c02, 0x0a0014c4, 0x00000000, 0x28620021, 0x10400009, 0x2862001f,
-	0x104000c1, 0x2402001b, 0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02,
-	0x0a0014c4, 0x00000000, 0x240200c2, 0x106200ca, 0x286200c3, 0x10400005,
-	0x24020080, 0x1062005a, 0x00a01821, 0x0a0014c4, 0x00000000, 0x240200c9,
-	0x106200cd, 0x30c5ffff, 0x0a0014c4, 0x00000000, 0x3c058000, 0x8f4201b8,
-	0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac870000,
-	0xac800004, 0xa082000a, 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000,
-	0xac800028, 0xac830024, 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808,
-	0x11000009, 0x00a01821, 0x3c020800, 0x24030002, 0xa0436a08, 0x24426a08,
-	0xac470008, 0x8f430144, 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8,
-	0x00451024, 0x1440fffd, 0x24020002, 0xac800000, 0xac870004, 0xa4830008,
-	0xa082000a, 0xa082000b, 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000,
-	0xac820028, 0x3c026000, 0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800,
-	0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x00000000, 0xac870000,
-	0x91026a08, 0x00002821, 0x10400002, 0x25076a08, 0x8ce50008, 0xac850004,
-	0xa4830008, 0x91036a08, 0x24020002, 0xa082000b, 0xa4860010, 0x34630001,
-	0xa083000a, 0x8f420144, 0xac820024, 0x91036a08, 0x10600002, 0x00001021,
-	0x8ce20004, 0xac820028, 0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006a08,
-	0x03e00008, 0xac400808, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
-	0x24020002, 0xa082000b, 0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000,
-	0xa4820012, 0x03e00008, 0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02,
-	0x93620005, 0x30420004, 0x14400020, 0x3c029000, 0x34420001, 0x00e21025,
-	0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
-	0x93620005, 0x3c038000, 0x34630001, 0x00e31825, 0x34420004, 0xa3620005,
-	0xaf430020, 0x93620005, 0x30420004, 0x14400003, 0x3c038000, 0x0000000d,
-	0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020005, 0x3c031000,
-	0xac870000, 0xa082000b, 0xaf4301b8, 0x0a001473, 0x00061c02, 0x0000000d,
-	0x03e00008, 0x00000000, 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024,
-	0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004,
-	0xa082000a, 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028,
-	0xac830024, 0x03e00008, 0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024,
-	0x1440fffd, 0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a,
-	0xa082000b, 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028,
-	0x03e00008, 0xaf4301b8, 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024,
-	0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xa082000a, 0x3c021000,
-	0xac870000, 0xac800004, 0xa083000b, 0xa4860010, 0xac800024, 0xac800028,
-	0x03e00008, 0xaf4201b8, 0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024,
-	0x1440fffd, 0x24020002, 0xac870000, 0xac800004, 0xa4830008, 0xa080000a,
-	0x0a00147e, 0xa082000b, 0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024,
-	0x1440fffd, 0x24020002, 0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000,
-	0xa7430188, 0xaf4401a4, 0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8,
-	0x0000000d, 0x03e00008, 0x00000000, 0x03e00008, 0x00000000, 0x8f420100,
-	0x3042003e, 0x14400011, 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0,
-	0x10400005, 0x00000000, 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001,
-	0xaf400054, 0xaf400040, 0x8f420100, 0x30423800, 0x54400001, 0xaf400044,
-	0x24020001, 0x03e00008, 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024,
-	0x1440fffd, 0x24020002, 0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000,
-	0xa7430188, 0xaf4501a4, 0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8,
-	0x3c029000, 0x34420001, 0x00822025, 0xaf440020, 0x3c038000, 0x8f420020,
-	0x00431024, 0x1440fffd, 0x00000000, 0x03e00008, 0x00000000, 0x3c028000,
-	0x34420001, 0x00822025, 0x03e00008, 0xaf440020, 0x308600ff, 0x27450180,
-	0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128,
-	0xaca20000, 0x8f640040, 0x24030008, 0x240240c1, 0xa4a20008, 0x24020002,
-	0xa0a2000b, 0x3c021000, 0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013,
-	0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008,
-	0xaf4201b8, 0x24020001, 0xacc40000, 0x03e00008, 0xa4e50000, 0x03e00008,
-	0x24020001, 0x24020001, 0xaf400044, 0x03e00008, 0xaf400050, 0x00803021,
-	0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
-	0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018,
-	0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010,
-	0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014,
-	0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc2002c, 0x3c031000,
-	0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044, 0x03e00008, 0xaf400050,
-	0x27bdffe8, 0xafbf0010, 0x0e001032, 0x00000000, 0x00002021, 0x0e000c99,
-	0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f460148, 0x27450180,
-	0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x00000000, 0x8f440140, 0x00061202, 0x304200ff, 0x00061c02, 0xaca20004,
-	0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b, 0xaca30024, 0x10e0000a,
-	0xaca40000, 0x28e20004, 0x14400005, 0x24020001, 0x24020005, 0x54e20005,
-	0xa0a0000a, 0x24020001, 0x0a001571, 0xa0a2000a, 0xa0a0000a, 0x3c021000,
-	0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021, 0x10c00007, 0x00000000,
-	0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004,
-	0x03e00008, 0x00000000, 0x0a001587, 0x00a01021, 0xac860000, 0x00000000,
-	0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, 0x24a5ffff, 0x03e00008,
-	0x00000000, 0x00000000 };
+	0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024,
+	0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008, 0xaf4201b8, 0x24020001,
+	0xacc40000, 0x03e00008, 0xa4e50000, 0x24020001, 0xaf400044, 0x03e00008,
+	0xaf400050, 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024,
+	0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1,
+	0xa4a20008, 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a,
+	0x94c20010, 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013,
+	0x8cc30014, 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028,
+	0x8cc2002c, 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044,
+	0x03e00008, 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e001047, 0x00000000,
+	0x00002021, 0x0e000c78, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018,
+	0x8f460148, 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8,
+	0x00431024, 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff,
+	0x00061c02, 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b,
+	0xaca30024, 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001,
+	0x24020005, 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a001609, 0xa0a2000a,
+	0xa0a0000a, 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021,
+	0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000,
+	0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00161f, 0x00a01021,
+	0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa,
+	0x24a5ffff, 0x03e00008, 0x00000000, 0x00000000 }; 
 
 static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b06FwRodata[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b06FwBss[(0x1394/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b06FwSbss[(0x18/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = {
+	0x0800468c, 0x0800458c, 0x08004630, 0x08004648, 0x08004660, 0x08004680,
+	0x0800468c, 0x0800468c, 0x08004594, 0x00000000, 0x00000000 };
+static u32 bnx2_RXP_b06FwBss[(0x13a4/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
 
 static u32 bnx2_rv2p_proc1[] = {
 	0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004,
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2582d98..e0f51af 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -576,7 +576,7 @@
 	slave->duplex = DUPLEX_FULL;
 
 	if (slave_dev->ethtool_ops) {
-		u32 res;
+		int res;
 
 		if (!slave_dev->ethtool_ops->get_settings) {
 			return -1;
@@ -1145,7 +1145,8 @@
 }
 
 #define BOND_INTERSECT_FEATURES \
-	(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
+	(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
+	NETIF_F_TSO|NETIF_F_UFO)
 
 /* 
  * Compute the common dev->feature set available to all slaves.  Some
@@ -1168,6 +1169,16 @@
 			  NETIF_F_HW_CSUM)))
 		features &= ~NETIF_F_SG;
 
+	/* 
+	 * features will include NETIF_F_TSO (NETIF_F_UFO) iff all 
+	 * slave devices support NETIF_F_TSO (NETIF_F_UFO), which 
+	 * implies that all slaves also support scatter-gather 
+	 * (NETIF_F_SG), which implies that features also includes 
+	 * NETIF_F_SG. So no need to check whether we have an  
+	 * illegal combination of NETIF_F_{TSO,UFO} and 
+	 * !NETIF_F_SG 
+	 */
+
 	features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
 	bond_dev->features = features;
 
@@ -4080,6 +4091,8 @@
 
 static struct ethtool_ops bond_ethtool_ops = {
 	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.get_tso		= ethtool_op_get_tso,
+	.get_ufo		= ethtool_op_get_ufo,
 	.get_sg			= ethtool_op_get_sg,
 	.get_drvinfo		= bond_ethtool_get_drvinfo,
 };
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 32d13da..041bcc5 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -260,7 +260,7 @@
 	char *ifname;
 	int i, res, found, ret = count;
 	struct slave *slave;
-	struct net_device *dev = 0;
+	struct net_device *dev = NULL;
 	struct bonding *bond = to_bond(cd);
 
 	/* Quick sanity check -- is the bond interface up? */
@@ -995,7 +995,7 @@
 			printk(KERN_INFO DRV_NAME
 			       ": %s: Setting primary slave to None.\n",
 			       bond->dev->name);
-			bond->primary_slave = 0;
+			bond->primary_slave = NULL;
 				bond_select_active_slave(bond);
 		} else {
 			printk(KERN_INFO DRV_NAME
@@ -1123,7 +1123,7 @@
 			printk(KERN_INFO DRV_NAME
 			       ": %s: Setting active slave to None.\n",
 			       bond->dev->name);
-			bond->primary_slave = 0;
+			bond->primary_slave = NULL;
 				bond_select_active_slave(bond);
 		} else {
 			printk(KERN_INFO DRV_NAME
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index dde631f..6e295fc 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -335,6 +335,30 @@
 		cas_disable_irq(cp, i);
 }
 
+static inline void cas_buffer_init(cas_page_t *cp)
+{
+	struct page *page = cp->buffer;
+	atomic_set((atomic_t *)&page->lru.next, 1);
+}
+
+static inline int cas_buffer_count(cas_page_t *cp)
+{
+	struct page *page = cp->buffer;
+	return atomic_read((atomic_t *)&page->lru.next);
+}
+
+static inline void cas_buffer_inc(cas_page_t *cp)
+{
+	struct page *page = cp->buffer;
+	atomic_inc((atomic_t *)&page->lru.next);
+}
+
+static inline void cas_buffer_dec(cas_page_t *cp)
+{
+	struct page *page = cp->buffer;
+	atomic_dec((atomic_t *)&page->lru.next);
+}
+
 static void cas_enable_irq(struct cas *cp, const int ring)
 {
 	if (ring == 0) { /* all but TX_DONE */
@@ -472,6 +496,7 @@
 {
 	pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size, 
 		       PCI_DMA_FROMDEVICE);
+	cas_buffer_dec(page);
 	__free_pages(page->buffer, cp->page_order);
 	kfree(page);
 	return 0;
@@ -501,6 +526,7 @@
 	page->buffer = alloc_pages(flags, cp->page_order);
 	if (!page->buffer)
 		goto page_err;
+	cas_buffer_init(page);
 	page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0,
 				      cp->page_size, PCI_DMA_FROMDEVICE);
 	return page;
@@ -579,7 +605,7 @@
 	list_for_each_safe(elem, tmp, &list) {
 		cas_page_t *page = list_entry(elem, cas_page_t, list);
 
-		if (page_count(page->buffer) > 1) 
+		if (cas_buffer_count(page) > 1)
 			continue;
 
 		list_del(elem);
@@ -1347,7 +1373,7 @@
 	cas_page_t *page = cp->rx_pages[1][index];
 	cas_page_t *new;
 
-	if (page_count(page->buffer) == 1)
+	if (cas_buffer_count(page) == 1)
 		return page;
 
 	new = cas_page_dequeue(cp);
@@ -1367,7 +1393,7 @@
 	cas_page_t **page1 = cp->rx_pages[1];
 
 	/* swap if buffer is in use */
-	if (page_count(page0[index]->buffer) > 1) {
+	if (cas_buffer_count(page0[index]) > 1) {
 		cas_page_t *new = cas_page_spare(cp, index);
 		if (new) {
 			page1[index] = page0[index];
@@ -2039,6 +2065,7 @@
 		skb->len      += hlen - swivel;
 
 		get_page(page->buffer);
+		cas_buffer_inc(page);
 		frag->page = page->buffer;
 		frag->page_offset = off;
 		frag->size = hlen - swivel;
@@ -2063,6 +2090,7 @@
 			frag++;
 
 			get_page(page->buffer);
+			cas_buffer_inc(page);
 			frag->page = page->buffer;
 			frag->page_offset = 0;
 			frag->size = hlen;
@@ -2225,7 +2253,7 @@
 	released = 0;
 	while (entry != last) {
 		/* make a new buffer if it's still in use */
-		if (page_count(page[entry]->buffer) > 1) {
+		if (cas_buffer_count(page[entry]) > 1) {
 			cas_page_t *new = cas_page_dequeue(cp);
 			if (!new) {
 				/* let the timer know that we need to 
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index bf1fd2b..24253c8 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2752,8 +2752,6 @@
 	retval = pci_enable_wake(pdev, 0, 0);
 	if (retval)
 		DPRINTK(PROBE,ERR, "Error clearing wake events\n");
-	if(e100_hw_init(nic))
-		DPRINTK(HW, ERR, "e100_hw_init failed\n");
 
 	netif_device_attach(netdev);
 	if(netif_running(netdev))
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index d252297..5cedc81 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -121,7 +121,7 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
-	if(hw->media_type == e1000_media_type_copper) {
+	if (hw->media_type == e1000_media_type_copper) {
 
 		ecmd->supported = (SUPPORTED_10baseT_Half |
 		                   SUPPORTED_10baseT_Full |
@@ -133,7 +133,7 @@
 
 		ecmd->advertising = ADVERTISED_TP;
 
-		if(hw->autoneg == 1) {
+		if (hw->autoneg == 1) {
 			ecmd->advertising |= ADVERTISED_Autoneg;
 
 			/* the e1000 autoneg seems to match ethtool nicely */
@@ -144,7 +144,7 @@
 		ecmd->port = PORT_TP;
 		ecmd->phy_address = hw->phy_addr;
 
-		if(hw->mac_type == e1000_82543)
+		if (hw->mac_type == e1000_82543)
 			ecmd->transceiver = XCVR_EXTERNAL;
 		else
 			ecmd->transceiver = XCVR_INTERNAL;
@@ -160,13 +160,13 @@
 
 		ecmd->port = PORT_FIBRE;
 
-		if(hw->mac_type >= e1000_82545)
+		if (hw->mac_type >= e1000_82545)
 			ecmd->transceiver = XCVR_INTERNAL;
 		else
 			ecmd->transceiver = XCVR_EXTERNAL;
 	}
 
-	if(netif_carrier_ok(adapter->netdev)) {
+	if (netif_carrier_ok(adapter->netdev)) {
 
 		e1000_get_speed_and_duplex(hw, &adapter->link_speed,
 		                                   &adapter->link_duplex);
@@ -175,7 +175,7 @@
 		/* unfortunatly FULL_DUPLEX != DUPLEX_FULL
 		 *          and HALF_DUPLEX != DUPLEX_HALF */
 
-		if(adapter->link_duplex == FULL_DUPLEX)
+		if (adapter->link_duplex == FULL_DUPLEX)
 			ecmd->duplex = DUPLEX_FULL;
 		else
 			ecmd->duplex = DUPLEX_HALF;
@@ -205,11 +205,11 @@
 
 	if (ecmd->autoneg == AUTONEG_ENABLE) {
 		hw->autoneg = 1;
-		if(hw->media_type == e1000_media_type_fiber)
+		if (hw->media_type == e1000_media_type_fiber)
 			hw->autoneg_advertised = ADVERTISED_1000baseT_Full |
 				     ADVERTISED_FIBRE |
 				     ADVERTISED_Autoneg;
-		else 
+		else
 			hw->autoneg_advertised = ADVERTISED_10baseT_Half |
 						  ADVERTISED_10baseT_Full |
 						  ADVERTISED_100baseT_Half |
@@ -219,12 +219,12 @@
 						  ADVERTISED_TP;
 		ecmd->advertising = hw->autoneg_advertised;
 	} else
-		if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
+		if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
 			return -EINVAL;
 
 	/* reset the link */
 
-	if(netif_running(adapter->netdev)) {
+	if (netif_running(adapter->netdev)) {
 		e1000_down(adapter);
 		e1000_reset(adapter);
 		e1000_up(adapter);
@@ -241,14 +241,14 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
-	pause->autoneg = 
+	pause->autoneg =
 		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
-	
-	if(hw->fc == e1000_fc_rx_pause)
+
+	if (hw->fc == e1000_fc_rx_pause)
 		pause->rx_pause = 1;
-	else if(hw->fc == e1000_fc_tx_pause)
+	else if (hw->fc == e1000_fc_tx_pause)
 		pause->tx_pause = 1;
-	else if(hw->fc == e1000_fc_full) {
+	else if (hw->fc == e1000_fc_full) {
 		pause->rx_pause = 1;
 		pause->tx_pause = 1;
 	}
@@ -260,31 +260,30 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
-	
+
 	adapter->fc_autoneg = pause->autoneg;
 
-	if(pause->rx_pause && pause->tx_pause)
+	if (pause->rx_pause && pause->tx_pause)
 		hw->fc = e1000_fc_full;
-	else if(pause->rx_pause && !pause->tx_pause)
+	else if (pause->rx_pause && !pause->tx_pause)
 		hw->fc = e1000_fc_rx_pause;
-	else if(!pause->rx_pause && pause->tx_pause)
+	else if (!pause->rx_pause && pause->tx_pause)
 		hw->fc = e1000_fc_tx_pause;
-	else if(!pause->rx_pause && !pause->tx_pause)
+	else if (!pause->rx_pause && !pause->tx_pause)
 		hw->fc = e1000_fc_none;
 
 	hw->original_fc = hw->fc;
 
-	if(adapter->fc_autoneg == AUTONEG_ENABLE) {
-		if(netif_running(adapter->netdev)) {
+	if (adapter->fc_autoneg == AUTONEG_ENABLE) {
+		if (netif_running(adapter->netdev)) {
 			e1000_down(adapter);
 			e1000_up(adapter);
 		} else
 			e1000_reset(adapter);
-	}
-	else
+	} else
 		return ((hw->media_type == e1000_media_type_fiber) ?
 			e1000_setup_link(hw) : e1000_force_mac_fc(hw));
-	
+
 	return 0;
 }
 
@@ -301,14 +300,14 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	adapter->rx_csum = data;
 
-	if(netif_running(netdev)) {
+	if (netif_running(netdev)) {
 		e1000_down(adapter);
 		e1000_up(adapter);
 	} else
 		e1000_reset(adapter);
 	return 0;
 }
-	
+
 static uint32_t
 e1000_get_tx_csum(struct net_device *netdev)
 {
@@ -320,7 +319,7 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
-	if(adapter->hw.mac_type < e1000_82543) {
+	if (adapter->hw.mac_type < e1000_82543) {
 		if (!data)
 			return -EINVAL;
 		return 0;
@@ -339,8 +338,8 @@
 e1000_set_tso(struct net_device *netdev, uint32_t data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	if((adapter->hw.mac_type < e1000_82544) ||
-	    (adapter->hw.mac_type == e1000_82547)) 
+	if ((adapter->hw.mac_type < e1000_82544) ||
+	    (adapter->hw.mac_type == e1000_82547))
 		return data ? -EINVAL : 0;
 
 	if (data)
@@ -348,7 +347,7 @@
 	else
 		netdev->features &= ~NETIF_F_TSO;
 	return 0;
-} 
+}
 #endif /* NETIF_F_TSO */
 
 static uint32_t
@@ -365,7 +364,7 @@
 	adapter->msg_enable = data;
 }
 
-static int 
+static int
 e1000_get_regs_len(struct net_device *netdev)
 {
 #define E1000_REGS_LEN 32
@@ -401,7 +400,7 @@
 	regs_buff[11] = E1000_READ_REG(hw, TIDV);
 
 	regs_buff[12] = adapter->hw.phy_type;  /* PHY type (IGP=1, M88=0) */
-	if(hw->phy_type == e1000_phy_igp) {
+	if (hw->phy_type == e1000_phy_igp) {
 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
 				    IGP01E1000_PHY_AGC_A);
 		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
@@ -455,7 +454,7 @@
 	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
 	regs_buff[24] = (uint32_t)phy_data;  /* phy local receiver status */
 	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
-	if(hw->mac_type >= e1000_82540 &&
+	if (hw->mac_type >= e1000_82540 &&
 	   hw->media_type == e1000_media_type_copper) {
 		regs_buff[26] = E1000_READ_REG(hw, MANC);
 	}
@@ -479,7 +478,7 @@
 	int ret_val = 0;
 	uint16_t i;
 
-	if(eeprom->len == 0)
+	if (eeprom->len == 0)
 		return -EINVAL;
 
 	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
@@ -489,16 +488,16 @@
 
 	eeprom_buff = kmalloc(sizeof(uint16_t) *
 			(last_word - first_word + 1), GFP_KERNEL);
-	if(!eeprom_buff)
+	if (!eeprom_buff)
 		return -ENOMEM;
 
-	if(hw->eeprom.type == e1000_eeprom_spi)
+	if (hw->eeprom.type == e1000_eeprom_spi)
 		ret_val = e1000_read_eeprom(hw, first_word,
 					    last_word - first_word + 1,
 					    eeprom_buff);
 	else {
 		for (i = 0; i < last_word - first_word + 1; i++)
-			if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
+			if ((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
 							&eeprom_buff[i])))
 				break;
 	}
@@ -525,10 +524,10 @@
 	int max_len, first_word, last_word, ret_val = 0;
 	uint16_t i;
 
-	if(eeprom->len == 0)
+	if (eeprom->len == 0)
 		return -EOPNOTSUPP;
 
-	if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
 		return -EFAULT;
 
 	max_len = hw->eeprom.word_size * 2;
@@ -536,19 +535,19 @@
 	first_word = eeprom->offset >> 1;
 	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
-	if(!eeprom_buff)
+	if (!eeprom_buff)
 		return -ENOMEM;
 
 	ptr = (void *)eeprom_buff;
 
-	if(eeprom->offset & 1) {
+	if (eeprom->offset & 1) {
 		/* need read/modify/write of first changed EEPROM word */
 		/* only the second byte of the word is being modified */
 		ret_val = e1000_read_eeprom(hw, first_word, 1,
 					    &eeprom_buff[0]);
 		ptr++;
 	}
-	if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
+	if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
 		/* need read/modify/write of last changed EEPROM word */
 		/* only the first byte of the word is being modified */
 		ret_val = e1000_read_eeprom(hw, last_word, 1,
@@ -567,9 +566,9 @@
 	ret_val = e1000_write_eeprom(hw, first_word,
 				     last_word - first_word + 1, eeprom_buff);
 
-	/* Update the checksum over the first part of the EEPROM if needed 
+	/* Update the checksum over the first part of the EEPROM if needed
 	 * and flush shadow RAM for 82573 conrollers */
-	if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) || 
+	if ((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
 				(hw->mac_type == e1000_82573)))
 		e1000_update_eeprom_checksum(hw);
 
@@ -633,7 +632,7 @@
 	ring->rx_jumbo_pending = 0;
 }
 
-static int 
+static int
 e1000_set_ringparam(struct net_device *netdev,
                     struct ethtool_ringparam *ring)
 {
@@ -670,25 +669,25 @@
 	txdr = adapter->tx_ring;
 	rxdr = adapter->rx_ring;
 
-	if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 		return -EINVAL;
 
 	rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
 	rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
 		E1000_MAX_RXD : E1000_MAX_82544_RXD));
-	E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE); 
+	E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
 
 	txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD);
 	txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ?
 		E1000_MAX_TXD : E1000_MAX_82544_TXD));
-	E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); 
+	E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
 
 	for (i = 0; i < adapter->num_tx_queues; i++)
 		txdr[i].count = txdr->count;
 	for (i = 0; i < adapter->num_rx_queues; i++)
 		rxdr[i].count = rxdr->count;
 
-	if(netif_running(adapter->netdev)) {
+	if (netif_running(adapter->netdev)) {
 		/* Try to get new resources before deleting old */
 		if ((err = e1000_setup_all_rx_resources(adapter)))
 			goto err_setup_rx;
@@ -708,7 +707,7 @@
 		kfree(rx_old);
 		adapter->rx_ring = rx_new;
 		adapter->tx_ring = tx_new;
-		if((err = e1000_up(adapter)))
+		if ((err = e1000_up(adapter)))
 			return err;
 	}
 
@@ -727,10 +726,10 @@
 	uint32_t pat, value;                                                   \
 	uint32_t test[] =                                                      \
 		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};              \
-	for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) {              \
+	for (pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) {              \
 		E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W));             \
 		value = E1000_READ_REG(&adapter->hw, R);                       \
-		if(value != (test[pat] & W & M)) {                             \
+		if (value != (test[pat] & W & M)) {                             \
 			DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \
 			        "0x%08X expected 0x%08X\n",                    \
 			        E1000_##R, value, (test[pat] & W & M));        \
@@ -746,7 +745,7 @@
 	uint32_t value;                                                        \
 	E1000_WRITE_REG(&adapter->hw, R, W & M);                               \
 	value = E1000_READ_REG(&adapter->hw, R);                               \
-	if((W & M) != (value & M)) {                                          \
+	if ((W & M) != (value & M)) {                                          \
 		DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
 		        "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \
 		*data = (adapter->hw.mac_type < e1000_82543) ?                 \
@@ -782,7 +781,7 @@
 	value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle);
 	E1000_WRITE_REG(&adapter->hw, STATUS, toggle);
 	after = E1000_READ_REG(&adapter->hw, STATUS) & toggle;
-	if(value != after) {
+	if (value != after) {
 		DPRINTK(DRV, ERR, "failed STATUS register test got: "
 		        "0x%08X expected: 0x%08X\n", after, value);
 		*data = 1;
@@ -810,7 +809,7 @@
 	REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);
 	REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
 
-	if(adapter->hw.mac_type >= e1000_82543) {
+	if (adapter->hw.mac_type >= e1000_82543) {
 
 		REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);
 		REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
@@ -818,7 +817,7 @@
 		REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
 		REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
 
-		for(i = 0; i < E1000_RAR_ENTRIES; i++) {
+		for (i = 0; i < E1000_RAR_ENTRIES; i++) {
 			REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,
 					 0xFFFFFFFF);
 			REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
@@ -834,7 +833,7 @@
 
 	}
 
-	for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+	for (i = 0; i < E1000_MC_TBL_SIZE; i++)
 		REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
 
 	*data = 0;
@@ -850,8 +849,8 @@
 
 	*data = 0;
 	/* Read and add up the contents of the EEPROM */
-	for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
-		if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
+	for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+		if ((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
 			*data = 1;
 			break;
 		}
@@ -859,7 +858,7 @@
 	}
 
 	/* If Checksum is not Correct return error else test passed */
-	if((checksum != (uint16_t) EEPROM_SUM) && !(*data))
+	if ((checksum != (uint16_t) EEPROM_SUM) && !(*data))
 		*data = 2;
 
 	return *data;
@@ -888,9 +887,9 @@
 	*data = 0;
 
 	/* Hook up test interrupt handler just for this test */
- 	if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
+ 	if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
  		shared_int = FALSE;
- 	} else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ,
+ 	} else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
 			      netdev->name, netdev)){
 		*data = 1;
 		return -1;
@@ -901,12 +900,12 @@
 	msec_delay(10);
 
 	/* Test each interrupt */
-	for(; i < 10; i++) {
+	for (; i < 10; i++) {
 
 		/* Interrupt to test */
 		mask = 1 << i;
 
- 		if(!shared_int) {
+ 		if (!shared_int) {
  			/* Disable the interrupt to be reported in
  			 * the cause register and then force the same
  			 * interrupt and see if one gets posted.  If
@@ -917,8 +916,8 @@
  			E1000_WRITE_REG(&adapter->hw, IMC, mask);
  			E1000_WRITE_REG(&adapter->hw, ICS, mask);
  			msec_delay(10);
- 
- 			if(adapter->test_icr & mask) {
+
+ 			if (adapter->test_icr & mask) {
  				*data = 3;
  				break;
  			}
@@ -935,12 +934,12 @@
 		E1000_WRITE_REG(&adapter->hw, ICS, mask);
 		msec_delay(10);
 
-		if(!(adapter->test_icr & mask)) {
+		if (!(adapter->test_icr & mask)) {
 			*data = 4;
 			break;
 		}
 
- 		if(!shared_int) {
+ 		if (!shared_int) {
 			/* Disable the other interrupts to be reported in
 			 * the cause register and then force the other
 			 * interrupts and see if any get posted.  If
@@ -952,7 +951,7 @@
 			E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF);
 			msec_delay(10);
 
-			if(adapter->test_icr) {
+			if (adapter->test_icr) {
 				*data = 5;
 				break;
 			}
@@ -977,24 +976,24 @@
 	struct pci_dev *pdev = adapter->pdev;
 	int i;
 
-	if(txdr->desc && txdr->buffer_info) {
-		for(i = 0; i < txdr->count; i++) {
-			if(txdr->buffer_info[i].dma)
+	if (txdr->desc && txdr->buffer_info) {
+		for (i = 0; i < txdr->count; i++) {
+			if (txdr->buffer_info[i].dma)
 				pci_unmap_single(pdev, txdr->buffer_info[i].dma,
 						 txdr->buffer_info[i].length,
 						 PCI_DMA_TODEVICE);
-			if(txdr->buffer_info[i].skb)
+			if (txdr->buffer_info[i].skb)
 				dev_kfree_skb(txdr->buffer_info[i].skb);
 		}
 	}
 
-	if(rxdr->desc && rxdr->buffer_info) {
-		for(i = 0; i < rxdr->count; i++) {
-			if(rxdr->buffer_info[i].dma)
+	if (rxdr->desc && rxdr->buffer_info) {
+		for (i = 0; i < rxdr->count; i++) {
+			if (rxdr->buffer_info[i].dma)
 				pci_unmap_single(pdev, rxdr->buffer_info[i].dma,
 						 rxdr->buffer_info[i].length,
 						 PCI_DMA_FROMDEVICE);
-			if(rxdr->buffer_info[i].skb)
+			if (rxdr->buffer_info[i].skb)
 				dev_kfree_skb(rxdr->buffer_info[i].skb);
 		}
 	}
@@ -1027,11 +1026,11 @@
 
 	/* Setup Tx descriptor ring and Tx buffers */
 
-	if(!txdr->count)
-		txdr->count = E1000_DEFAULT_TXD;   
+	if (!txdr->count)
+		txdr->count = E1000_DEFAULT_TXD;
 
 	size = txdr->count * sizeof(struct e1000_buffer);
-	if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+	if (!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
 		ret_val = 1;
 		goto err_nomem;
 	}
@@ -1039,7 +1038,7 @@
 
 	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
 	E1000_ROUNDUP(txdr->size, 4096);
-	if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
+	if (!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
 		ret_val = 2;
 		goto err_nomem;
 	}
@@ -1058,12 +1057,12 @@
 			E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
 			E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
 
-	for(i = 0; i < txdr->count; i++) {
+	for (i = 0; i < txdr->count; i++) {
 		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
 		struct sk_buff *skb;
 		unsigned int size = 1024;
 
-		if(!(skb = alloc_skb(size, GFP_KERNEL))) {
+		if (!(skb = alloc_skb(size, GFP_KERNEL))) {
 			ret_val = 3;
 			goto err_nomem;
 		}
@@ -1083,18 +1082,18 @@
 
 	/* Setup Rx descriptor ring and Rx buffers */
 
-	if(!rxdr->count)
-		rxdr->count = E1000_DEFAULT_RXD;   
+	if (!rxdr->count)
+		rxdr->count = E1000_DEFAULT_RXD;
 
 	size = rxdr->count * sizeof(struct e1000_buffer);
-	if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+	if (!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
 		ret_val = 4;
 		goto err_nomem;
 	}
 	memset(rxdr->buffer_info, 0, size);
 
 	rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
-	if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
+	if (!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
 		ret_val = 5;
 		goto err_nomem;
 	}
@@ -1114,11 +1113,11 @@
 		(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 
-	for(i = 0; i < rxdr->count; i++) {
+	for (i = 0; i < rxdr->count; i++) {
 		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
 		struct sk_buff *skb;
 
-		if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
+		if (!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
 				GFP_KERNEL))) {
 			ret_val = 6;
 			goto err_nomem;
@@ -1227,15 +1226,15 @@
 
 	/* Check Phy Configuration */
 	e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
-	if(phy_reg != 0x4100)
+	if (phy_reg != 0x4100)
 		 return 9;
 
 	e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
-	if(phy_reg != 0x0070)
+	if (phy_reg != 0x0070)
 		return 10;
 
 	e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
-	if(phy_reg != 0x001A)
+	if (phy_reg != 0x001A)
 		return 11;
 
 	return 0;
@@ -1249,7 +1248,7 @@
 
 	adapter->hw.autoneg = FALSE;
 
-	if(adapter->hw.phy_type == e1000_phy_m88) {
+	if (adapter->hw.phy_type == e1000_phy_m88) {
 		/* Auto-MDI/MDIX Off */
 		e1000_write_phy_reg(&adapter->hw,
 				    M88E1000_PHY_SPEC_CTRL, 0x0808);
@@ -1269,14 +1268,14 @@
 		     E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
 		     E1000_CTRL_FD);	 /* Force Duplex to FULL */
 
-	if(adapter->hw.media_type == e1000_media_type_copper &&
+	if (adapter->hw.media_type == e1000_media_type_copper &&
 	   adapter->hw.phy_type == e1000_phy_m88) {
 		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
 	} else {
 		/* Set the ILOS bit on the fiber Nic is half
 		 * duplex link is detected. */
 		stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
-		if((stat_reg & E1000_STATUS_FD) == 0)
+		if ((stat_reg & E1000_STATUS_FD) == 0)
 			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
 	}
 
@@ -1285,7 +1284,7 @@
 	/* Disable the receiver on the PHY so when a cable is plugged in, the
 	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
 	 */
-	if(adapter->hw.phy_type == e1000_phy_m88)
+	if (adapter->hw.phy_type == e1000_phy_m88)
 		e1000_phy_disable_receiver(adapter);
 
 	udelay(500);
@@ -1301,14 +1300,14 @@
 
 	switch (adapter->hw.mac_type) {
 	case e1000_82543:
-		if(adapter->hw.media_type == e1000_media_type_copper) {
+		if (adapter->hw.media_type == e1000_media_type_copper) {
 			/* Attempt to setup Loopback mode on Non-integrated PHY.
 			 * Some PHY registers get corrupted at random, so
 			 * attempt this 10 times.
 			 */
-			while(e1000_nonintegrated_phy_loopback(adapter) &&
+			while (e1000_nonintegrated_phy_loopback(adapter) &&
 			      count++ < 10);
-			if(count < 11)
+			if (count < 11)
 				return 0;
 		}
 		break;
@@ -1430,8 +1429,8 @@
 e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
 {
 	frame_size &= ~1;
-	if(*(skb->data + 3) == 0xFF) {
-		if((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
+	if (*(skb->data + 3) == 0xFF) {
+		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
 		   (*(skb->data + frame_size / 2 + 12) == 0xAF)) {
 			return 0;
 		}
@@ -1450,53 +1449,53 @@
 
 	E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
 
-	/* Calculate the loop count based on the largest descriptor ring 
+	/* Calculate the loop count based on the largest descriptor ring
 	 * The idea is to wrap the largest ring a number of times using 64
 	 * send/receive pairs during each loop
 	 */
 
-	if(rxdr->count <= txdr->count)
+	if (rxdr->count <= txdr->count)
 		lc = ((txdr->count / 64) * 2) + 1;
 	else
 		lc = ((rxdr->count / 64) * 2) + 1;
 
 	k = l = 0;
-	for(j = 0; j <= lc; j++) { /* loop count loop */
-		for(i = 0; i < 64; i++) { /* send the packets */
-			e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 
+	for (j = 0; j <= lc; j++) { /* loop count loop */
+		for (i = 0; i < 64; i++) { /* send the packets */
+			e1000_create_lbtest_frame(txdr->buffer_info[i].skb,
 					1024);
-			pci_dma_sync_single_for_device(pdev, 
+			pci_dma_sync_single_for_device(pdev,
 					txdr->buffer_info[k].dma,
 				    	txdr->buffer_info[k].length,
 				    	PCI_DMA_TODEVICE);
-			if(unlikely(++k == txdr->count)) k = 0;
+			if (unlikely(++k == txdr->count)) k = 0;
 		}
 		E1000_WRITE_REG(&adapter->hw, TDT, k);
 		msec_delay(200);
 		time = jiffies; /* set the start time for the receive */
 		good_cnt = 0;
 		do { /* receive the sent packets */
-			pci_dma_sync_single_for_cpu(pdev, 
+			pci_dma_sync_single_for_cpu(pdev,
 					rxdr->buffer_info[l].dma,
 				    	rxdr->buffer_info[l].length,
 				    	PCI_DMA_FROMDEVICE);
-	
+
 			ret_val = e1000_check_lbtest_frame(
 					rxdr->buffer_info[l].skb,
 				   	1024);
-			if(!ret_val)
+			if (!ret_val)
 				good_cnt++;
-			if(unlikely(++l == rxdr->count)) l = 0;
-			/* time + 20 msecs (200 msecs on 2.4) is more than 
-			 * enough time to complete the receives, if it's 
+			if (unlikely(++l == rxdr->count)) l = 0;
+			/* time + 20 msecs (200 msecs on 2.4) is more than
+			 * enough time to complete the receives, if it's
 			 * exceeded, break and error off
 			 */
 		} while (good_cnt < 64 && jiffies < (time + 20));
-		if(good_cnt != 64) {
+		if (good_cnt != 64) {
 			ret_val = 13; /* ret_val is the same as mis-compare */
-			break; 
+			break;
 		}
-		if(jiffies >= (time + 2)) {
+		if (jiffies >= (time + 2)) {
 			ret_val = 14; /* error code for time out error */
 			break;
 		}
@@ -1549,17 +1548,17 @@
 		*data = 1;
 	} else {
 		e1000_check_for_link(&adapter->hw);
-		if(adapter->hw.autoneg)  /* if auto_neg is set wait for it */
+		if (adapter->hw.autoneg)  /* if auto_neg is set wait for it */
 			msec_delay(4000);
 
-		if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+		if (!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
 			*data = 1;
 		}
 	}
 	return *data;
 }
 
-static int 
+static int
 e1000_diag_test_count(struct net_device *netdev)
 {
 	return E1000_TEST_LEN;
@@ -1572,7 +1571,7 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	boolean_t if_running = netif_running(netdev);
 
-	if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
+	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
 		/* Offline tests */
 
 		/* save speed, duplex, autoneg settings */
@@ -1582,27 +1581,27 @@
 
 		/* Link test performed before hardware reset so autoneg doesn't
 		 * interfere with test result */
-		if(e1000_link_test(adapter, &data[4]))
+		if (e1000_link_test(adapter, &data[4]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
-		if(if_running)
+		if (if_running)
 			e1000_down(adapter);
 		else
 			e1000_reset(adapter);
 
-		if(e1000_reg_test(adapter, &data[0]))
+		if (e1000_reg_test(adapter, &data[0]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		e1000_reset(adapter);
-		if(e1000_eeprom_test(adapter, &data[1]))
+		if (e1000_eeprom_test(adapter, &data[1]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		e1000_reset(adapter);
-		if(e1000_intr_test(adapter, &data[2]))
+		if (e1000_intr_test(adapter, &data[2]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		e1000_reset(adapter);
-		if(e1000_loopback_test(adapter, &data[3]))
+		if (e1000_loopback_test(adapter, &data[3]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		/* restore speed, duplex, autoneg settings */
@@ -1611,11 +1610,11 @@
 		adapter->hw.autoneg = autoneg;
 
 		e1000_reset(adapter);
-		if(if_running)
+		if (if_running)
 			e1000_up(adapter);
 	} else {
 		/* Online tests */
-		if(e1000_link_test(adapter, &data[4]))
+		if (e1000_link_test(adapter, &data[4]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		/* Offline tests aren't run; pass by default */
@@ -1633,7 +1632,7 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
-	switch(adapter->hw.device_id) {
+	switch (adapter->hw.device_id) {
 	case E1000_DEV_ID_82542:
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
@@ -1649,7 +1648,7 @@
 	case E1000_DEV_ID_82546GB_FIBER:
 	case E1000_DEV_ID_82571EB_FIBER:
 		/* Wake events only supported on port A for dual fiber */
-		if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
+		if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
 			wol->supported = 0;
 			wol->wolopts   = 0;
 			return;
@@ -1661,13 +1660,13 @@
 				 WAKE_BCAST | WAKE_MAGIC;
 
 		wol->wolopts = 0;
-		if(adapter->wol & E1000_WUFC_EX)
+		if (adapter->wol & E1000_WUFC_EX)
 			wol->wolopts |= WAKE_UCAST;
-		if(adapter->wol & E1000_WUFC_MC)
+		if (adapter->wol & E1000_WUFC_MC)
 			wol->wolopts |= WAKE_MCAST;
-		if(adapter->wol & E1000_WUFC_BC)
+		if (adapter->wol & E1000_WUFC_BC)
 			wol->wolopts |= WAKE_BCAST;
-		if(adapter->wol & E1000_WUFC_MAG)
+		if (adapter->wol & E1000_WUFC_MAG)
 			wol->wolopts |= WAKE_MAGIC;
 		return;
 	}
@@ -1679,7 +1678,7 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
-	switch(adapter->hw.device_id) {
+	switch (adapter->hw.device_id) {
 	case E1000_DEV_ID_82542:
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
@@ -1693,23 +1692,23 @@
 	case E1000_DEV_ID_82546GB_FIBER:
 	case E1000_DEV_ID_82571EB_FIBER:
 		/* Wake events only supported on port A for dual fiber */
-		if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+		if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
 			return wol->wolopts ? -EOPNOTSUPP : 0;
 		/* Fall Through */
 
 	default:
-		if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+		if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
 			return -EOPNOTSUPP;
 
 		adapter->wol = 0;
 
-		if(wol->wolopts & WAKE_UCAST)
+		if (wol->wolopts & WAKE_UCAST)
 			adapter->wol |= E1000_WUFC_EX;
-		if(wol->wolopts & WAKE_MCAST)
+		if (wol->wolopts & WAKE_MCAST)
 			adapter->wol |= E1000_WUFC_MC;
-		if(wol->wolopts & WAKE_BCAST)
+		if (wol->wolopts & WAKE_BCAST)
 			adapter->wol |= E1000_WUFC_BC;
-		if(wol->wolopts & WAKE_MAGIC)
+		if (wol->wolopts & WAKE_MAGIC)
 			adapter->wol |= E1000_WUFC_MAG;
 	}
 
@@ -1727,7 +1726,7 @@
 {
 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
 
-	if(test_and_change_bit(E1000_LED_ON, &adapter->led_status))
+	if (test_and_change_bit(E1000_LED_ON, &adapter->led_status))
 		e1000_led_off(&adapter->hw);
 	else
 		e1000_led_on(&adapter->hw);
@@ -1740,11 +1739,11 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
-	if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
+	if (!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
 		data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
 
-	if(adapter->hw.mac_type < e1000_82571) {
-		if(!adapter->blink_timer.function) {
+	if (adapter->hw.mac_type < e1000_82571) {
+		if (!adapter->blink_timer.function) {
 			init_timer(&adapter->blink_timer);
 			adapter->blink_timer.function = e1000_led_blink_callback;
 			adapter->blink_timer.data = (unsigned long) adapter;
@@ -1782,21 +1781,21 @@
 e1000_nway_reset(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	if(netif_running(netdev)) {
+	if (netif_running(netdev)) {
 		e1000_down(adapter);
 		e1000_up(adapter);
 	}
 	return 0;
 }
 
-static int 
+static int
 e1000_get_stats_count(struct net_device *netdev)
 {
 	return E1000_STATS_LEN;
 }
 
-static void 
-e1000_get_ethtool_stats(struct net_device *netdev, 
+static void
+e1000_get_ethtool_stats(struct net_device *netdev,
 		struct ethtool_stats *stats, uint64_t *data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1830,7 +1829,7 @@
 /*	BUG_ON(i != E1000_STATS_LEN); */
 }
 
-static void 
+static void
 e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
 {
 #ifdef CONFIG_E1000_MQ
@@ -1839,9 +1838,9 @@
 	uint8_t *p = data;
 	int i;
 
-	switch(stringset) {
+	switch (stringset) {
 	case ETH_SS_TEST:
-		memcpy(data, *e1000_gstrings_test, 
+		memcpy(data, *e1000_gstrings_test,
 			E1000_TEST_LEN*ETH_GSTRING_LEN);
 		break;
 	case ETH_SS_STATS:
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 2437d36..beeec0f 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -1600,10 +1600,10 @@
     if(ret_val)
         return ret_val;
 
-        /* Read the MII 1000Base-T Control Register (Address 9). */
-        ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
-        if(ret_val)
-            return ret_val;
+    /* Read the MII 1000Base-T Control Register (Address 9). */
+    ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+    if(ret_val)
+        return ret_val;
 
     /* Need to parse both autoneg_advertised and fc and set up
      * the appropriate PHY registers.  First we will parse for
@@ -3916,7 +3916,7 @@
         }
     }
 
-    if(eeprom->use_eerd == TRUE) {
+    if (eeprom->use_eerd == TRUE) {
         ret_val = e1000_read_eeprom_eerd(hw, offset, words, data);
         if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
             (hw->mac_type != e1000_82573))
@@ -4423,7 +4423,7 @@
             return -E1000_ERR_EEPROM;
         }
 
-	/* If STM opcode located in bits 15:8 of flop, reset firmware */
+        /* If STM opcode located in bits 15:8 of flop, reset firmware */
         if ((flop & 0xFF00) == E1000_STM_OPCODE) {
             E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
         }
@@ -4431,7 +4431,7 @@
         /* Perform the flash update */
         E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
 
-	for (i=0; i < attempts; i++) {
+        for (i=0; i < attempts; i++) {
             eecd = E1000_READ_REG(hw, EECD);
             if ((eecd & E1000_EECD_FLUPD) == 0) {
                 break;
@@ -4504,6 +4504,7 @@
         hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
         hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
     }
+
     switch (hw->mac_type) {
     default:
         break;
@@ -6840,7 +6841,8 @@
 e1000_check_phy_reset_block(struct e1000_hw *hw)
 {
     uint32_t manc = 0;
-    if(hw->mac_type > e1000_82547_rev_2)
+
+    if (hw->mac_type > e1000_82547_rev_2)
         manc = E1000_READ_REG(hw, MANC);
     return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
 	    E1000_BLK_PHY_RESET : E1000_SUCCESS;
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 0b8f6f2b7..f1219dd 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -377,6 +377,7 @@
 void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
 
 /* Filters (multicast, vlan, receive) */
+void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
 uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
 void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
 void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
@@ -401,7 +402,9 @@
 void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
 /* Port I/O is only supported on 82544 and newer */
 uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port);
+uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
 void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
+void e1000_enable_pciex_master(struct e1000_hw *hw);
 int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
 int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
 void e1000_release_software_semaphore(struct e1000_hw *hw);
@@ -899,14 +902,14 @@
 #define E1000_TXDCTL   0x03828  /* TX Descriptor Control - RW */
 #define E1000_TADV     0x0382C  /* TX Interrupt Absolute Delay Val - RW */
 #define E1000_TSPMT    0x03830  /* TCP Segmentation PAD & Min Threshold - RW */
-#define E1000_TARC0    0x03840 /* TX Arbitration Count (0) */
-#define E1000_TDBAL1   0x03900 /* TX Desc Base Address Low (1) - RW */
-#define E1000_TDBAH1   0x03904 /* TX Desc Base Address High (1) - RW */
-#define E1000_TDLEN1   0x03908 /* TX Desc Length (1) - RW */
-#define E1000_TDH1     0x03910 /* TX Desc Head (1) - RW */
-#define E1000_TDT1     0x03918 /* TX Desc Tail (1) - RW */
-#define E1000_TXDCTL1  0x03928 /* TX Descriptor Control (1) - RW */
-#define E1000_TARC1    0x03940 /* TX Arbitration Count (1) */
+#define E1000_TARC0    0x03840  /* TX Arbitration Count (0) */
+#define E1000_TDBAL1   0x03900  /* TX Desc Base Address Low (1) - RW */
+#define E1000_TDBAH1   0x03904  /* TX Desc Base Address High (1) - RW */
+#define E1000_TDLEN1   0x03908  /* TX Desc Length (1) - RW */
+#define E1000_TDH1     0x03910  /* TX Desc Head (1) - RW */
+#define E1000_TDT1     0x03918  /* TX Desc Tail (1) - RW */
+#define E1000_TXDCTL1  0x03928  /* TX Descriptor Control (1) - RW */
+#define E1000_TARC1    0x03940  /* TX Arbitration Count (1) */
 #define E1000_CRCERRS  0x04000  /* CRC Error Count - R/clr */
 #define E1000_ALGNERRC 0x04004  /* Alignment Error Count - R/clr */
 #define E1000_SYMERRS  0x04008  /* Symbol Error Count - R/clr */
@@ -1761,7 +1764,6 @@
 #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
 #define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
                                               still to be processed. */
-
 /* Transmit Configuration Word */
 #define E1000_TXCW_FD         0x00000020        /* TXCW full duplex */
 #define E1000_TXCW_HD         0x00000040        /* TXCW half duplex */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index d0a5d16..31e3329 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -29,11 +29,71 @@
 #include "e1000.h"
 
 /* Change Log
- * 6.0.58       4/20/05
- *   o Accepted ethtool cleanup patch from Stephen Hemminger 
- * 6.0.44+	2/15/05
- *   o applied Anton's patch to resolve tx hang in hardware
- *   o Applied Andrew Mortons patch - e1000 stops working after resume
+ * 6.3.9	12/16/2005
+ *   o incorporate fix for recycled skbs from IBM LTC
+ * 6.3.7	11/18/2005
+ *   o Honor eeprom setting for enabling/disabling Wake On Lan
+ * 6.3.5 	11/17/2005
+ *   o Fix memory leak in rx ring handling for PCI Express adapters
+ * 6.3.4	11/8/05
+ *   o Patch from Jesper Juhl to remove redundant NULL checks for kfree
+ * 6.3.2	9/20/05
+ *   o Render logic that sets/resets DRV_LOAD as inline functions to 
+ *     avoid code replication. If f/w is AMT then set DRV_LOAD only when
+ *     network interface is open.
+ *   o Handle DRV_LOAD set/reset in cases where AMT uses VLANs.
+ *   o Adjust PBA partioning for Jumbo frames using MTU size and not
+ *     rx_buffer_len
+ * 6.3.1	9/19/05
+ *   o Use adapter->tx_timeout_factor in Tx Hung Detect logic 
+       (e1000_clean_tx_irq)
+ *   o Support for 8086:10B5 device (Quad Port)
+ * 6.2.14	9/15/05
+ *   o In AMT enabled configurations, set/reset DRV_LOAD bit on interface 
+ *     open/close 
+ * 6.2.13       9/14/05
+ *   o Invoke e1000_check_mng_mode only for 8257x controllers since it 
+ *     accesses the FWSM that is not supported in other controllers
+ * 6.2.12       9/9/05
+ *   o Add support for device id E1000_DEV_ID_82546GB_QUAD_COPPER
+ *   o set RCTL:SECRC only for controllers newer than 82543. 
+ *   o When the n/w interface comes down reset DRV_LOAD bit to notify f/w.
+ *     This code was moved from e1000_remove to e1000_close
+ * 6.2.10       9/6/05
+ *   o Fix error in updating RDT in el1000_alloc_rx_buffers[_ps] -- one off.
+ *   o Enable fc by default on 82573 controllers (do not read eeprom)
+ *   o Fix rx_errors statistic not to include missed_packet_count
+ *   o Fix rx_dropped statistic not to include missed_packet_count 
+       (Padraig Brady)
+ * 6.2.9        8/30/05
+ *   o Remove call to update statistics from the controller ib e1000_get_stats
+ * 6.2.8        8/30/05
+ *   o Improved algorithm for rx buffer allocation/rdt update
+ *   o Flow control watermarks relative to rx PBA size
+ *   o Simplified 'Tx Hung' detect logic
+ * 6.2.7 	8/17/05
+ *   o Report rx buffer allocation failures and tx timeout counts in stats
+ * 6.2.6 	8/16/05
+ *   o Implement workaround for controller erratum -- linear non-tso packet
+ *     following a TSO gets written back prematurely
+ * 6.2.5	8/15/05
+ *   o Set netdev->tx_queue_len based on link speed/duplex settings.
+ *   o Fix net_stats.rx_fifo_errors <p@draigBrady.com>
+ *   o Do not power off PHY if SoL/IDER session is active
+ * 6.2.4	8/10/05
+ *   o Fix loopback test setup/cleanup for 82571/3 controllers
+ *   o Fix parsing of outgoing packets (e1000_transfer_dhcp_info) to treat
+ *     all packets as raw
+ *   o Prevent operations that will cause the PHY to be reset if SoL/IDER
+ *     sessions are active and log a message
+ * 6.2.2	7/21/05
+ *   o used fixed size descriptors for all MTU sizes, reduces memory load
+ * 6.1.2	4/13/05
+ *   o Fixed ethtool diagnostics
+ *   o Enabled flow control to take default eeprom settings
+ *   o Added stats_lock around e1000_read_phy_reg commands to avoid concurrent
+ *     calls, one from mii_ioctl and other from within update_stats while 
+ *     processing MIIREG ioctl.
  */
 
 char e1000_driver_name[] = "e1000";
@@ -295,7 +355,7 @@
 static inline void
 e1000_irq_enable(struct e1000_adapter *adapter)
 {
-	if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
+	if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
 		E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
 		E1000_WRITE_FLUSH(&adapter->hw);
 	}
@@ -307,17 +367,17 @@
 	struct net_device *netdev = adapter->netdev;
 	uint16_t vid = adapter->hw.mng_cookie.vlan_id;
 	uint16_t old_vid = adapter->mng_vlan_id;
-	if(adapter->vlgrp) {
-		if(!adapter->vlgrp->vlan_devices[vid]) {
-			if(adapter->hw.mng_cookie.status &
+	if (adapter->vlgrp) {
+		if (!adapter->vlgrp->vlan_devices[vid]) {
+			if (adapter->hw.mng_cookie.status &
 				E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
 				e1000_vlan_rx_add_vid(netdev, vid);
 				adapter->mng_vlan_id = vid;
 			} else
 				adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-				
-			if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
-					(vid != old_vid) && 
+
+			if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
+					(vid != old_vid) &&
 					!adapter->vlgrp->vlan_devices[old_vid])
 				e1000_vlan_rx_kill_vid(netdev, old_vid);
 		}
@@ -401,10 +461,10 @@
 	/* hardware has been reset, we need to reload some things */
 
 	/* Reset the PHY if it was previously powered down */
-	if(adapter->hw.media_type == e1000_media_type_copper) {
+	if (adapter->hw.media_type == e1000_media_type_copper) {
 		uint16_t mii_reg;
 		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
-		if(mii_reg & MII_CR_POWER_DOWN)
+		if (mii_reg & MII_CR_POWER_DOWN)
 			e1000_phy_reset(&adapter->hw);
 	}
 
@@ -425,16 +485,16 @@
 	}
 
 #ifdef CONFIG_PCI_MSI
-	if(adapter->hw.mac_type > e1000_82547_rev_2) {
+	if (adapter->hw.mac_type > e1000_82547_rev_2) {
 		adapter->have_msi = TRUE;
-		if((err = pci_enable_msi(adapter->pdev))) {
+		if ((err = pci_enable_msi(adapter->pdev))) {
 			DPRINTK(PROBE, ERR,
 			 "Unable to allocate MSI interrupt Error: %d\n", err);
 			adapter->have_msi = FALSE;
 		}
 	}
 #endif
-	if((err = request_irq(adapter->pdev->irq, &e1000_intr,
+	if ((err = request_irq(adapter->pdev->irq, &e1000_intr,
 		              SA_SHIRQ | SA_SAMPLE_RANDOM,
 		              netdev->name, netdev))) {
 		DPRINTK(PROBE, ERR,
@@ -471,7 +531,7 @@
 #endif
 	free_irq(adapter->pdev->irq, netdev);
 #ifdef CONFIG_PCI_MSI
-	if(adapter->hw.mac_type > e1000_82547_rev_2 &&
+	if (adapter->hw.mac_type > e1000_82547_rev_2 &&
 	   adapter->have_msi == TRUE)
 		pci_disable_msi(adapter->pdev);
 #endif
@@ -537,12 +597,12 @@
 		break;
 	}
 
-	if((adapter->hw.mac_type != e1000_82573) &&
+	if ((adapter->hw.mac_type != e1000_82573) &&
 	   (adapter->netdev->mtu > E1000_RXBUFFER_8192))
 		pba -= 8; /* allocate more FIFO for Tx */
 
 
-	if(adapter->hw.mac_type == e1000_82547) {
+	if (adapter->hw.mac_type == e1000_82547) {
 		adapter->tx_fifo_head = 0;
 		adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
 		adapter->tx_fifo_size =
@@ -565,9 +625,9 @@
 
 	/* Allow time for pending master requests to run */
 	e1000_reset_hw(&adapter->hw);
-	if(adapter->hw.mac_type >= e1000_82544)
+	if (adapter->hw.mac_type >= e1000_82544)
 		E1000_WRITE_REG(&adapter->hw, WUC, 0);
-	if(e1000_init_hw(&adapter->hw))
+	if (e1000_init_hw(&adapter->hw))
 		DPRINTK(PROBE, ERR, "Hardware Error\n");
 	e1000_update_mng_vlan(adapter);
 	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
@@ -606,26 +666,26 @@
 	int i, err, pci_using_dac;
 	uint16_t eeprom_data;
 	uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
-	if((err = pci_enable_device(pdev)))
+	if ((err = pci_enable_device(pdev)))
 		return err;
 
-	if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+	if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
 		pci_using_dac = 1;
 	} else {
-		if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+		if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
 			E1000_ERR("No usable DMA configuration, aborting\n");
 			return err;
 		}
 		pci_using_dac = 0;
 	}
 
-	if((err = pci_request_regions(pdev, e1000_driver_name)))
+	if ((err = pci_request_regions(pdev, e1000_driver_name)))
 		return err;
 
 	pci_set_master(pdev);
 
 	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
-	if(!netdev) {
+	if (!netdev) {
 		err = -ENOMEM;
 		goto err_alloc_etherdev;
 	}
@@ -644,15 +704,15 @@
 	mmio_len = pci_resource_len(pdev, BAR_0);
 
 	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
-	if(!adapter->hw.hw_addr) {
+	if (!adapter->hw.hw_addr) {
 		err = -EIO;
 		goto err_ioremap;
 	}
 
-	for(i = BAR_1; i <= BAR_5; i++) {
-		if(pci_resource_len(pdev, i) == 0)
+	for (i = BAR_1; i <= BAR_5; i++) {
+		if (pci_resource_len(pdev, i) == 0)
 			continue;
-		if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+		if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
 			adapter->hw.io_base = pci_resource_start(pdev, i);
 			break;
 		}
@@ -689,13 +749,13 @@
 
 	/* setup the private structure */
 
-	if((err = e1000_sw_init(adapter)))
+	if ((err = e1000_sw_init(adapter)))
 		goto err_sw_init;
 
-	if((err = e1000_check_phy_reset_block(&adapter->hw)))
+	if ((err = e1000_check_phy_reset_block(&adapter->hw)))
 		DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
 
-	if(adapter->hw.mac_type >= e1000_82543) {
+	if (adapter->hw.mac_type >= e1000_82543) {
 		netdev->features = NETIF_F_SG |
 				   NETIF_F_HW_CSUM |
 				   NETIF_F_HW_VLAN_TX |
@@ -704,16 +764,16 @@
 	}
 
 #ifdef NETIF_F_TSO
-	if((adapter->hw.mac_type >= e1000_82544) &&
+	if ((adapter->hw.mac_type >= e1000_82544) &&
 	   (adapter->hw.mac_type != e1000_82547))
 		netdev->features |= NETIF_F_TSO;
 
 #ifdef NETIF_F_TSO_IPV6
-	if(adapter->hw.mac_type > e1000_82547_rev_2)
+	if (adapter->hw.mac_type > e1000_82547_rev_2)
 		netdev->features |= NETIF_F_TSO_IPV6;
 #endif
 #endif
-	if(pci_using_dac)
+	if (pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
  	/* hard_start_xmit is safe against parallel locking */
@@ -721,14 +781,14 @@
  
 	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
 
-	/* before reading the EEPROM, reset the controller to 
+	/* before reading the EEPROM, reset the controller to
 	 * put the device in a known good starting state */
-	
+
 	e1000_reset_hw(&adapter->hw);
 
 	/* make sure the EEPROM is good */
 
-	if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
+	if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
 		DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
 		err = -EIO;
 		goto err_eeprom;
@@ -736,12 +796,12 @@
 
 	/* copy the MAC address out of the EEPROM */
 
-	if(e1000_read_mac_addr(&adapter->hw))
+	if (e1000_read_mac_addr(&adapter->hw))
 		DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
 	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
 	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
 
-	if(!is_valid_ether_addr(netdev->perm_addr)) {
+	if (!is_valid_ether_addr(netdev->perm_addr)) {
 		DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
 		err = -EIO;
 		goto err_eeprom;
@@ -781,7 +841,7 @@
 	 * enable the ACPI Magic Packet filter
 	 */
 
-	switch(adapter->hw.mac_type) {
+	switch (adapter->hw.mac_type) {
 	case e1000_82542_rev2_0:
 	case e1000_82542_rev2_1:
 	case e1000_82543:
@@ -794,7 +854,7 @@
 	case e1000_82546:
 	case e1000_82546_rev_3:
 	case e1000_82571:
-		if(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){
+		if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){
 			e1000_read_eeprom(&adapter->hw,
 				EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
 			break;
@@ -805,7 +865,7 @@
 			EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
 		break;
 	}
-	if(eeprom_data & eeprom_apme_mask)
+	if (eeprom_data & eeprom_apme_mask)
 		adapter->wol |= E1000_WUFC_MAG;
 
 	/* print bus type/speed/width info */
@@ -840,7 +900,7 @@
 		e1000_get_hw_control(adapter);
 
 	strcpy(netdev->name, "eth%d");
-	if((err = register_netdev(netdev)))
+	if ((err = register_netdev(netdev)))
 		goto err_register;
 
 	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
@@ -881,10 +941,10 @@
 
 	flush_scheduled_work();
 
-	if(adapter->hw.mac_type >= e1000_82540 &&
+	if (adapter->hw.mac_type >= e1000_82540 &&
 	   adapter->hw.media_type == e1000_media_type_copper) {
 		manc = E1000_READ_REG(&adapter->hw, MANC);
-		if(manc & E1000_MANC_SMBUS_EN) {
+		if (manc & E1000_MANC_SMBUS_EN) {
 			manc |= E1000_MANC_ARP_EN;
 			E1000_WRITE_REG(&adapter->hw, MANC, manc);
 		}
@@ -900,7 +960,7 @@
 		__dev_put(&adapter->polling_netdev[i]);
 #endif
 
-	if(!e1000_check_phy_reset_block(&adapter->hw))
+	if (!e1000_check_phy_reset_block(&adapter->hw))
 		e1000_phy_hw_reset(&adapter->hw);
 
 	kfree(adapter->tx_ring);
@@ -959,19 +1019,19 @@
 
 	/* identify the MAC */
 
-	if(e1000_set_mac_type(hw)) {
+	if (e1000_set_mac_type(hw)) {
 		DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
 		return -EIO;
 	}
 
 	/* initialize eeprom parameters */
 
-	if(e1000_init_eeprom_params(hw)) {
+	if (e1000_init_eeprom_params(hw)) {
 		E1000_ERR("EEPROM initialization failed\n");
 		return -EIO;
 	}
 
-	switch(hw->mac_type) {
+	switch (hw->mac_type) {
 	default:
 		break;
 	case e1000_82541:
@@ -990,7 +1050,7 @@
 
 	/* Copper options */
 
-	if(hw->media_type == e1000_media_type_copper) {
+	if (hw->media_type == e1000_media_type_copper) {
 		hw->mdix = AUTO_ALL_MODES;
 		hw->disable_polarity_correction = FALSE;
 		hw->master_slave = E1000_MASTER_SLAVE;
@@ -1166,10 +1226,10 @@
 	if ((err = e1000_setup_all_rx_resources(adapter)))
 		goto err_setup_rx;
 
-	if((err = e1000_up(adapter)))
+	if ((err = e1000_up(adapter)))
 		goto err_up;
 	adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-	if((adapter->hw.mng_cookie.status &
+	if ((adapter->hw.mng_cookie.status &
 			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
 		e1000_update_mng_vlan(adapter);
 	}
@@ -1214,7 +1274,7 @@
 	e1000_free_all_tx_resources(adapter);
 	e1000_free_all_rx_resources(adapter);
 
-	if((adapter->hw.mng_cookie.status &
+	if ((adapter->hw.mng_cookie.status &
 			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
 		e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
 	}
@@ -1269,7 +1329,7 @@
 	size = sizeof(struct e1000_buffer) * txdr->count;
 
 	txdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
-	if(!txdr->buffer_info) {
+	if (!txdr->buffer_info) {
 		DPRINTK(PROBE, ERR,
 		"Unable to allocate memory for the transmit descriptor ring\n");
 		return -ENOMEM;
@@ -1282,7 +1342,7 @@
 	E1000_ROUNDUP(txdr->size, 4096);
 
 	txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
-	if(!txdr->desc) {
+	if (!txdr->desc) {
 setup_tx_desc_die:
 		vfree(txdr->buffer_info);
 		DPRINTK(PROBE, ERR,
@@ -1298,8 +1358,8 @@
 				     "at %p\n", txdr->size, txdr->desc);
 		/* Try again, without freeing the previous */
 		txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
-		if(!txdr->desc) {
 		/* Failed allocation, critical failure */
+		if (!txdr->desc) {
 			pci_free_consistent(pdev, txdr->size, olddesc, olddma);
 			goto setup_tx_desc_die;
 		}
@@ -1499,7 +1559,7 @@
 
 	size = sizeof(struct e1000_ps_page) * rxdr->count;
 	rxdr->ps_page = kmalloc(size, GFP_KERNEL);
-	if(!rxdr->ps_page) {
+	if (!rxdr->ps_page) {
 		vfree(rxdr->buffer_info);
 		DPRINTK(PROBE, ERR,
 		"Unable to allocate memory for the receive descriptor ring\n");
@@ -1509,7 +1569,7 @@
 
 	size = sizeof(struct e1000_ps_page_dma) * rxdr->count;
 	rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL);
-	if(!rxdr->ps_page_dma) {
+	if (!rxdr->ps_page_dma) {
 		vfree(rxdr->buffer_info);
 		kfree(rxdr->ps_page);
 		DPRINTK(PROBE, ERR,
@@ -1518,7 +1578,7 @@
 	}
 	memset(rxdr->ps_page_dma, 0, size);
 
-	if(adapter->hw.mac_type <= e1000_82547_rev_2)
+	if (adapter->hw.mac_type <= e1000_82547_rev_2)
 		desc_len = sizeof(struct e1000_rx_desc);
 	else
 		desc_len = sizeof(union e1000_rx_desc_packet_split);
@@ -1621,7 +1681,7 @@
 {
 	uint32_t rctl, rfctl;
 	uint32_t psrctl = 0;
-#ifdef CONFIG_E1000_PACKET_SPLIT
+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
 	uint32_t pages = 0;
 #endif
 
@@ -1647,32 +1707,17 @@
 		rctl |= E1000_RCTL_LPE;
 
 	/* Setup buffer sizes */
-	if(adapter->hw.mac_type >= e1000_82571) {
+	if (adapter->hw.mac_type >= e1000_82571) {
 		/* We can now specify buffers in 1K increments.
 		 * BSIZE and BSEX are ignored in this case. */
 		rctl |= adapter->rx_buffer_len << 0x11;
 	} else {
 		rctl &= ~E1000_RCTL_SZ_4096;
-		rctl |= E1000_RCTL_BSEX; 
-		switch (adapter->rx_buffer_len) {
-		case E1000_RXBUFFER_2048:
-		default:
-			rctl |= E1000_RCTL_SZ_2048;
-			rctl &= ~E1000_RCTL_BSEX;
-			break;
-		case E1000_RXBUFFER_4096:
-			rctl |= E1000_RCTL_SZ_4096;
-			break;
-		case E1000_RXBUFFER_8192:
-			rctl |= E1000_RCTL_SZ_8192;
-			break;
-		case E1000_RXBUFFER_16384:
-			rctl |= E1000_RCTL_SZ_16384;
-			break;
-		}
+		rctl &= ~E1000_RCTL_BSEX;
+		rctl |= E1000_RCTL_SZ_2048;
 	}
 
-#ifdef CONFIG_E1000_PACKET_SPLIT
+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
 	/* 82571 and greater support packet-split where the protocol
 	 * header is placed in skb->data and the packet data is
 	 * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
@@ -1696,7 +1741,7 @@
 		E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
 
 		rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC;
-		
+
 		psrctl |= adapter->rx_ps_bsize0 >>
 			E1000_PSRCTL_BSIZE0_SHIFT;
 
@@ -1758,7 +1803,7 @@
 
 	if (hw->mac_type >= e1000_82540) {
 		E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
-		if(adapter->itr > 1)
+		if (adapter->itr > 1)
 			E1000_WRITE_REG(hw, ITR,
 				1000000000 / (adapter->itr * 256));
 	}
@@ -1847,13 +1892,13 @@
 	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
 	if (hw->mac_type >= e1000_82543) {
 		rxcsum = E1000_READ_REG(hw, RXCSUM);
-		if(adapter->rx_csum == TRUE) {
+		if (adapter->rx_csum == TRUE) {
 			rxcsum |= E1000_RXCSUM_TUOFL;
 
 			/* Enable 82571 IPv4 payload checksum for UDP fragments
 			 * Must be used in conjunction with packet-split. */
-			if ((hw->mac_type >= e1000_82571) && 
-			   (adapter->rx_ps_pages)) {
+			if ((hw->mac_type >= e1000_82571) &&
+			    (adapter->rx_ps_pages)) {
 				rxcsum |= E1000_RXCSUM_IPPCSE;
 			}
 		} else {
@@ -1915,7 +1960,7 @@
 e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
 			struct e1000_buffer *buffer_info)
 {
-	if(buffer_info->dma) {
+	if (buffer_info->dma) {
 		pci_unmap_page(adapter->pdev,
 				buffer_info->dma,
 				buffer_info->length,
@@ -1942,7 +1987,7 @@
 
 	/* Free all the Tx ring sk_buffs */
 
-	for(i = 0; i < tx_ring->count; i++) {
+	for (i = 0; i < tx_ring->count; i++) {
 		buffer_info = &tx_ring->buffer_info[i];
 		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
 	}
@@ -2038,10 +2083,9 @@
 	unsigned int i, j;
 
 	/* Free all the Rx ring sk_buffs */
-
-	for(i = 0; i < rx_ring->count; i++) {
+	for (i = 0; i < rx_ring->count; i++) {
 		buffer_info = &rx_ring->buffer_info[i];
-		if(buffer_info->skb) {
+		if (buffer_info->skb) {
 			pci_unmap_single(pdev,
 					 buffer_info->dma,
 					 buffer_info->length,
@@ -2122,7 +2166,7 @@
 	E1000_WRITE_FLUSH(&adapter->hw);
 	mdelay(5);
 
-	if(netif_running(netdev))
+	if (netif_running(netdev))
 		e1000_clean_all_rx_rings(adapter);
 }
 
@@ -2138,13 +2182,13 @@
 	E1000_WRITE_FLUSH(&adapter->hw);
 	mdelay(5);
 
-	if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
+	if (adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
 		e1000_pci_set_mwi(&adapter->hw);
 
-	if(netif_running(netdev)) {
-		e1000_configure_rx(adapter);
+	if (netif_running(netdev)) {
 		/* No need to loop, because 82542 supports only 1 queue */
 		struct e1000_rx_ring *ring = &adapter->rx_ring[0];
+		e1000_configure_rx(adapter);
 		adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
 	}
 }
@@ -2163,12 +2207,12 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct sockaddr *addr = p;
 
-	if(!is_valid_ether_addr(addr->sa_data))
+	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
 	/* 82542 2.0 needs to be in reset to write receive address registers */
 
-	if(adapter->hw.mac_type == e1000_82542_rev2_0)
+	if (adapter->hw.mac_type == e1000_82542_rev2_0)
 		e1000_enter_82542_rst(adapter);
 
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
@@ -2182,17 +2226,17 @@
 		/* activate the work around */
 		adapter->hw.laa_is_present = 1;
 
-		/* Hold a copy of the LAA in RAR[14] This is done so that 
-		 * between the time RAR[0] gets clobbered  and the time it 
-		 * gets fixed (in e1000_watchdog), the actual LAA is in one 
+		/* Hold a copy of the LAA in RAR[14] This is done so that
+		 * between the time RAR[0] gets clobbered  and the time it
+		 * gets fixed (in e1000_watchdog), the actual LAA is in one
 		 * of the RARs and no incoming packets directed to this port
-		 * are dropped. Eventaully the LAA will be in RAR[0] and 
+		 * are dropped. Eventaully the LAA will be in RAR[0] and
 		 * RAR[14] */
-		e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 
+		e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
 					E1000_RAR_ENTRIES - 1);
 	}
 
-	if(adapter->hw.mac_type == e1000_82542_rev2_0)
+	if (adapter->hw.mac_type == e1000_82542_rev2_0)
 		e1000_leave_82542_rst(adapter);
 
 	return 0;
@@ -2226,9 +2270,9 @@
 
 	rctl = E1000_READ_REG(hw, RCTL);
 
-	if(netdev->flags & IFF_PROMISC) {
+	if (netdev->flags & IFF_PROMISC) {
 		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
-	} else if(netdev->flags & IFF_ALLMULTI) {
+	} else if (netdev->flags & IFF_ALLMULTI) {
 		rctl |= E1000_RCTL_MPE;
 		rctl &= ~E1000_RCTL_UPE;
 	} else {
@@ -2239,7 +2283,7 @@
 
 	/* 82542 2.0 needs to be in reset to write receive address registers */
 
-	if(hw->mac_type == e1000_82542_rev2_0)
+	if (hw->mac_type == e1000_82542_rev2_0)
 		e1000_enter_82542_rst(adapter);
 
 	/* load the first 14 multicast address into the exact filters 1-14
@@ -2249,7 +2293,7 @@
 	 */
 	mc_ptr = netdev->mc_list;
 
-	for(i = 1; i < rar_entries; i++) {
+	for (i = 1; i < rar_entries; i++) {
 		if (mc_ptr) {
 			e1000_rar_set(hw, mc_ptr->dmi_addr, i);
 			mc_ptr = mc_ptr->next;
@@ -2261,17 +2305,17 @@
 
 	/* clear the old settings from the multicast hash table */
 
-	for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
+	for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
 		E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
 
 	/* load any remaining addresses into the hash table */
 
-	for(; mc_ptr; mc_ptr = mc_ptr->next) {
+	for (; mc_ptr; mc_ptr = mc_ptr->next) {
 		hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr);
 		e1000_mta_set(hw, hash_value);
 	}
 
-	if(hw->mac_type == e1000_82542_rev2_0)
+	if (hw->mac_type == e1000_82542_rev2_0)
 		e1000_leave_82542_rst(adapter);
 }
 
@@ -2297,8 +2341,8 @@
 	struct net_device *netdev = adapter->netdev;
 	uint32_t tctl;
 
-	if(atomic_read(&adapter->tx_fifo_stall)) {
-		if((E1000_READ_REG(&adapter->hw, TDT) ==
+	if (atomic_read(&adapter->tx_fifo_stall)) {
+		if ((E1000_READ_REG(&adapter->hw, TDT) ==
 		    E1000_READ_REG(&adapter->hw, TDH)) &&
 		   (E1000_READ_REG(&adapter->hw, TDFT) ==
 		    E1000_READ_REG(&adapter->hw, TDFH)) &&
@@ -2350,18 +2394,18 @@
 	e1000_check_for_link(&adapter->hw);
 	if (adapter->hw.mac_type == e1000_82573) {
 		e1000_enable_tx_pkt_filtering(&adapter->hw);
-		if(adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
+		if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
 			e1000_update_mng_vlan(adapter);
-	}	
+	}
 
-	if((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
+	if ((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
 	   !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
 		link = !adapter->hw.serdes_link_down;
 	else
 		link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
 
-	if(link) {
-		if(!netif_carrier_ok(netdev)) {
+	if (link) {
+		if (!netif_carrier_ok(netdev)) {
 			e1000_get_speed_and_duplex(&adapter->hw,
 			                           &adapter->link_speed,
 			                           &adapter->link_duplex);
@@ -2392,7 +2436,7 @@
 			adapter->smartspeed = 0;
 		}
 	} else {
-		if(netif_carrier_ok(netdev)) {
+		if (netif_carrier_ok(netdev)) {
 			adapter->link_speed = 0;
 			adapter->link_duplex = 0;
 			DPRINTK(LINK, INFO, "NIC Link is Down\n");
@@ -2432,12 +2476,12 @@
 	}
 
 	/* Dynamic mode for Interrupt Throttle Rate (ITR) */
-	if(adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
+	if (adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
 		/* Symmetric Tx/Rx gets a reduced ITR=2000; Total
 		 * asymmetrical Tx or Rx gets ITR=8000; everyone
 		 * else is between 2000-8000. */
 		uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000;
-		uint32_t dif = (adapter->gotcl > adapter->gorcl ? 
+		uint32_t dif = (adapter->gotcl > adapter->gorcl ?
 			adapter->gotcl - adapter->gorcl :
 			adapter->gorcl - adapter->gotcl) / 10000;
 		uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
@@ -2450,7 +2494,7 @@
 	/* Force detection of hung controller every watchdog period */
 	adapter->detect_tx_hung = TRUE;
 
-	/* With 82571 controllers, LAA may be overwritten due to controller 
+	/* With 82571 controllers, LAA may be overwritten due to controller
 	 * reset from the other port. Set the appropriate LAA in RAR[0] */
 	if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
 		e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
@@ -2479,7 +2523,7 @@
 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
 	int err;
 
-	if(skb_shinfo(skb)->tso_size) {
+	if (skb_shinfo(skb)->tso_size) {
 		if (skb_header_cloned(skb)) {
 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 			if (err)
@@ -2488,7 +2532,7 @@
 
 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
 		mss = skb_shinfo(skb)->tso_size;
-		if(skb->protocol == ntohs(ETH_P_IP)) {
+		if (skb->protocol == ntohs(ETH_P_IP)) {
 			skb->nh.iph->tot_len = 0;
 			skb->nh.iph->check = 0;
 			skb->h.th->check =
@@ -2500,7 +2544,7 @@
 			cmd_length = E1000_TXD_CMD_IP;
 			ipcse = skb->h.raw - skb->data - 1;
 #ifdef NETIF_F_TSO_IPV6
-		} else if(skb->protocol == ntohs(ETH_P_IPV6)) {
+		} else if (skb->protocol == ntohs(ETH_P_IPV6)) {
 			skb->nh.ipv6h->payload_len = 0;
 			skb->h.th->check =
 				~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
@@ -2555,7 +2599,7 @@
 	unsigned int i;
 	uint8_t css;
 
-	if(likely(skb->ip_summed == CHECKSUM_HW)) {
+	if (likely(skb->ip_summed == CHECKSUM_HW)) {
 		css = skb->h.raw - skb->data;
 
 		i = tx_ring->next_to_use;
@@ -2595,7 +2639,7 @@
 
 	i = tx_ring->next_to_use;
 
-	while(len) {
+	while (len) {
 		buffer_info = &tx_ring->buffer_info[i];
 		size = min(len, max_per_txd);
 #ifdef NETIF_F_TSO
@@ -2611,7 +2655,7 @@
 
 		/* Workaround for premature desc write-backs
 		 * in TSO mode.  Append 4-byte sentinel desc */
-		if(unlikely(mss && !nr_frags && size == len && size > 8))
+		if (unlikely(mss && !nr_frags && size == len && size > 8))
 			size -= 4;
 #endif
 		/* work-around for errata 10 and it applies
@@ -2619,13 +2663,13 @@
 		 * The fix is to make sure that the first descriptor of a
 		 * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
 		 */
-		if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+		if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
 		                (size > 2015) && count == 0))
 		        size = 2015;
-                                                                                
+
 		/* Workaround for potential 82544 hang in PCI-X.  Avoid
 		 * terminating buffers within evenly-aligned dwords. */
-		if(unlikely(adapter->pcix_82544 &&
+		if (unlikely(adapter->pcix_82544 &&
 		   !((unsigned long)(skb->data + offset + size - 1) & 4) &&
 		   size > 4))
 			size -= 4;
@@ -2641,29 +2685,29 @@
 		len -= size;
 		offset += size;
 		count++;
-		if(unlikely(++i == tx_ring->count)) i = 0;
+		if (unlikely(++i == tx_ring->count)) i = 0;
 	}
 
-	for(f = 0; f < nr_frags; f++) {
+	for (f = 0; f < nr_frags; f++) {
 		struct skb_frag_struct *frag;
 
 		frag = &skb_shinfo(skb)->frags[f];
 		len = frag->size;
 		offset = frag->page_offset;
 
-		while(len) {
+		while (len) {
 			buffer_info = &tx_ring->buffer_info[i];
 			size = min(len, max_per_txd);
 #ifdef NETIF_F_TSO
 			/* Workaround for premature desc write-backs
 			 * in TSO mode.  Append 4-byte sentinel desc */
-			if(unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
+			if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
 				size -= 4;
 #endif
 			/* Workaround for potential 82544 hang in PCI-X.
 			 * Avoid terminating buffers within evenly-aligned
 			 * dwords. */
-			if(unlikely(adapter->pcix_82544 &&
+			if (unlikely(adapter->pcix_82544 &&
 			   !((unsigned long)(frag->page+offset+size-1) & 4) &&
 			   size > 4))
 				size -= 4;
@@ -2680,7 +2724,7 @@
 			len -= size;
 			offset += size;
 			count++;
-			if(unlikely(++i == tx_ring->count)) i = 0;
+			if (unlikely(++i == tx_ring->count)) i = 0;
 		}
 	}
 
@@ -2700,35 +2744,35 @@
 	uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
 	unsigned int i;
 
-	if(likely(tx_flags & E1000_TX_FLAGS_TSO)) {
+	if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
 		             E1000_TXD_CMD_TSE;
 		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
 
-		if(likely(tx_flags & E1000_TX_FLAGS_IPV4))
+		if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
 			txd_upper |= E1000_TXD_POPTS_IXSM << 8;
 	}
 
-	if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
+	if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
 		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
 	}
 
-	if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
+	if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
 		txd_lower |= E1000_TXD_CMD_VLE;
 		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
 	}
 
 	i = tx_ring->next_to_use;
 
-	while(count--) {
+	while (count--) {
 		buffer_info = &tx_ring->buffer_info[i];
 		tx_desc = E1000_TX_DESC(*tx_ring, i);
 		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
 		tx_desc->lower.data =
 			cpu_to_le32(txd_lower | buffer_info->length);
 		tx_desc->upper.data = cpu_to_le32(txd_upper);
-		if(unlikely(++i == tx_ring->count)) i = 0;
+		if (unlikely(++i == tx_ring->count)) i = 0;
 	}
 
 	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
@@ -2763,20 +2807,20 @@
 
 	E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR);
 
-	if(adapter->link_duplex != HALF_DUPLEX)
+	if (adapter->link_duplex != HALF_DUPLEX)
 		goto no_fifo_stall_required;
 
-	if(atomic_read(&adapter->tx_fifo_stall))
+	if (atomic_read(&adapter->tx_fifo_stall))
 		return 1;
 
-	if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
+	if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
 		atomic_set(&adapter->tx_fifo_stall, 1);
 		return 1;
 	}
 
 no_fifo_stall_required:
 	adapter->tx_fifo_head += skb_fifo_len;
-	if(adapter->tx_fifo_head >= adapter->tx_fifo_size)
+	if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
 		adapter->tx_fifo_head -= adapter->tx_fifo_size;
 	return 0;
 }
@@ -2787,27 +2831,27 @@
 {
 	struct e1000_hw *hw =  &adapter->hw;
 	uint16_t length, offset;
-	if(vlan_tx_tag_present(skb)) {
-		if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+	if (vlan_tx_tag_present(skb)) {
+		if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
 			( adapter->hw.mng_cookie.status &
 			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
 			return 0;
 	}
- 	if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
+	if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
 		struct ethhdr *eth = (struct ethhdr *) skb->data;
-		if((htons(ETH_P_IP) == eth->h_proto)) {
-			const struct iphdr *ip = 
+		if ((htons(ETH_P_IP) == eth->h_proto)) {
+			const struct iphdr *ip =
 				(struct iphdr *)((uint8_t *)skb->data+14);
-			if(IPPROTO_UDP == ip->protocol) {
-				struct udphdr *udp = 
-					(struct udphdr *)((uint8_t *)ip + 
+			if (IPPROTO_UDP == ip->protocol) {
+				struct udphdr *udp =
+					(struct udphdr *)((uint8_t *)ip +
 						(ip->ihl << 2));
-				if(ntohs(udp->dest) == 67) {
+				if (ntohs(udp->dest) == 67) {
 					offset = (uint8_t *)udp + 8 - skb->data;
 					length = skb->len - offset;
 
 					return e1000_mng_write_dhcp_info(hw,
-							(uint8_t *)udp + 8, 
+							(uint8_t *)udp + 8,
 							length);
 				}
 			}
@@ -2830,7 +2874,7 @@
 	unsigned int nr_frags = 0;
 	unsigned int mss = 0;
 	int count = 0;
-	int tso;
+ 	int tso;
 	unsigned int f;
 	len -= skb->data_len;
 
@@ -2853,7 +2897,7 @@
 	 * 4 = ceil(buffer len/mss).  To make sure we don't
 	 * overrun the FIFO, adjust the max buffer len if mss
 	 * drops. */
-	if(mss) {
+	if (mss) {
 		uint8_t hdr_len;
 		max_per_txd = min(mss << 2, max_per_txd);
 		max_txd_pwr = fls(max_per_txd) - 1;
@@ -2876,12 +2920,12 @@
 		}
 	}
 
-	if((mss) || (skb->ip_summed == CHECKSUM_HW))
 	/* reserve a descriptor for the offload context */
+	if ((mss) || (skb->ip_summed == CHECKSUM_HW))
 		count++;
 	count++;
 #else
-	if(skb->ip_summed == CHECKSUM_HW)
+	if (skb->ip_summed == CHECKSUM_HW)
 		count++;
 #endif
 
@@ -2894,24 +2938,24 @@
 
 	count += TXD_USE_COUNT(len, max_txd_pwr);
 
-	if(adapter->pcix_82544)
+	if (adapter->pcix_82544)
 		count++;
 
-	/* work-around for errata 10 and it applies to all controllers 
+	/* work-around for errata 10 and it applies to all controllers
 	 * in PCI-X mode, so add one more descriptor to the count
 	 */
-	if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+	if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
 			(len > 2015)))
 		count++;
 
 	nr_frags = skb_shinfo(skb)->nr_frags;
-	for(f = 0; f < nr_frags; f++)
+	for (f = 0; f < nr_frags; f++)
 		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
 				       max_txd_pwr);
-	if(adapter->pcix_82544)
+	if (adapter->pcix_82544)
 		count += nr_frags;
 
-	if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
+	if (adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
 		e1000_transfer_dhcp_info(adapter, skb);
 
 	local_irq_save(flags);
@@ -2929,8 +2973,8 @@
 		return NETDEV_TX_BUSY;
 	}
 
-	if(unlikely(adapter->hw.mac_type == e1000_82547)) {
-		if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
+	if (unlikely(adapter->hw.mac_type == e1000_82547)) {
+		if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
 			netif_stop_queue(netdev);
 			mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
 			spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
@@ -2938,13 +2982,13 @@
 		}
 	}
 
-	if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+	if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
 		tx_flags |= E1000_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
 	}
 
 	first = tx_ring->next_to_use;
-	
+
 	tso = e1000_tso(adapter, tx_ring, skb);
 	if (tso < 0) {
 		dev_kfree_skb_any(skb);
@@ -3033,9 +3077,9 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
 
-	if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
-		(max_frame > MAX_JUMBO_FRAME_SIZE)) {
-			DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
+	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
 		return -EINVAL;
 	}
 
@@ -3083,7 +3127,7 @@
 
 	netdev->mtu = new_mtu;
 
-	if(netif_running(netdev)) {
+	if (netif_running(netdev)) {
 		e1000_down(adapter);
 		e1000_up(adapter);
 	}
@@ -3170,7 +3214,7 @@
 	hw->collision_delta = E1000_READ_REG(hw, COLC);
 	adapter->stats.colc += hw->collision_delta;
 
-	if(hw->mac_type >= e1000_82543) {
+	if (hw->mac_type >= e1000_82543) {
 		adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
 		adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
 		adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
@@ -3178,7 +3222,7 @@
 		adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
 		adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
 	}
-	if(hw->mac_type > e1000_82547_rev_2) {
+	if (hw->mac_type > e1000_82547_rev_2) {
 		adapter->stats.iac += E1000_READ_REG(hw, IAC);
 		adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
 		adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
@@ -3222,14 +3266,14 @@
 
 	/* Phy Stats */
 
-	if(hw->media_type == e1000_media_type_copper) {
-		if((adapter->link_speed == SPEED_1000) &&
+	if (hw->media_type == e1000_media_type_copper) {
+		if ((adapter->link_speed == SPEED_1000) &&
 		   (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
 			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
 			adapter->phy_stats.idle_errors += phy_tmp;
 		}
 
-		if((hw->mac_type <= e1000_82546) &&
+		if ((hw->mac_type <= e1000_82546) &&
 		   (hw->phy_type == e1000_phy_m88) &&
 		   !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
 			adapter->phy_stats.receive_errors += phy_tmp;
@@ -3294,7 +3338,7 @@
 		return IRQ_NONE;  /* Not our interrupt */
 	}
 
-	if(unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
+	if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
 		hw->get_link_status = 1;
 		mod_timer(&adapter->watchdog_timer, jiffies);
 	}
@@ -3326,26 +3370,26 @@
 
 #else /* if !CONFIG_E1000_NAPI */
 	/* Writing IMC and IMS is needed for 82547.
-	   Due to Hub Link bus being occupied, an interrupt
-	   de-assertion message is not able to be sent.
-	   When an interrupt assertion message is generated later,
-	   two messages are re-ordered and sent out.
-	   That causes APIC to think 82547 is in de-assertion
-	   state, while 82547 is in assertion state, resulting
-	   in dead lock. Writing IMC forces 82547 into
-	   de-assertion state.
-	*/
-	if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2){
+	 * Due to Hub Link bus being occupied, an interrupt
+	 * de-assertion message is not able to be sent.
+	 * When an interrupt assertion message is generated later,
+	 * two messages are re-ordered and sent out.
+	 * That causes APIC to think 82547 is in de-assertion
+	 * state, while 82547 is in assertion state, resulting
+	 * in dead lock. Writing IMC forces 82547 into
+	 * de-assertion state.
+	 */
+	if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) {
 		atomic_inc(&adapter->irq_sem);
 		E1000_WRITE_REG(hw, IMC, ~0);
 	}
 
-	for(i = 0; i < E1000_MAX_INTR; i++)
-		if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+	for (i = 0; i < E1000_MAX_INTR; i++)
+		if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
 		   !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
 			break;
 
-	if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
+	if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
 		e1000_irq_enable(adapter);
 
 #endif /* CONFIG_E1000_NAPI */
@@ -3397,9 +3441,9 @@
 
 	*budget -= work_done;
 	poll_dev->quota -= work_done;
-	
+
 	/* If no Tx and not enough Rx work done, exit the polling mode */
-	if((!tx_cleaned && (work_done == 0)) ||
+	if ((!tx_cleaned && (work_done == 0)) ||
 	   !netif_running(adapter->netdev)) {
 quit_polling:
 		netif_rx_complete(poll_dev);
@@ -3431,7 +3475,7 @@
 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
 	while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
-		for(cleaned = FALSE; !cleaned; ) {
+		for (cleaned = FALSE; !cleaned; ) {
 			tx_desc = E1000_TX_DESC(*tx_ring, i);
 			buffer_info = &tx_ring->buffer_info[i];
 			cleaned = (i == eop);
@@ -3442,7 +3486,7 @@
 			e1000_unmap_and_free_tx_resource(adapter, buffer_info);
 			memset(tx_desc, 0, sizeof(struct e1000_tx_desc));
 
-			if(unlikely(++i == tx_ring->count)) i = 0;
+			if (unlikely(++i == tx_ring->count)) i = 0;
 		}
 
 #ifdef CONFIG_E1000_MQ
@@ -3457,7 +3501,7 @@
 
 	spin_lock(&tx_ring->tx_lock);
 
-	if(unlikely(cleaned && netif_queue_stopped(netdev) &&
+	if (unlikely(cleaned && netif_queue_stopped(netdev) &&
 		    netif_carrier_ok(netdev)))
 		netif_wake_queue(netdev);
 
@@ -3519,21 +3563,21 @@
 	skb->ip_summed = CHECKSUM_NONE;
 
 	/* 82543 or newer only */
-	if(unlikely(adapter->hw.mac_type < e1000_82543)) return;
+	if (unlikely(adapter->hw.mac_type < e1000_82543)) return;
 	/* Ignore Checksum bit is set */
-	if(unlikely(status & E1000_RXD_STAT_IXSM)) return;
+	if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
 	/* TCP/UDP checksum error bit is set */
-	if(unlikely(errors & E1000_RXD_ERR_TCPE)) {
+	if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
 		/* let the stack verify checksum errors */
 		adapter->hw_csum_err++;
 		return;
 	}
 	/* TCP/UDP Checksum has not been calculated */
-	if(adapter->hw.mac_type <= e1000_82547_rev_2) {
-		if(!(status & E1000_RXD_STAT_TCPCS))
+	if (adapter->hw.mac_type <= e1000_82547_rev_2) {
+		if (!(status & E1000_RXD_STAT_TCPCS))
 			return;
 	} else {
-		if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
+		if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
 			return;
 	}
 	/* It must be a TCP or UDP packet with a valid checksum */
@@ -3569,9 +3613,8 @@
 {
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_rx_desc *rx_desc;
-	struct e1000_buffer *buffer_info;
-	struct sk_buff *skb;
+	struct e1000_rx_desc *rx_desc, *next_rxd;
+	struct e1000_buffer *buffer_info, *next_buffer;
 	unsigned long flags;
 	uint32_t length;
 	uint8_t last_byte;
@@ -3581,16 +3624,25 @@
 
 	i = rx_ring->next_to_clean;
 	rx_desc = E1000_RX_DESC(*rx_ring, i);
+	buffer_info = &rx_ring->buffer_info[i];
 
-	while(rx_desc->status & E1000_RXD_STAT_DD) {
-		buffer_info = &rx_ring->buffer_info[i];
+	while (rx_desc->status & E1000_RXD_STAT_DD) {
+		struct sk_buff *skb, *next_skb;
 		u8 status;
 #ifdef CONFIG_E1000_NAPI
-		if(*work_done >= work_to_do)
+		if (*work_done >= work_to_do)
 			break;
 		(*work_done)++;
 #endif
 		status = rx_desc->status;
+		skb = buffer_info->skb;
+		buffer_info->skb = NULL;
+
+		if (++i == rx_ring->count) i = 0;
+		next_rxd = E1000_RX_DESC(*rx_ring, i);
+		next_buffer = &rx_ring->buffer_info[i];
+		next_skb = next_buffer->skb;
+
 		cleaned = TRUE;
 		cleaned_count++;
 		pci_unmap_single(pdev,
@@ -3598,20 +3650,50 @@
 		                 buffer_info->length,
 		                 PCI_DMA_FROMDEVICE);
 
-		skb = buffer_info->skb;
 		length = le16_to_cpu(rx_desc->length);
 
-		if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) {
-			/* All receives must fit into a single buffer */
-			E1000_DBG("%s: Receive packet consumed multiple"
-				  " buffers\n", netdev->name);
-			dev_kfree_skb_irq(skb);
+		skb_put(skb, length);
+
+		if (!(status & E1000_RXD_STAT_EOP)) {
+			if (!rx_ring->rx_skb_top) {
+				rx_ring->rx_skb_top = skb;
+				rx_ring->rx_skb_top->len = length;
+				rx_ring->rx_skb_prev = skb;
+			} else {
+				if (skb_shinfo(rx_ring->rx_skb_top)->frag_list) {
+					rx_ring->rx_skb_prev->next = skb;
+					skb->prev = rx_ring->rx_skb_prev;
+				} else {
+					skb_shinfo(rx_ring->rx_skb_top)->frag_list = skb;
+				}
+				rx_ring->rx_skb_prev = skb;
+				rx_ring->rx_skb_top->data_len += length;
+			}
 			goto next_desc;
+		} else {
+			if (rx_ring->rx_skb_top) {
+				if (skb_shinfo(rx_ring->rx_skb_top)
+							->frag_list) {
+					rx_ring->rx_skb_prev->next = skb;
+					skb->prev = rx_ring->rx_skb_prev;
+				} else
+					skb_shinfo(rx_ring->rx_skb_top)
+							->frag_list = skb;
+
+				rx_ring->rx_skb_top->data_len += length;
+				rx_ring->rx_skb_top->len +=
+					rx_ring->rx_skb_top->data_len;
+
+				skb = rx_ring->rx_skb_top;
+				multi_descriptor = TRUE;
+				rx_ring->rx_skb_top = NULL;
+				rx_ring->rx_skb_prev = NULL;
+			}
 		}
 
-		if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
+		if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
 			last_byte = *(skb->data + length - 1);
-			if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
+			if (TBI_ACCEPT(&adapter->hw, status,
 			              rx_desc->errors, length, last_byte)) {
 				spin_lock_irqsave(&adapter->stats_lock, flags);
 				e1000_tbi_adjust_stats(&adapter->hw,
@@ -3656,9 +3738,10 @@
 				  (uint32_t)(status) |
 				  ((uint32_t)(rx_desc->errors) << 24),
 				  rx_desc->csum, skb);
+
 		skb->protocol = eth_type_trans(skb, netdev);
 #ifdef CONFIG_E1000_NAPI
-		if(unlikely(adapter->vlgrp &&
+		if (unlikely(adapter->vlgrp &&
 			    (status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
 						 le16_to_cpu(rx_desc->special) &
@@ -3667,8 +3750,8 @@
 			netif_receive_skb(skb);
 		}
 #else /* CONFIG_E1000_NAPI */
-		if(unlikely(adapter->vlgrp &&
-			    (rx_desc->status & E1000_RXD_STAT_VP))) {
+		if (unlikely(adapter->vlgrp &&
+			    (status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_rx(skb, adapter->vlgrp,
 					le16_to_cpu(rx_desc->special) &
 					E1000_RXD_SPC_VLAN_MASK);
@@ -3691,6 +3774,8 @@
 			cleaned_count = 0;
 		}
 
+		rx_desc = next_rxd;
+		buffer_info = next_buffer;
 	}
 	rx_ring->next_to_clean = i;
 
@@ -3716,13 +3801,13 @@
                       struct e1000_rx_ring *rx_ring)
 #endif
 {
-	union e1000_rx_desc_packet_split *rx_desc;
+	union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_buffer *buffer_info;
+	struct e1000_buffer *buffer_info, *next_buffer;
 	struct e1000_ps_page *ps_page;
 	struct e1000_ps_page_dma *ps_page_dma;
-	struct sk_buff *skb;
+	struct sk_buff *skb, *next_skb;
 	unsigned int i, j;
 	uint32_t length, staterr;
 	int cleaned_count = 0;
@@ -3731,39 +3816,44 @@
 	i = rx_ring->next_to_clean;
 	rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
 	staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+	buffer_info = &rx_ring->buffer_info[i];
 
-	while(staterr & E1000_RXD_STAT_DD) {
-		buffer_info = &rx_ring->buffer_info[i];
+	while (staterr & E1000_RXD_STAT_DD) {
 		ps_page = &rx_ring->ps_page[i];
 		ps_page_dma = &rx_ring->ps_page_dma[i];
 #ifdef CONFIG_E1000_NAPI
-		if(unlikely(*work_done >= work_to_do))
+		if (unlikely(*work_done >= work_to_do))
 			break;
 		(*work_done)++;
 #endif
+		skb = buffer_info->skb;
+
+		if (++i == rx_ring->count) i = 0;
+		next_rxd = E1000_RX_DESC_PS(*rx_ring, i);
+		next_buffer = &rx_ring->buffer_info[i];
+		next_skb = next_buffer->skb;
+
 		cleaned = TRUE;
 		cleaned_count++;
 		pci_unmap_single(pdev, buffer_info->dma,
 				 buffer_info->length,
 				 PCI_DMA_FROMDEVICE);
 
-		skb = buffer_info->skb;
-
-		if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
+		if (unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
 			E1000_DBG("%s: Packet Split buffers didn't pick up"
 				  " the full packet\n", netdev->name);
 			dev_kfree_skb_irq(skb);
 			goto next_desc;
 		}
 
-		if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
+		if (unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
 			dev_kfree_skb_irq(skb);
 			goto next_desc;
 		}
 
 		length = le16_to_cpu(rx_desc->wb.middle.length0);
 
-		if(unlikely(!length)) {
+		if (unlikely(!length)) {
 			E1000_DBG("%s: Last part of the packet spanning"
 				  " multiple descriptors\n", netdev->name);
 			dev_kfree_skb_irq(skb);
@@ -3773,8 +3863,8 @@
 		/* Good Receive */
 		skb_put(skb, length);
 
-		for(j = 0; j < adapter->rx_ps_pages; j++) {
-			if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
+		for (j = 0; j < adapter->rx_ps_pages; j++) {
+			if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
 				break;
 
 			pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
@@ -3794,15 +3884,11 @@
 				  rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
 		skb->protocol = eth_type_trans(skb, netdev);
 
-		if(likely(rx_desc->wb.upper.header_status &
-			  E1000_RXDPS_HDRSTAT_HDRSP)) {
+		if (likely(rx_desc->wb.upper.header_status &
+			  E1000_RXDPS_HDRSTAT_HDRSP))
 			adapter->rx_hdr_split++;
-#ifdef HAVE_RX_ZERO_COPY
-			skb_shinfo(skb)->zero_copy = TRUE;
-#endif
-	        }
 #ifdef CONFIG_E1000_NAPI
-		if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+		if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
 				le16_to_cpu(rx_desc->wb.middle.vlan) &
 				E1000_RXD_SPC_VLAN_MASK);
@@ -3810,7 +3896,7 @@
 			netif_receive_skb(skb);
 		}
 #else /* CONFIG_E1000_NAPI */
-		if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+		if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_rx(skb, adapter->vlgrp,
 				le16_to_cpu(rx_desc->wb.middle.vlan) &
 				E1000_RXD_SPC_VLAN_MASK);
@@ -3834,6 +3920,9 @@
 			cleaned_count = 0;
 		}
 
+		rx_desc = next_rxd;
+		buffer_info = next_buffer;
+
 		staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
 	}
 	rx_ring->next_to_clean = i;
@@ -3875,7 +3964,7 @@
 		}
 
 
-		if(unlikely(!skb)) {
+		if (unlikely(!skb)) {
 			/* Better luck next round */
 			adapter->alloc_rx_buff_failed++;
 			break;
@@ -3940,20 +4029,23 @@
 		rx_desc = E1000_RX_DESC(*rx_ring, i);
 		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
 
-		if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
-			/* Force memory writes to complete before letting h/w
-			 * know there are new descriptors to fetch.  (Only
-			 * applicable for weak-ordered memory model archs,
-			 * such as IA-64). */
-			wmb();
-			writel(i, adapter->hw.hw_addr + rx_ring->rdt);
-		}
-
-		if(unlikely(++i == rx_ring->count)) i = 0;
+		if (unlikely(++i == rx_ring->count))
+			i = 0;
 		buffer_info = &rx_ring->buffer_info[i];
 	}
 
-	rx_ring->next_to_use = i;
+	if (likely(rx_ring->next_to_use != i)) {
+		rx_ring->next_to_use = i;
+		if (unlikely(i-- == 0))
+			i = (rx_ring->count - 1);
+
+		/* Force memory writes to complete before letting h/w
+		 * know there are new descriptors to fetch.  (Only
+		 * applicable for weak-ordered memory model archs,
+		 * such as IA-64). */
+		wmb();
+		writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+	}
 }
 
 /**
@@ -3983,13 +4075,15 @@
 	while (cleaned_count--) {
 		rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
 
-		for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+		for (j = 0; j < PS_PAGE_BUFFERS; j++) {
 			if (j < adapter->rx_ps_pages) {
 				if (likely(!ps_page->ps_page[j])) {
 					ps_page->ps_page[j] =
 						alloc_page(GFP_ATOMIC);
-					if (unlikely(!ps_page->ps_page[j]))
+					if (unlikely(!ps_page->ps_page[j])) {
+						adapter->alloc_rx_buff_failed++;
 						goto no_buffers;
+					}
 					ps_page_dma->ps_page_dma[j] =
 						pci_map_page(pdev,
 							    ps_page->ps_page[j],
@@ -3997,7 +4091,7 @@
 							    PCI_DMA_FROMDEVICE);
 				}
 				/* Refresh the desc even if buffer_addrs didn't
-				 * change because each write-back erases 
+				 * change because each write-back erases
 				 * this info.
 				 */
 				rx_desc->read.buffer_addr[j+1] =
@@ -4008,8 +4102,10 @@
 
 		skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
 
-		if(unlikely(!skb))
+		if (unlikely(!skb)) {
+			adapter->alloc_rx_buff_failed++;
 			break;
+		}
 
 		/* Make buffer alignment 2 beyond a 16 byte boundary
 		 * this will result in a 16 byte aligned IP header after
@@ -4027,27 +4123,28 @@
 
 		rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
 
-		if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
-			/* Force memory writes to complete before letting h/w
-			 * know there are new descriptors to fetch.  (Only
-			 * applicable for weak-ordered memory model archs,
-			 * such as IA-64). */
-			wmb();
-			/* Hardware increments by 16 bytes, but packet split
-			 * descriptors are 32 bytes...so we increment tail
-			 * twice as much.
-			 */
-			writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
-		}
-
-		if(unlikely(++i == rx_ring->count)) i = 0;
+		if (unlikely(++i == rx_ring->count)) i = 0;
 		buffer_info = &rx_ring->buffer_info[i];
 		ps_page = &rx_ring->ps_page[i];
 		ps_page_dma = &rx_ring->ps_page_dma[i];
 	}
 
 no_buffers:
-	rx_ring->next_to_use = i;
+	if (likely(rx_ring->next_to_use != i)) {
+		rx_ring->next_to_use = i;
+		if (unlikely(i-- == 0)) i = (rx_ring->count - 1);
+
+		/* Force memory writes to complete before letting h/w
+		 * know there are new descriptors to fetch.  (Only
+		 * applicable for weak-ordered memory model archs,
+		 * such as IA-64). */
+		wmb();
+		/* Hardware increments by 16 bytes, but packet split
+		 * descriptors are 32 bytes...so we increment tail
+		 * twice as much.
+		 */
+		writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
+	}
 }
 
 /**
@@ -4061,24 +4158,24 @@
 	uint16_t phy_status;
 	uint16_t phy_ctrl;
 
-	if((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
+	if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
 	   !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
 		return;
 
-	if(adapter->smartspeed == 0) {
+	if (adapter->smartspeed == 0) {
 		/* If Master/Slave config fault is asserted twice,
 		 * we assume back-to-back */
 		e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
-		if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
+		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
 		e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
-		if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
+		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
 		e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
-		if(phy_ctrl & CR_1000T_MS_ENABLE) {
+		if (phy_ctrl & CR_1000T_MS_ENABLE) {
 			phy_ctrl &= ~CR_1000T_MS_ENABLE;
 			e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
 					    phy_ctrl);
 			adapter->smartspeed++;
-			if(!e1000_phy_setup_autoneg(&adapter->hw) &&
+			if (!e1000_phy_setup_autoneg(&adapter->hw) &&
 			   !e1000_read_phy_reg(&adapter->hw, PHY_CTRL,
 				   	       &phy_ctrl)) {
 				phy_ctrl |= (MII_CR_AUTO_NEG_EN |
@@ -4088,12 +4185,12 @@
 			}
 		}
 		return;
-	} else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
+	} else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
 		/* If still no link, perhaps using 2/3 pair cable */
 		e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
 		phy_ctrl |= CR_1000T_MS_ENABLE;
 		e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
-		if(!e1000_phy_setup_autoneg(&adapter->hw) &&
+		if (!e1000_phy_setup_autoneg(&adapter->hw) &&
 		   !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
 			phy_ctrl |= (MII_CR_AUTO_NEG_EN |
 				     MII_CR_RESTART_AUTO_NEG);
@@ -4101,7 +4198,7 @@
 		}
 	}
 	/* Restart process after E1000_SMARTSPEED_MAX iterations */
-	if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
+	if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
 		adapter->smartspeed = 0;
 }
 
@@ -4142,7 +4239,7 @@
 	uint16_t spddplx;
 	unsigned long flags;
 
-	if(adapter->hw.media_type != e1000_media_type_copper)
+	if (adapter->hw.media_type != e1000_media_type_copper)
 		return -EOPNOTSUPP;
 
 	switch (cmd) {
@@ -4150,10 +4247,10 @@
 		data->phy_id = adapter->hw.phy_addr;
 		break;
 	case SIOCGMIIREG:
-		if(!capable(CAP_NET_ADMIN))
+		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		spin_lock_irqsave(&adapter->stats_lock, flags);
-		if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+		if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
 				   &data->val_out)) {
 			spin_unlock_irqrestore(&adapter->stats_lock, flags);
 			return -EIO;
@@ -4161,23 +4258,23 @@
 		spin_unlock_irqrestore(&adapter->stats_lock, flags);
 		break;
 	case SIOCSMIIREG:
-		if(!capable(CAP_NET_ADMIN))
+		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		if(data->reg_num & ~(0x1F))
+		if (data->reg_num & ~(0x1F))
 			return -EFAULT;
 		mii_reg = data->val_in;
 		spin_lock_irqsave(&adapter->stats_lock, flags);
-		if(e1000_write_phy_reg(&adapter->hw, data->reg_num,
+		if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
 					mii_reg)) {
 			spin_unlock_irqrestore(&adapter->stats_lock, flags);
 			return -EIO;
 		}
-		if(adapter->hw.phy_type == e1000_phy_m88) {
+		if (adapter->hw.phy_type == e1000_phy_m88) {
 			switch (data->reg_num) {
 			case PHY_CTRL:
-				if(mii_reg & MII_CR_POWER_DOWN)
+				if (mii_reg & MII_CR_POWER_DOWN)
 					break;
-				if(mii_reg & MII_CR_AUTO_NEG_EN) {
+				if (mii_reg & MII_CR_AUTO_NEG_EN) {
 					adapter->hw.autoneg = 1;
 					adapter->hw.autoneg_advertised = 0x2F;
 				} else {
@@ -4192,14 +4289,14 @@
 						   HALF_DUPLEX;
 					retval = e1000_set_spd_dplx(adapter,
 								    spddplx);
-					if(retval) {
+					if (retval) {
 						spin_unlock_irqrestore(
-							&adapter->stats_lock, 
+							&adapter->stats_lock,
 							flags);
 						return retval;
 					}
 				}
-				if(netif_running(adapter->netdev)) {
+				if (netif_running(adapter->netdev)) {
 					e1000_down(adapter);
 					e1000_up(adapter);
 				} else
@@ -4207,7 +4304,7 @@
 				break;
 			case M88E1000_PHY_SPEC_CTRL:
 			case M88E1000_EXT_PHY_SPEC_CTRL:
-				if(e1000_phy_reset(&adapter->hw)) {
+				if (e1000_phy_reset(&adapter->hw)) {
 					spin_unlock_irqrestore(
 						&adapter->stats_lock, flags);
 					return -EIO;
@@ -4217,9 +4314,9 @@
 		} else {
 			switch (data->reg_num) {
 			case PHY_CTRL:
-				if(mii_reg & MII_CR_POWER_DOWN)
+				if (mii_reg & MII_CR_POWER_DOWN)
 					break;
-				if(netif_running(adapter->netdev)) {
+				if (netif_running(adapter->netdev)) {
 					e1000_down(adapter);
 					e1000_up(adapter);
 				} else
@@ -4241,7 +4338,7 @@
 	struct e1000_adapter *adapter = hw->back;
 	int ret_val = pci_set_mwi(adapter->pdev);
 
-	if(ret_val)
+	if (ret_val)
 		DPRINTK(PROBE, ERR, "Error in setting MWI\n");
 }
 
@@ -4290,7 +4387,7 @@
 	e1000_irq_disable(adapter);
 	adapter->vlgrp = grp;
 
-	if(grp) {
+	if (grp) {
 		/* enable VLAN tag insert/strip */
 		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
 		ctrl |= E1000_CTRL_VME;
@@ -4312,7 +4409,7 @@
 		rctl = E1000_READ_REG(&adapter->hw, RCTL);
 		rctl &= ~E1000_RCTL_VFE;
 		E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
-		if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
+		if (adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
 			e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
 			adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
 		}
@@ -4326,9 +4423,10 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	uint32_t vfta, index;
-	if((adapter->hw.mng_cookie.status &
-		E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
-		(vid == adapter->mng_vlan_id))
+
+	if ((adapter->hw.mng_cookie.status &
+	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+	    (vid == adapter->mng_vlan_id))
 		return;
 	/* add VID to filter table */
 	index = (vid >> 5) & 0x7F;
@@ -4345,13 +4443,13 @@
 
 	e1000_irq_disable(adapter);
 
-	if(adapter->vlgrp)
+	if (adapter->vlgrp)
 		adapter->vlgrp->vlan_devices[vid] = NULL;
 
 	e1000_irq_enable(adapter);
 
-	if((adapter->hw.mng_cookie.status &
-		E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+	if ((adapter->hw.mng_cookie.status &
+	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
 	    (vid == adapter->mng_vlan_id)) {
 		/* release control to f/w */
 		e1000_release_hw_control(adapter);
@@ -4370,10 +4468,10 @@
 {
 	e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
 
-	if(adapter->vlgrp) {
+	if (adapter->vlgrp) {
 		uint16_t vid;
-		for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
-			if(!adapter->vlgrp->vlan_devices[vid])
+		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+			if (!adapter->vlgrp->vlan_devices[vid])
 				continue;
 			e1000_vlan_rx_add_vid(adapter->netdev, vid);
 		}
@@ -4386,13 +4484,13 @@
 	adapter->hw.autoneg = 0;
 
 	/* Fiber NICs only allow 1000 gbps Full duplex */
-	if((adapter->hw.media_type == e1000_media_type_fiber) &&
+	if ((adapter->hw.media_type == e1000_media_type_fiber) &&
 		spddplx != (SPEED_1000 + DUPLEX_FULL)) {
 		DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
 		return -EINVAL;
 	}
 
-	switch(spddplx) {
+	switch (spddplx) {
 	case SPEED_10 + DUPLEX_HALF:
 		adapter->hw.forced_speed_duplex = e1000_10_half;
 		break;
@@ -4418,6 +4516,54 @@
 }
 
 #ifdef CONFIG_PM
+/* these functions save and restore 16 or 64 dwords (64-256 bytes) of config
+ * space versus the 64 bytes that pci_[save|restore]_state handle
+ */
+#define PCIE_CONFIG_SPACE_LEN 256
+#define PCI_CONFIG_SPACE_LEN 64
+static int
+e1000_pci_save_state(struct e1000_adapter *adapter)
+{
+	struct pci_dev *dev = adapter->pdev;
+	int size;
+	int i;
+	if (adapter->hw.mac_type >= e1000_82571)
+		size = PCIE_CONFIG_SPACE_LEN;
+	else
+		size = PCI_CONFIG_SPACE_LEN;
+
+	WARN_ON(adapter->config_space != NULL);
+
+	adapter->config_space = kmalloc(size, GFP_KERNEL);
+	if (!adapter->config_space) {
+		DPRINTK(PROBE, ERR, "unable to allocate %d bytes\n", size);
+		return -ENOMEM;
+	}
+	for (i = 0; i < (size / 4); i++)
+		pci_read_config_dword(dev, i * 4, &adapter->config_space[i]);
+	return 0;
+}
+
+static void
+e1000_pci_restore_state(struct e1000_adapter *adapter)
+{
+	struct pci_dev *dev = adapter->pdev;
+	int size;
+	int i;
+	if (adapter->config_space == NULL)
+		return;
+	if (adapter->hw.mac_type >= e1000_82571)
+		size = PCIE_CONFIG_SPACE_LEN;
+	else
+		size = PCI_CONFIG_SPACE_LEN;
+	for (i = 0; i < (size / 4); i++)
+		pci_write_config_dword(dev, i * 4, adapter->config_space[i]);
+	kfree(adapter->config_space);
+	adapter->config_space = NULL;
+	return;
+}
+#endif /* CONFIG_PM */
+
 static int
 e1000_suspend(struct pci_dev *pdev, pm_message_t state)
 {
@@ -4429,25 +4575,33 @@
 
 	netif_device_detach(netdev);
 
-	if(netif_running(netdev))
+	if (netif_running(netdev))
 		e1000_down(adapter);
 
+#ifdef CONFIG_PM
+	/* implement our own version of pci_save_state(pdev) because pci 
+	 * express adapters have larger 256 byte config spaces */
+	retval = e1000_pci_save_state(adapter);
+	if (retval)
+		return retval;
+#endif
+
 	status = E1000_READ_REG(&adapter->hw, STATUS);
-	if(status & E1000_STATUS_LU)
+	if (status & E1000_STATUS_LU)
 		wufc &= ~E1000_WUFC_LNKC;
 
-	if(wufc) {
+	if (wufc) {
 		e1000_setup_rctl(adapter);
 		e1000_set_multi(netdev);
 
 		/* turn on all-multi mode if wake on multicast is enabled */
-		if(adapter->wol & E1000_WUFC_MC) {
+		if (adapter->wol & E1000_WUFC_MC) {
 			rctl = E1000_READ_REG(&adapter->hw, RCTL);
 			rctl |= E1000_RCTL_MPE;
 			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 		}
 
-		if(adapter->hw.mac_type >= e1000_82540) {
+		if (adapter->hw.mac_type >= e1000_82540) {
 			ctrl = E1000_READ_REG(&adapter->hw, CTRL);
 			/* advertise wake from D3Cold */
 			#define E1000_CTRL_ADVD3WUC 0x00100000
@@ -4458,7 +4612,7 @@
 			E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
 		}
 
-		if(adapter->hw.media_type == e1000_media_type_fiber ||
+		if (adapter->hw.media_type == e1000_media_type_fiber ||
 		   adapter->hw.media_type == e1000_media_type_internal_serdes) {
 			/* keep the laser running in D3 */
 			ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
@@ -4488,12 +4642,10 @@
 			DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
 	}
 
-	pci_save_state(pdev);
-
-	if(adapter->hw.mac_type >= e1000_82540 &&
+	if (adapter->hw.mac_type >= e1000_82540 &&
 	   adapter->hw.media_type == e1000_media_type_copper) {
 		manc = E1000_READ_REG(&adapter->hw, MANC);
-		if(manc & E1000_MANC_SMBUS_EN) {
+		if (manc & E1000_MANC_SMBUS_EN) {
 			manc |= E1000_MANC_ARP_EN;
 			E1000_WRITE_REG(&adapter->hw, MANC, manc);
 			retval = pci_enable_wake(pdev, PCI_D3hot, 1);
@@ -4518,6 +4670,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
 static int
 e1000_resume(struct pci_dev *pdev)
 {
@@ -4529,6 +4682,7 @@
 	retval = pci_set_power_state(pdev, PCI_D0);
 	if (retval)
 		DPRINTK(PROBE, ERR, "Error in setting power state\n");
+	e1000_pci_restore_state(adapter);
 	ret_val = pci_enable_device(pdev);
 	pci_set_master(pdev);
 
@@ -4542,12 +4696,12 @@
 	e1000_reset(adapter);
 	E1000_WRITE_REG(&adapter->hw, WUS, ~0);
 
-	if(netif_running(netdev))
+	if (netif_running(netdev))
 		e1000_up(adapter);
 
 	netif_device_attach(netdev);
 
-	if(adapter->hw.mac_type >= e1000_82540 &&
+	if (adapter->hw.mac_type >= e1000_82540 &&
 	   adapter->hw.media_type == e1000_media_type_copper) {
 		manc = E1000_READ_REG(&adapter->hw, MANC);
 		manc &= ~(E1000_MANC_ARP_EN);
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index aac64de..9790db9 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -47,7 +47,7 @@
 	                	BUG(); \
 			} else { \
 				msleep(x); \
-			} } while(0)
+			} } while (0)
 
 /* Some workarounds require millisecond delays and are run during interrupt
  * context.  Most notably, when establishing link, the phy may need tweaking
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 0a7918c..3768d83 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -227,7 +227,7 @@
 e1000_validate_option(int *value, struct e1000_option *opt,
 		struct e1000_adapter *adapter)
 {
-	if(*value == OPTION_UNSET) {
+	if (*value == OPTION_UNSET) {
 		*value = opt->def;
 		return 0;
 	}
@@ -244,7 +244,7 @@
 		}
 		break;
 	case range_option:
-		if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
 			DPRINTK(PROBE, INFO,
 					"%s set to %i\n", opt->name, *value);
 			return 0;
@@ -254,10 +254,10 @@
 		int i;
 		struct e1000_opt_list *ent;
 
-		for(i = 0; i < opt->arg.l.nr; i++) {
+		for (i = 0; i < opt->arg.l.nr; i++) {
 			ent = &opt->arg.l.p[i];
-			if(*value == ent->i) {
-				if(ent->str[0] != '\0')
+			if (*value == ent->i) {
+				if (ent->str[0] != '\0')
 					DPRINTK(PROBE, INFO, "%s\n", ent->str);
 				return 0;
 			}
@@ -291,7 +291,7 @@
 e1000_check_options(struct e1000_adapter *adapter)
 {
 	int bd = adapter->bd_number;
-	if(bd >= E1000_MAX_NIC) {
+	if (bd >= E1000_MAX_NIC) {
 		DPRINTK(PROBE, NOTICE,
 		       "Warning: no configuration for board #%i\n", bd);
 		DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
@@ -315,7 +315,7 @@
 		if (num_TxDescriptors > bd) {
 			tx_ring->count = TxDescriptors[bd];
 			e1000_validate_option(&tx_ring->count, &opt, adapter);
-			E1000_ROUNDUP(tx_ring->count, 
+			E1000_ROUNDUP(tx_ring->count,
 						REQ_TX_DESCRIPTOR_MULTIPLE);
 		} else {
 			tx_ring->count = opt.def;
@@ -341,7 +341,7 @@
 		if (num_RxDescriptors > bd) {
 			rx_ring->count = RxDescriptors[bd];
 			e1000_validate_option(&rx_ring->count, &opt, adapter);
-			E1000_ROUNDUP(rx_ring->count, 
+			E1000_ROUNDUP(rx_ring->count,
 						REQ_RX_DESCRIPTOR_MULTIPLE);
 		} else {
 			rx_ring->count = opt.def;
@@ -403,7 +403,7 @@
 
 		if (num_TxIntDelay > bd) {
 			adapter->tx_int_delay = TxIntDelay[bd];
-			e1000_validate_option(&adapter->tx_int_delay, &opt, 
+			e1000_validate_option(&adapter->tx_int_delay, &opt,
 								adapter);
 		} else {
 			adapter->tx_int_delay = opt.def;
@@ -421,7 +421,7 @@
 
 		if (num_TxAbsIntDelay > bd) {
 			adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
-			e1000_validate_option(&adapter->tx_abs_int_delay, &opt, 
+			e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
 								adapter);
 		} else {
 			adapter->tx_abs_int_delay = opt.def;
@@ -439,7 +439,7 @@
 
 		if (num_RxIntDelay > bd) {
 			adapter->rx_int_delay = RxIntDelay[bd];
-			e1000_validate_option(&adapter->rx_int_delay, &opt, 
+			e1000_validate_option(&adapter->rx_int_delay, &opt,
 								adapter);
 		} else {
 			adapter->rx_int_delay = opt.def;
@@ -457,7 +457,7 @@
 
 		if (num_RxAbsIntDelay > bd) {
 			adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
-			e1000_validate_option(&adapter->rx_abs_int_delay, &opt, 
+			e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
 								adapter);
 		} else {
 			adapter->rx_abs_int_delay = opt.def;
@@ -475,17 +475,17 @@
 
 		if (num_InterruptThrottleRate > bd) {
 			adapter->itr = InterruptThrottleRate[bd];
-			switch(adapter->itr) {
+			switch (adapter->itr) {
 			case 0:
-				DPRINTK(PROBE, INFO, "%s turned off\n", 
+				DPRINTK(PROBE, INFO, "%s turned off\n",
 					opt.name);
 				break;
 			case 1:
-				DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", 
+				DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
 					opt.name);
 				break;
 			default:
-				e1000_validate_option(&adapter->itr, &opt, 
+				e1000_validate_option(&adapter->itr, &opt,
 					adapter);
 				break;
 			}
@@ -494,7 +494,7 @@
 		}
 	}
 
-	switch(adapter->hw.media_type) {
+	switch (adapter->hw.media_type) {
 	case e1000_media_type_fiber:
 	case e1000_media_type_internal_serdes:
 		e1000_check_fiber_options(adapter);
@@ -518,17 +518,17 @@
 e1000_check_fiber_options(struct e1000_adapter *adapter)
 {
 	int bd = adapter->bd_number;
-	if(num_Speed > bd) {
+	if (num_Speed > bd) {
 		DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
 
-	if(num_Duplex > bd) {
+	if (num_Duplex > bd) {
 		DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
 
-	if((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
+	if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
 		DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
 				 "not valid for fiber adapters, "
 				 "parameter ignored\n");
@@ -598,7 +598,7 @@
 		}
 	}
 
-	if((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
+	if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
 		DPRINTK(PROBE, INFO,
 		       "AutoNeg specified along with Speed or Duplex, "
 		       "parameter ignored\n");
@@ -659,7 +659,7 @@
 	switch (speed + dplx) {
 	case 0:
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		if((num_Speed > bd) && (speed != 0 || dplx != 0))
+		if ((num_Speed > bd) && (speed != 0 || dplx != 0))
 			DPRINTK(PROBE, INFO,
 			       "Speed and duplex autonegotiation enabled\n");
 		break;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0c18dbd..0e8e3fc 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -199,8 +199,7 @@
 
 	/* get a pointer to the register memory */
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	priv->regs = (struct gfar *)
-		ioremap(r->start, sizeof (struct gfar));
+	priv->regs = ioremap(r->start, sizeof (struct gfar));
 
 	if (NULL == priv->regs) {
 		err = -ENOMEM;
@@ -369,7 +368,7 @@
 	return 0;
 
 register_fail:
-	iounmap((void *) priv->regs);
+	iounmap(priv->regs);
 regs_fail:
 	free_netdev(dev);
 	return err;
@@ -382,7 +381,7 @@
 
 	platform_set_drvdata(pdev, NULL);
 
-	iounmap((void *) priv->regs);
+	iounmap(priv->regs);
 	free_netdev(dev);
 
 	return 0;
@@ -454,8 +453,7 @@
 
 	/* Zero out the rmon mib registers if it has them */
 	if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
-		memset((void *) &(priv->regs->rmon), 0,
-		       sizeof (struct rmon_mib));
+		memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib));
 
 		/* Mask off the CAM interrupts */
 		gfar_write(&priv->regs->rmon.cam1, 0xffffffff);
@@ -477,7 +475,7 @@
 void gfar_halt(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar *regs = priv->regs;
+	struct gfar __iomem *regs = priv->regs;
 	u32 tempval;
 
 	/* Mask all interrupts */
@@ -507,7 +505,7 @@
 void stop_gfar(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar *regs = priv->regs;
+	struct gfar __iomem *regs = priv->regs;
 	unsigned long flags;
 
 	phy_stop(priv->phydev);
@@ -590,7 +588,7 @@
 void gfar_start(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar *regs = priv->regs;
+	struct gfar __iomem *regs = priv->regs;
 	u32 tempval;
 
 	/* Enable Rx and Tx in MACCFG1 */
@@ -624,7 +622,7 @@
 	unsigned long vaddr;
 	int i;
 	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar *regs = priv->regs;
+	struct gfar __iomem *regs = priv->regs;
 	int err = 0;
 	u32 rctrl = 0;
 	u32 attrs = 0;
@@ -1622,7 +1620,7 @@
 static void adjust_link(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar *regs = priv->regs;
+	struct gfar __iomem *regs = priv->regs;
 	unsigned long flags;
 	struct phy_device *phydev = priv->phydev;
 	int new_state = 0;
@@ -1703,7 +1701,7 @@
 {
 	struct dev_mc_list *mc_ptr;
 	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar *regs = priv->regs;
+	struct gfar __iomem *regs = priv->regs;
 	u32 tempval;
 
 	if(dev->flags & IFF_PROMISC) {
@@ -1842,7 +1840,7 @@
 	int idx;
 	char tmpbuf[MAC_ADDR_LEN];
 	u32 tempval;
-	u32 *macptr = &priv->regs->macstnaddr1;
+	u32 __iomem *macptr = &priv->regs->macstnaddr1;
 
 	macptr += num*2;
 
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index cb9d66a..d37d540 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -682,8 +682,8 @@
 	struct rxbd8 *cur_rx;           /* Next free rx ring entry */
 	struct txbd8 *cur_tx;	        /* Next free ring entry */
 	struct txbd8 *dirty_tx;		/* The Ring entry to be freed. */
-	struct gfar *regs;	/* Pointer to the GFAR memory mapped Registers */
-	u32 *hash_regs[16];
+	struct gfar __iomem *regs;	/* Pointer to the GFAR memory mapped Registers */
+	u32 __iomem *hash_regs[16];
 	int hash_width;
 	struct net_device_stats stats; /* linux network statistics */
 	struct gfar_extra_stats extra_stats;
@@ -718,14 +718,14 @@
 	uint32_t msg_enable;
 };
 
-static inline u32 gfar_read(volatile unsigned *addr)
+static inline u32 gfar_read(volatile unsigned __iomem *addr)
 {
 	u32 val;
 	val = in_be32(addr);
 	return val;
 }
 
-static inline void gfar_write(volatile unsigned *addr, u32 val)
+static inline void gfar_write(volatile unsigned __iomem *addr, u32 val)
 {
 	out_be32(addr, val);
 }
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 765e810..5de7b2e 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -144,11 +144,11 @@
 	u64 *extra = (u64 *) & priv->extra_stats;
 
 	if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
-		u32 *rmon = (u32 *) & priv->regs->rmon;
+		u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon;
 		struct gfar_stats *stats = (struct gfar_stats *) buf;
 
 		for (i = 0; i < GFAR_RMON_LEN; i++)
-			stats->rmon[i] = (u64) (rmon[i]);
+			stats->rmon[i] = (u64) gfar_read(&rmon[i]);
 
 		for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
 			stats->extra[i] = extra[i];
@@ -221,11 +221,11 @@
 {
 	int i;
 	struct gfar_private *priv = netdev_priv(dev);
-	u32 *theregs = (u32 *) priv->regs;
+	u32 __iomem *theregs = (u32 __iomem *) priv->regs;
 	u32 *buf = (u32 *) regbuf;
 
 	for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++)
-		buf[i] = theregs[i];
+		buf[i] = gfar_read(&theregs[i]);
 }
 
 /* Convert microseconds to ethernet clock ticks, which changes
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 74e52fc..c6b7255 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -50,7 +50,7 @@
  * All PHY configuration is done through the TSEC1 MIIM regs */
 int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
 {
-	struct gfar_mii *regs = bus->priv;
+	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
 
 	/* Set the PHY address and the register address we want to write */
 	gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
@@ -70,7 +70,7 @@
  * configuration has to be done through the TSEC1 MIIM regs */
 int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 {
-	struct gfar_mii *regs = bus->priv;
+	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
 	u16 value;
 
 	/* Set the PHY address and the register address we want to read */
@@ -94,7 +94,7 @@
 /* Reset the MIIM registers, and wait for the bus to free */
 int gfar_mdio_reset(struct mii_bus *bus)
 {
-	struct gfar_mii *regs = bus->priv;
+	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
 	unsigned int timeout = PHY_INIT_TIMEOUT;
 
 	spin_lock_bh(&bus->mdio_lock);
@@ -126,7 +126,7 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct gianfar_mdio_data *pdata;
-	struct gfar_mii *regs;
+	struct gfar_mii __iomem *regs;
 	struct mii_bus *new_bus;
 	struct resource *r;
 	int err = 0;
@@ -155,15 +155,14 @@
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	/* Set the PHY base address */
-	regs = (struct gfar_mii *) ioremap(r->start,
-			sizeof (struct gfar_mii));
+	regs = ioremap(r->start, sizeof (struct gfar_mii));
 
 	if (NULL == regs) {
 		err = -ENOMEM;
 		goto reg_map_fail;
 	}
 
-	new_bus->priv = regs;
+	new_bus->priv = (void __force *)regs;
 
 	new_bus->irq = pdata->irq;
 
@@ -181,7 +180,7 @@
 	return 0;
 
 bus_register_fail:
-	iounmap((void *) regs);
+	iounmap(regs);
 reg_map_fail:
 	kfree(new_bus);
 
@@ -197,7 +196,7 @@
 
 	dev_set_drvdata(dev, NULL);
 
-	iounmap((void *) (&bus->priv));
+	iounmap((void __iomem *)bus->priv);
 	bus->priv = NULL;
 	kfree(bus);
 
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index 3b1bef1..77411a0 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -86,7 +86,6 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/bug.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index 6139f06..94d5ea1 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -56,8 +56,6 @@
 All other communication is through memory!
 */
 
-#define SLOW_DOWN_IO udelay(5)
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 40ae36b..c0998ef 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -32,6 +32,8 @@
  */
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
+#include <linux/in.h>
+#include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/etherdevice.h>
@@ -444,6 +446,7 @@
 			netif_rx(skb);
 #endif
 		}
+		dev->last_rx = jiffies;
 	}
 
 	return received_packets;
@@ -461,7 +464,7 @@
  */
 
 static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
-							struct pt_regs *regs)
+						struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct mv643xx_private *mp = netdev_priv(dev);
@@ -1047,16 +1050,15 @@
 
 static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
 {
-        unsigned int frag;
-        skb_frag_t *fragp;
+	unsigned int frag;
+	skb_frag_t *fragp;
 
-        for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
-                fragp = &skb_shinfo(skb)->frags[frag];
-                if (fragp->size <= 8 && fragp->page_offset & 0x7)
-                        return 1;
-
-        }
-        return 0;
+	for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+		fragp = &skb_shinfo(skb)->frags[frag];
+		if (fragp->size <= 8 && fragp->page_offset & 0x7)
+			return 1;
+	}
+	return 0;
 }
 
 
@@ -2137,26 +2139,26 @@
 	 */
 	if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) {
 		for (table_index = 0; table_index <= 0xFC; table_index += 4) {
-			 /* Set all entries in DA filter special multicast
-			  * table (Ex_dFSMT)
-			  * Set for ETH_Q0 for now
-			  * Bits
-			  * 0	  Accept=1, Drop=0
-			  * 3-1  Queue	 ETH_Q0=0
-			  * 7-4  Reserved = 0;
-			  */
-			 mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+			/* Set all entries in DA filter special multicast
+			 * table (Ex_dFSMT)
+			 * Set for ETH_Q0 for now
+			 * Bits
+			 * 0	  Accept=1, Drop=0
+			 * 3-1  Queue	 ETH_Q0=0
+			 * 7-4  Reserved = 0;
+			 */
+			mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
 
-			 /* Set all entries in DA filter other multicast
-			  * table (Ex_dFOMT)
-			  * Set for ETH_Q0 for now
-			  * Bits
-			  * 0	  Accept=1, Drop=0
-			  * 3-1  Queue	 ETH_Q0=0
-			  * 7-4  Reserved = 0;
-			  */
-			 mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
-       	}
+			/* Set all entries in DA filter other multicast
+			 * table (Ex_dFOMT)
+			 * Set for ETH_Q0 for now
+			 * Bits
+			 * 0	  Accept=1, Drop=0
+			 * 3-1  Queue	 ETH_Q0=0
+			 * 7-4  Reserved = 0;
+			 */
+			mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+		}
 		return;
 	}
 
@@ -2617,7 +2619,6 @@
 	struct eth_tx_desc *current_descriptor;
 	struct eth_tx_desc *first_descriptor;
 	u32 command;
-	unsigned long flags;
 
 	/* Do not process Tx ring in case of Tx ring resource error */
 	if (mp->tx_resource_err)
@@ -2634,8 +2635,6 @@
 		return ETH_ERROR;
 	}
 
-	spin_lock_irqsave(&mp->lock, flags);
-
 	mp->tx_ring_skbs++;
 	BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
 
@@ -2685,15 +2684,11 @@
 		mp->tx_resource_err = 1;
 		mp->tx_curr_desc_q = tx_first_desc;
 
-		spin_unlock_irqrestore(&mp->lock, flags);
-
 		return ETH_QUEUE_LAST_RESOURCE;
 	}
 
 	mp->tx_curr_desc_q = tx_next_desc;
 
-	spin_unlock_irqrestore(&mp->lock, flags);
-
 	return ETH_OK;
 }
 #else
@@ -2704,14 +2699,11 @@
 	int tx_desc_used;
 	struct eth_tx_desc *current_descriptor;
 	unsigned int command_status;
-	unsigned long flags;
 
 	/* Do not process Tx ring in case of Tx ring resource error */
 	if (mp->tx_resource_err)
 		return ETH_QUEUE_FULL;
 
-	spin_lock_irqsave(&mp->lock, flags);
-
 	mp->tx_ring_skbs++;
 	BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
 
@@ -2742,12 +2734,9 @@
 	/* Check for ring index overlap in the Tx desc ring */
 	if (tx_desc_curr == tx_desc_used) {
 		mp->tx_resource_err = 1;
-
-		spin_unlock_irqrestore(&mp->lock, flags);
 		return ETH_QUEUE_LAST_RESOURCE;
 	}
 
-	spin_unlock_irqrestore(&mp->lock, flags);
 	return ETH_OK;
 }
 #endif
@@ -2898,8 +2887,10 @@
 	p_pkt_info->return_info = mp->rx_skb[rx_curr_desc];
 	p_pkt_info->l4i_chk = p_rx_desc->buf_size;
 
-	/* Clean the return info field to indicate that the packet has been */
-	/* moved to the upper layers					    */
+	/*
+	 * Clean the return info field to indicate that the
+	 * packet has been moved to the upper layers
+	 */
 	mp->rx_skb[rx_curr_desc] = NULL;
 
 	/* Update current index in data structure */
@@ -2980,7 +2971,7 @@
 };
 
 #define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \
-		      offsetof(struct mv643xx_private, m)
+					offsetof(struct mv643xx_private, m)
 
 static const struct mv643xx_stats mv643xx_gstrings_stats[] = {
 	{ "rx_packets", MV643XX_STAT(stats.rx_packets) },
@@ -3131,9 +3122,8 @@
 	return 0;
 }
 
-static void
-mv643xx_get_drvinfo(struct net_device *netdev,
-                       struct ethtool_drvinfo *drvinfo)
+static void mv643xx_get_drvinfo(struct net_device *netdev,
+				struct ethtool_drvinfo *drvinfo)
 {
 	strncpy(drvinfo->driver,  mv643xx_driver_name, 32);
 	strncpy(drvinfo->version, mv643xx_driver_version, 32);
@@ -3142,39 +3132,37 @@
 	drvinfo->n_stats = MV643XX_STATS_LEN;
 }
 
-static int 
-mv643xx_get_stats_count(struct net_device *netdev)
+static int mv643xx_get_stats_count(struct net_device *netdev)
 {
 	return MV643XX_STATS_LEN;
 }
 
-static void 
-mv643xx_get_ethtool_stats(struct net_device *netdev, 
-		struct ethtool_stats *stats, uint64_t *data)
+static void mv643xx_get_ethtool_stats(struct net_device *netdev,
+				struct ethtool_stats *stats, uint64_t *data)
 {
 	struct mv643xx_private *mp = netdev->priv;
 	int i;
 
 	eth_update_mib_counters(mp);
 
-	for(i = 0; i < MV643XX_STATS_LEN; i++) {
+	for (i = 0; i < MV643XX_STATS_LEN; i++) {
 		char *p = (char *)mp+mv643xx_gstrings_stats[i].stat_offset;	
-		data[i] = (mv643xx_gstrings_stats[i].sizeof_stat == 
+		data[i] = (mv643xx_gstrings_stats[i].sizeof_stat ==
 			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
 	}
 }
 
-static void 
-mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
+static void mv643xx_get_strings(struct net_device *netdev, uint32_t stringset,
+				uint8_t *data)
 {
 	int i;
 
 	switch(stringset) {
 	case ETH_SS_STATS:
 		for (i=0; i < MV643XX_STATS_LEN; i++) {
-			memcpy(data + i * ETH_GSTRING_LEN, 
-			mv643xx_gstrings_stats[i].stat_string,
-			ETH_GSTRING_LEN);
+			memcpy(data + i * ETH_GSTRING_LEN,
+					mv643xx_gstrings_stats[i].stat_string,
+					ETH_GSTRING_LEN);
 		}
 		break;
 	}
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 1c6d328..0245e40 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1610,6 +1610,8 @@
 		}
 		else if (!pskb_may_pull(skb, skb->len))
 			goto err;
+		else
+			skb->ip_summed = CHECKSUM_NONE;
 
 		len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2);
 		if (len <= 0) {
@@ -1690,6 +1692,7 @@
 			kfree_skb(skb);
 		} else {
 			skb_pull(skb, 2);	/* chop off protocol */
+			skb_postpull_rcsum(skb, skb->data - 2, 2);
 			skb->dev = ppp->dev;
 			skb->protocol = htons(npindex_to_ethertype[npi]);
 			skb->mac.raw = skb->data;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 2e1bed15..6e10184 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -484,13 +484,12 @@
 	int i;
 
 	RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
-	udelay(1000);
 
-	for (i = 2000; i > 0; i--) {
+	for (i = 20; i > 0; i--) {
 		/* Check if the RTL8169 has completed writing to the specified MII register */
 		if (!(RTL_R32(PHYAR) & 0x80000000)) 
 			break;
-		udelay(100);
+		udelay(25);
 	}
 }
 
@@ -499,15 +498,14 @@
 	int i, value = -1;
 
 	RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
-	udelay(1000);
 
-	for (i = 2000; i > 0; i--) {
+	for (i = 20; i > 0; i--) {
 		/* Check if the RTL8169 has completed retrieving data from the specified MII register */
 		if (RTL_R32(PHYAR) & 0x80000000) {
 			value = (int) (RTL_R32(PHYAR) & 0xFFFF);
 			break;
 		}
-		udelay(100);
+		udelay(25);
 	}
 	return value;
 }
@@ -677,6 +675,9 @@
 
 		if (duplex == DUPLEX_HALF)
 			auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);
+
+		if (duplex == DUPLEX_FULL)
+			auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half);
 	}
 
 	tp->phy_auto_nego_reg = auto_nego;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 89c4678..49b597c 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -3586,7 +3586,7 @@
 		txdp->Buffer_Pointer = (u64) pci_map_page
 		    (sp->pdev, frag->page, frag->page_offset,
 		     frag->size, PCI_DMA_TODEVICE);
-		txdp->Control_1 |= TXD_BUFFER0_SIZE(frag->size);
+		txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
 		if (skb_shinfo(skb)->ufo_size)
 			txdp->Control_1 |= TXD_UFO_EN;
 	}
diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h
index 4233ea5..5032394 100644
--- a/drivers/net/sis900.h
+++ b/drivers/net/sis900.h
@@ -33,7 +33,6 @@
         rxcfg=0x34,             //Receive Configuration Register
         flctrl=0x38,            //Flow Control Register
         rxlen=0x3c,             //Receive Packet Length Register
-        cfgpmcsr=0x44,          //Configuration Power Management Control/Status Register
         rfcr=0x48,              //Receive Filter Control Register
         rfdr=0x4C,              //Receive Filter Data Register
         pmctrl=0xB0,            //Power Management Control Register
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index f8b973a..cae2edf 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -23,12 +23,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/*
- * TOTEST
- *	- speed setting
- *	- suspend/resume
- */
-
 #include <linux/config.h>
 #include <linux/crc32.h>
 #include <linux/kernel.h>
@@ -57,7 +51,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"0.13"
+#define DRV_VERSION		"0.15"
 #define PFX			DRV_NAME " "
 
 /*
@@ -102,6 +96,10 @@
 module_param(copybreak, int, 0);
 MODULE_PARM_DESC(copybreak, "Receive copy threshold");
 
+static int disable_msi = 0;
+module_param(disable_msi, int, 0);
+MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
+
 static const struct pci_device_id sky2_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
@@ -198,7 +196,7 @@
 	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 
 	pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control);
-	vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
+	vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
 		(power_control & PCI_PM_CAP_PME_D3cold);
 
 	pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control);
@@ -1834,6 +1832,8 @@
 	u16 hwidx;
 	u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS };
 
+	sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
 	hwidx = sky2_read16(hw, STAT_PUT_IDX);
 	BUG_ON(hwidx >= STATUS_RING_SIZE);
 	rmb();
@@ -1913,12 +1913,10 @@
 	}
 
 exit_loop:
-	sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-
 	sky2_tx_check(hw, 0, tx_done[0]);
 	sky2_tx_check(hw, 1, tx_done[1]);
 
-	if (sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx) {
+	if (likely(work_done < to_do)) {
 		/* need to restart TX timer */
 		if (is_ec_a1(hw)) {
 			sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
@@ -2141,14 +2139,12 @@
 
 static int sky2_reset(struct sky2_hw *hw)
 {
-	u32 ctst;
 	u16 status;
 	u8 t8, pmd_type;
-	int i;
-
-	ctst = sky2_read32(hw, B0_CTST);
+	int i, err;
 
 	sky2_write8(hw, B0_CTST, CS_RST_CLR);
+
 	hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
 	if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
 		printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n",
@@ -2156,12 +2152,6 @@
 		return -EOPNOTSUPP;
 	}
 
-	/* ring for status responses */
-	hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
-					 &hw->st_dma);
-	if (!hw->st_le)
-		return -ENOMEM;
-
 	/* disable ASF */
 	if (hw->chip_id <= CHIP_ID_YUKON_EC) {
 		sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
@@ -2173,19 +2163,24 @@
 	sky2_write8(hw, B0_CTST, CS_RST_CLR);
 
 	/* clear PCI errors, if any */
-	pci_read_config_word(hw->pdev, PCI_STATUS, &status);
+	err = pci_read_config_word(hw->pdev, PCI_STATUS, &status);
+	if (err)
+		goto pci_err;
+
 	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-	pci_write_config_word(hw->pdev, PCI_STATUS,
-			      status | PCI_STATUS_ERROR_BITS);
+	err = pci_write_config_word(hw->pdev, PCI_STATUS,
+				    status | PCI_STATUS_ERROR_BITS);
+	if (err)
+		goto pci_err;
 
 	sky2_write8(hw, B0_CTST, CS_MRST_CLR);
 
 	/* clear any PEX errors */
-	if (is_pciex(hw)) {
-		u16 lstat;
-		pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
-				       0xffffffffUL);
-		pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat);
+	if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) {
+		err = pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
+						 0xffffffffUL);
+		if (err)
+			goto pci_err;
 	}
 
 	pmd_type = sky2_read8(hw, B2_PMD_TYP);
@@ -2297,6 +2292,14 @@
 	sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
 
 	return 0;
+
+pci_err:
+	/* This is to catch a BIOS bug workaround where
+	 * mmconfig table doesn't have other buses.
+	 */
+	printk(KERN_ERR PFX "%s: can't access PCI config space\n",
+	       pci_name(hw->pdev));
+	return err;
 }
 
 static u32 sky2_supported_modes(const struct sky2_hw *hw)
@@ -2551,19 +2554,24 @@
 static int sky2_set_mac_address(struct net_device *dev, void *p)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
-	struct sockaddr *addr = p;
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	const struct sockaddr *addr = p;
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
 	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
-	memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8,
+	memcpy_toio(hw->regs + B2_MAC_1 + port * 8,
 		    dev->dev_addr, ETH_ALEN);
-	memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8,
+	memcpy_toio(hw->regs + B2_MAC_2 + port * 8,
 		    dev->dev_addr, ETH_ALEN);
 
-	if (netif_running(dev))
-		sky2_phy_reinit(sky2);
+	/* virtual address for data */
+	gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
+
+	/* physical address: used for pause frames */
+	gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
 
 	return 0;
 }
@@ -2843,7 +2851,7 @@
 	if (ecmd->rx_coalesce_usecs_irq == 0)
 		sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP);
 	else {
-		sky2_write32(hw, STAT_TX_TIMER_INI,
+		sky2_write32(hw, STAT_ISR_TIMER_INI,
 			     sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq));
 		sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
 	}
@@ -3055,6 +3063,61 @@
 		       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 }
 
+/* Handle software interrupt used during MSI test */
+static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id,
+					    struct pt_regs *regs)
+{
+	struct sky2_hw *hw = dev_id;
+	u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
+
+	if (status == 0)
+		return IRQ_NONE;
+
+	if (status & Y2_IS_IRQ_SW) {
+		sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
+		hw->msi = 1;
+	}
+	sky2_write32(hw, B0_Y2_SP_ICR, 2);
+
+	sky2_read32(hw, B0_IMSK);
+	return IRQ_HANDLED;
+}
+
+/* Test interrupt path by forcing a a software IRQ */
+static int __devinit sky2_test_msi(struct sky2_hw *hw)
+{
+	struct pci_dev *pdev = hw->pdev;
+	int i, err;
+
+	sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
+
+	err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw);
+	if (err) {
+		printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
+		       pci_name(pdev), pdev->irq);
+		return err;
+	}
+
+	sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
+	wmb();
+
+	for (i = 0; i < 10; i++) {
+		barrier();
+		if (hw->msi)
+			goto found;
+		mdelay(1);
+	}
+
+	err = -EOPNOTSUPP;
+	sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
+ found:
+	sky2_write32(hw, B0_IMSK, 0);
+
+	free_irq(pdev->irq, hw);
+
+	return err;
+}
+
 static int __devinit sky2_probe(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
@@ -3135,6 +3198,12 @@
 	}
 	hw->pm_cap = pm_cap;
 
+	/* ring for status responses */
+	hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
+					 &hw->st_dma);
+	if (!hw->st_le)
+		goto err_out_iounmap;
+
 	err = sky2_reset(hw);
 	if (err)
 		goto err_out_iounmap;
@@ -3169,7 +3238,22 @@
 		}
 	}
 
-	err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw);
+	if (!disable_msi && pci_enable_msi(pdev) == 0) {
+		err = sky2_test_msi(hw);
+		if (err == -EOPNOTSUPP) {
+			/* MSI test failed, go back to INTx mode */
+			printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, "
+			       "switching to INTx mode. Please report this failure to "
+			       "the PCI maintainer and include system chipset information.\n",
+			       pci_name(pdev));
+			pci_disable_msi(pdev);
+		}
+		else if (err)
+			goto err_out_unregister;
+	}
+
+	err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
+			  DRV_NAME, hw);
 	if (err) {
 		printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
 		       pci_name(pdev), pdev->irq);
@@ -3184,6 +3268,8 @@
 	return 0;
 
 err_out_unregister:
+	if (hw->msi)
+		pci_disable_msi(pdev);
 	if (dev1) {
 		unregister_netdev(dev1);
 		free_netdev(dev1);
@@ -3226,6 +3312,8 @@
 	sky2_read8(hw, B0_CTST);
 
 	free_irq(pdev->irq, hw);
+	if (hw->msi)
+		pci_disable_msi(pdev);
 	pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
@@ -3263,25 +3351,33 @@
 static int sky2_resume(struct pci_dev *pdev)
 {
 	struct sky2_hw *hw = pci_get_drvdata(pdev);
-	int i;
+	int i, err;
 
 	pci_restore_state(pdev);
 	pci_enable_wake(pdev, PCI_D0, 0);
-	sky2_set_power_state(hw, PCI_D0);
+	err = sky2_set_power_state(hw, PCI_D0);
+	if (err)
+		goto out;
 
-	sky2_reset(hw);
+	err = sky2_reset(hw);
+	if (err)
+		goto out;
 
 	for (i = 0; i < 2; i++) {
 		struct net_device *dev = hw->dev[i];
-		if (dev) {
-			if (netif_running(dev)) {
-				netif_device_attach(dev);
-				if (sky2_up(dev))
-					dev_close(dev);
+		if (dev && netif_running(dev)) {
+			netif_device_attach(dev);
+			err = sky2_up(dev);
+			if (err) {
+				printk(KERN_ERR PFX "%s: could not up: %d\n",
+				       dev->name, err);
+				dev_close(dev);
+				break;
 			}
 		}
 	}
-	return 0;
+out:
+	return err;
 }
 #endif
 
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 9551892..fd12c28 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1841,6 +1841,7 @@
 	struct net_device    *dev[2];
 
 	int		     pm_cap;
+	int		     msi;
 	u8	     	     chip_id;
 	u8		     chip_rev;
 	u8		     copper;
@@ -1867,14 +1868,6 @@
 	return readb(hw->regs + reg);
 }
 
-/* This should probably go away, bus based tweeks suck */
-static inline int is_pciex(const struct sky2_hw *hw)
-{
-	u32 status;
-	pci_read_config_dword(hw->pdev, PCI_DEV_STATUS, &status);
-	return (status & PCI_OS_PCI_X) == 0;
-}
-
 static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val)
 {
 	writel(val, hw->regs + reg);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index f2d1daf..e7dc653 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.48"
-#define DRV_MODULE_RELDATE	"Jan 16, 2006"
+#define DRV_MODULE_VERSION	"3.49"
+#define DRV_MODULE_RELDATE	"Feb 2, 2006"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -3482,6 +3482,17 @@
 	struct tg3 *tp = _data;
 	unsigned int restart_timer;
 
+	tg3_full_lock(tp, 0);
+	tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK;
+
+	if (!netif_running(tp->dev)) {
+		tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
+		tg3_full_unlock(tp);
+		return;
+	}
+
+	tg3_full_unlock(tp);
+
 	tg3_netif_stop(tp);
 
 	tg3_full_lock(tp, 1);
@@ -3494,10 +3505,12 @@
 
 	tg3_netif_start(tp);
 
-	tg3_full_unlock(tp);
-
 	if (restart_timer)
 		mod_timer(&tp->timer, jiffies + 1);
+
+	tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
+
+	tg3_full_unlock(tp);
 }
 
 static void tg3_tx_timeout(struct net_device *dev)
@@ -6786,6 +6799,13 @@
 {
 	struct tg3 *tp = netdev_priv(dev);
 
+	/* Calling flush_scheduled_work() may deadlock because
+	 * linkwatch_event() may be on the workqueue and it will try to get
+	 * the rtnl_lock which we are holding.
+	 */
+	while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK)
+		msleep(1);
+
 	netif_stop_queue(dev);
 
 	del_timer_sync(&tp->timer);
@@ -10880,6 +10900,7 @@
 	if (dev) {
 		struct tg3 *tp = netdev_priv(dev);
 
+		flush_scheduled_work();
 		unregister_netdev(dev);
 		if (tp->regs) {
 			iounmap(tp->regs);
@@ -10901,6 +10922,7 @@
 	if (!netif_running(dev))
 		return 0;
 
+	flush_scheduled_work();
 	tg3_netif_stop(tp);
 
 	del_timer_sync(&tp->timer);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index e824330..7f4b7f6 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2162,6 +2162,7 @@
 #define TG3_FLAG_JUMBO_RING_ENABLE	0x00800000
 #define TG3_FLAG_10_100_ONLY		0x01000000
 #define TG3_FLAG_PAUSE_AUTONEG		0x02000000
+#define TG3_FLAG_IN_RESET_TASK		0x04000000
 #define TG3_FLAG_BROKEN_CHECKSUMS	0x10000000
 #define TG3_FLAG_GOT_SERDES_FLOWCTL	0x20000000
 #define TG3_FLAG_SPLIT_MODE		0x40000000
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 9839816..238e9c7 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -214,7 +214,7 @@
 /* For module input parameter */
 static int debug;
 static u32 cr6set;
-static unsigned char mode = 8;
+static int mode = 8;
 
 /* function declaration ------------------------------------- */
 static int uli526x_open(struct net_device *);
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 2f61a47..1ff5de0 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -1943,7 +1943,7 @@
 					(++i%TX_RING_SIZE)*sizeof(*tx_fd));
 	} while (i < TX_RING_SIZE);
 
-	if (dscc4_init_dummy_skb(dpriv) < 0)
+	if (!dscc4_init_dummy_skb(dpriv))
 		goto err_free_dma_tx;
 
 	memset(dpriv->rx_skbuff, 0, sizeof(struct sk_buff *)*RX_RING_SIZE);
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index 8dea07b..eba8e5c 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -29,7 +29,7 @@
 #include <linux/netdevice.h>
 #include <linux/hdlc.h>
 #include <linux/pci.h>
-#include <asm/delay.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 
 #include "hd64572.h"
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index 9c1e106..9d3b51c 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -27,8 +27,8 @@
 #include <linux/hdlc.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
+#include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/delay.h>
 
 #include "wanxl.h"
 
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 233a4f6..ef85d76 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -148,7 +148,7 @@
 	  In order to use this driver, you will need a firmware image for it.
           You can obtain the firmware from
 	  <http://ipw2100.sf.net/>.  Once you have the firmware image, you 
-	  will need to place it in /etc/firmware.
+	  will need to place it in /lib/firmware.
 
           You will also very likely need the Wireless Tools in order to
           configure your card:
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
index c8f6286..308f773 100644
--- a/drivers/net/wireless/hostap/Kconfig
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -75,7 +75,7 @@
 
 config HOSTAP_CS
 	tristate "Host AP driver for Prism2/2.5/3 PC Cards"
-	depends on PCMCIA!=n && HOSTAP
+	depends on PCMCIA && HOSTAP
 	---help---
 	Host AP driver's version for Prism2/2.5/3 PC Cards.
 
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 8bf0276..6290c9f 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -2201,6 +2201,17 @@
 #define SEARCH_SNAPSHOT 1
 
 #define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff))
+static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
+{
+	int i;
+	if (!priv->snapshot[0])
+		return;
+	for (i = 0; i < 0x30; i++)
+		kfree(priv->snapshot[i]);
+	priv->snapshot[0] = NULL;
+}
+
+#ifdef CONFIG_IPW2100_DEBUG_C3
 static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
 {
 	int i;
@@ -2221,16 +2232,6 @@
 	return 1;
 }
 
-static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
-{
-	int i;
-	if (!priv->snapshot[0])
-		return;
-	for (i = 0; i < 0x30; i++)
-		kfree(priv->snapshot[i]);
-	priv->snapshot[0] = NULL;
-}
-
 static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
 				    size_t len, int mode)
 {
@@ -2269,6 +2270,7 @@
 
 	return ret;
 }
+#endif
 
 /*
  *
@@ -7112,11 +7114,17 @@
 {
 	struct ipw2100_priv *priv = ieee80211_priv(dev);
 	int err = 0, value;
+	
+	if (ipw_radio_kill_sw(priv, wrqu->txpower.disabled))
+		return -EINPROGRESS;
 
 	if (priv->ieee->iw_mode != IW_MODE_ADHOC)
+		return 0;
+
+	if ((wrqu->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
 		return -EINVAL;
 
-	if (wrqu->txpower.disabled == 1 || wrqu->txpower.fixed == 0)
+	if (wrqu->txpower.fixed == 0)
 		value = IPW_TX_POWER_DEFAULT;
 	else {
 		if (wrqu->txpower.value < IPW_TX_POWER_MIN_DBM ||
@@ -7151,24 +7159,19 @@
 
 	struct ipw2100_priv *priv = ieee80211_priv(dev);
 
-	if (priv->ieee->iw_mode != IW_MODE_ADHOC) {
-		wrqu->power.disabled = 1;
-		return 0;
-	}
+	wrqu->txpower.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0;
 
 	if (priv->tx_power == IPW_TX_POWER_DEFAULT) {
-		wrqu->power.fixed = 0;
-		wrqu->power.value = IPW_TX_POWER_MAX_DBM;
-		wrqu->power.disabled = 1;
+		wrqu->txpower.fixed = 0;
+		wrqu->txpower.value = IPW_TX_POWER_MAX_DBM;
 	} else {
-		wrqu->power.disabled = 0;
-		wrqu->power.fixed = 1;
-		wrqu->power.value = priv->tx_power;
+		wrqu->txpower.fixed = 1;
+		wrqu->txpower.value = priv->tx_power;
 	}
 
-	wrqu->power.flags = IW_TXPOW_DBM;
+	wrqu->txpower.flags = IW_TXPOW_DBM;
 
-	IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->power.value);
+	IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->txpower.value);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 4c28e33..14beab4 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -2456,7 +2456,7 @@
 	   copy.  Otherwise let the firmware know to perform the operation
 	   on it's own
 	 */
-	if ((priv->eeprom + EEPROM_VERSION) != 0) {
+	if (priv->eeprom[EEPROM_VERSION] != 0) {
 		IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n");
 
 		/* write the eeprom data to sram */
@@ -8012,6 +8012,10 @@
 	else
 		IPW_DEBUG_INFO("Auto adhoc creation disabled.\n");
 
+	priv->config &= ~CFG_STATIC_ESSID;
+	priv->essid_len = 0;
+	memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
+
 	if (disable) {
 		priv->status |= STATUS_RF_KILL_SW;
 		IPW_DEBUG_INFO("Radio disabled.\n");
@@ -11035,7 +11039,6 @@
 	net_dev->set_multicast_list = ipw_net_set_multicast_list;
 	net_dev->set_mac_address = ipw_net_set_mac_address;
 	priv->wireless_data.spy_data = &priv->ieee->spy_data;
-	priv->wireless_data.ieee80211 = priv->ieee;
 	net_dev->wireless_data = &priv->wireless_data;
 	net_dev->wireless_handlers = &ipw_wx_handler_def;
 	net_dev->ethtool_ops = &ipw_ethtool_ops;
@@ -11121,8 +11124,8 @@
 	/* Free MAC hash list for ADHOC */
 	for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) {
 		list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
-			kfree(list_entry(p, struct ipw_ibss_seq, list));
 			list_del(p);
+			kfree(list_entry(p, struct ipw_ibss_seq, list));
 		}
 	}
 
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index b664708..ec6f2a4 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -261,13 +261,13 @@
 		/* Note that the CIS values need to be rescaled */
 		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
 			if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
 				if (!ignore_cis_vcc)
 					goto next_entry;
 			}
 		} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
 			if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
-				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
+				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
 				if(!ignore_cis_vcc)
 					goto next_entry;
 			}
@@ -590,6 +590,7 @@
 	PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
 	PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
 	PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
+	PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
 	PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
 	PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
 	PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index c5cd61c..e5bb9f5 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -748,7 +748,7 @@
 	if (essid->length) {
 		dwrq->flags = 1;	/* set ESSID to ON for Wireless Extensions */
 		/* if it is to big, trunk it */
-		dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length);
+		dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length);
 	} else {
 		dwrq->flags = 0;
 		dwrq->length = 0;
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 9e0229f..f46e843 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -1423,7 +1423,7 @@
 	struct resource *res = ioc->mmio_region;
 	char *name = kmalloc(14, GFP_KERNEL);
 
-	sprintf(name, "GSC Bus [%d/]", ioc->hw_path);
+	snprintf(name, 14, "GSC Bus [%d/]", ioc->hw_path);
 
 	ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
 	ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
@@ -1557,12 +1557,11 @@
 	int i;
 	struct ioc *ioc, **ioc_p = &ioc_list;
 	
-	ioc = kmalloc(sizeof(struct ioc), GFP_KERNEL);
+	ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL);
 	if (ioc == NULL) {
 		printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
 		return 1;
 	}
-	memset(ioc, 0, sizeof(struct ioc));
 
 	ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn";
 
@@ -1578,7 +1577,7 @@
 	ccio_ioc_init(ioc);
 	ccio_init_resources(ioc);
 	hppa_dma_ops = &ccio_ops;
-	dev->dev.platform_data = kmalloc(sizeof(struct pci_hba_data), GFP_KERNEL);
+	dev->dev.platform_data = kzalloc(sizeof(struct pci_hba_data), GFP_KERNEL);
 
 	/* if this fails, no I/O cards will work, so may as well bug */
 	BUG_ON(dev->dev.platform_data == NULL);
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 216d1d8..3d1a7f9 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -989,14 +989,12 @@
 */
 	}
 
-	dino_dev = kmalloc(sizeof(struct dino_device), GFP_KERNEL);
+	dino_dev = kzalloc(sizeof(struct dino_device), GFP_KERNEL);
 	if (!dino_dev) {
 		printk("dino_init_chip - couldn't alloc dino_device\n");
 		return 1;
 	}
 
-	memset(dino_dev, 0, sizeof(struct dino_device));
-
 	dino_dev->hba.dev = dev;
 	dino_dev->hba.base_addr = ioremap(hpa, 4096);
 	dino_dev->hba.lmmio_space_offset = 0;	/* CPU addrs == bus addrs */
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index 5edf93f..07dc2b6 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -60,12 +60,11 @@
 	}
 
 	if(card->hpa) {
-		card->next = kmalloc(sizeof(struct hppb_card), GFP_KERNEL);
+		card->next = kzalloc(sizeof(struct hppb_card), GFP_KERNEL);
 		if(!card->next) {
 			printk(KERN_ERR "HP-PB: Unable to allocate memory.\n");
 			return 1;
 		}
-		memset(card->next, '\0', sizeof(struct hppb_card));
 		card = card->next;
 	}
         printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start);
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 19657ef..8d7a363 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -873,28 +873,24 @@
 		return NULL;
 	}
 
-	isi = (struct iosapic_info *)kmalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+	isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
 	if (!isi) {
 		BUG();
 		return NULL;
 	}
 
-	memset(isi, 0, sizeof(struct iosapic_info));
-
 	isi->addr = ioremap(hpa, 4096);
 	isi->isi_hpa = hpa;
 	isi->isi_version = iosapic_rd_version(isi);
 	isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
 
 	vip = isi->isi_vector = (struct vector_info *)
-		kmalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
+		kzalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
 	if (vip == NULL) {
 		kfree(isi);
 		return NULL;
 	}
 
-	memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
-
 	for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
 		vip->irqline = (unsigned char) cnt;
 		vip->iosapic = isi;
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index 2b3ba1d..cb3d281 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -166,11 +166,12 @@
 int __init
 lasi_init_chip(struct parisc_device *dev)
 {
+	extern void (*chassis_power_off)(void);
 	struct gsc_asic *lasi;
 	struct gsc_irq gsc_irq;
 	int ret;
 
-	lasi = kmalloc(sizeof(*lasi), GFP_KERNEL);
+	lasi = kzalloc(sizeof(*lasi), GFP_KERNEL);
 	if (!lasi)
 		return -ENOMEM;
 
@@ -222,7 +223,7 @@
 	 * ensure that only the first LASI (the one controlling the power off)
 	 * should set the HPA here */
 	lasi_power_off_hpa = lasi->hpa;
-	pm_power_off = lasi_power_off;
+	chassis_power_off = lasi_power_off;
 	
 	return ret;
 }
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index cbae8c8..e8a2a4a 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1565,7 +1565,7 @@
 	} else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) {
 		func_class &= 0xff;
 		version = kmalloc(6, GFP_KERNEL);
-		sprintf(version,"TR%d.%d",(func_class >> 4),(func_class & 0xf));
+		snprintf(version, 6, "TR%d.%d",(func_class >> 4),(func_class & 0xf));
 		/* We could use one printk for both Elroy and Mercury,
                  * but for the mask for func_class.
                  */ 
@@ -1586,14 +1586,12 @@
 	**	have an IRT entry will get NULL back from iosapic code.
 	*/
 	
-	lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);
+	lba_dev = kzalloc(sizeof(struct lba_device), GFP_KERNEL);
 	if (!lba_dev) {
 		printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n");
 		return(1);
 	}
 
-	memset(lba_dev, 0, sizeof(struct lba_device));
-
 
 	/* ---------- First : initialize data we already have --------- */
 
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 42a3c54..a28e178 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -1,7 +1,7 @@
 /* 
  *    Interfaces to retrieve and set PDC Stable options (firmware)
  *
- *    Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *    Copyright (C) 2005-2006 Thibaut VARENE <varenet@parisc-linux.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
@@ -26,11 +26,19 @@
  *
  *    Since locations between 96 and 192 are the various paths, most (if not
  *    all) PA-RISC machines should have them. Anyway, for safety reasons, the
- *    following code can deal with only 96 bytes of Stable Storage, and all
+ *    following code can deal with just 96 bytes of Stable Storage, and all
  *    sizes between 96 and 192 bytes (provided they are multiple of struct
  *    device_path size, eg: 128, 160 and 192) to provide full information.
  *    The code makes no use of data above 192 bytes. One last word: there's one
  *    path we can always count on: the primary path.
+ *
+ *    The current policy wrt file permissions is:
+ *	- write: root only
+ *	- read: (reading triggers PDC calls) ? root only : everyone
+ *    The rationale is that PDC calls could hog (DoS) the machine.
+ *
+ *	TODO:
+ *	- timer/fastsize write calls
  */
 
 #undef PDCS_DEBUG
@@ -50,13 +58,15 @@
 #include <linux/kobject.h>
 #include <linux/device.h>
 #include <linux/errno.h>
+#include <linux/spinlock.h>
 
 #include <asm/pdc.h>
 #include <asm/page.h>
 #include <asm/uaccess.h>
 #include <asm/hardware.h>
 
-#define PDCS_VERSION	"0.10"
+#define PDCS_VERSION	"0.22"
+#define PDCS_PREFIX	"PDC Stable Storage"
 
 #define PDCS_ADDR_PPRI	0x00
 #define PDCS_ADDR_OSID	0x40
@@ -70,10 +80,12 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(PDCS_VERSION);
 
+/* holds Stable Storage size. Initialized once and for all, no lock needed */
 static unsigned long pdcs_size __read_mostly;
 
 /* This struct defines what we need to deal with a parisc pdc path entry */
 struct pdcspath_entry {
+	rwlock_t rw_lock;		/* to protect path entry access */
 	short ready;			/* entry record is valid if != 0 */
 	unsigned long addr;		/* entry address in stable storage */
 	char *name;			/* entry name */
@@ -121,6 +133,8 @@
  * content of the stable storage WRT various paths in these structs. We read
  * these structs when reading the files, and we will write to these structs when
  * writing to the files, and only then write them back to the Stable Storage.
+ *
+ * This function expects to be called with @entry->rw_lock write-hold.
  */
 static int
 pdcspath_fetch(struct pdcspath_entry *entry)
@@ -160,14 +174,15 @@
  * pointer, from which it'll find out the corresponding hardware path.
  * For now we do not handle the case where there's an error in writing to the
  * Stable Storage area, so you'd better not mess up the data :P
+ *
+ * This function expects to be called with @entry->rw_lock write-hold.
  */
-static int
+static void
 pdcspath_store(struct pdcspath_entry *entry)
 {
 	struct device_path *devpath;
 
-	if (!entry)
-		return -EINVAL;
+	BUG_ON(!entry);
 
 	devpath = &entry->devpath;
 	
@@ -176,10 +191,8 @@
 	   First case, we don't have a preset hwpath... */
 	if (!entry->ready) {
 		/* ...but we have a device, map it */
-		if (entry->dev)
-			device_to_hwpath(entry->dev, (struct hardware_path *)devpath);
-		else
-			return -EINVAL;
+		BUG_ON(!entry->dev);
+		device_to_hwpath(entry->dev, (struct hardware_path *)devpath);
 	}
 	/* else, we expect the provided hwpath to be valid. */
 	
@@ -191,15 +204,13 @@
 		printk(KERN_ERR "%s: an error occured when writing to PDC.\n"
 				"It is likely that the Stable Storage data has been corrupted.\n"
 				"Please check it carefully upon next reboot.\n", __func__);
-		return -EIO;
+		WARN_ON(1);
 	}
 		
 	/* kobject is already registered */
 	entry->ready = 2;
 	
 	DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
-	
-	return 0;
 }
 
 /**
@@ -214,14 +225,17 @@
 {
 	char *out = buf;
 	struct device_path *devpath;
-	unsigned short i;
+	short i;
 
 	if (!entry || !buf)
 		return -EINVAL;
 
+	read_lock(&entry->rw_lock);
 	devpath = &entry->devpath;
+	i = entry->ready;
+	read_unlock(&entry->rw_lock);
 
-	if (!entry->ready)
+	if (!i)	/* entry is not ready */
 		return -ENODATA;
 	
 	for (i = 0; i < 6; i++) {
@@ -242,7 +256,7 @@
  * 
  * We will call this function to change the current hardware path.
  * Hardware paths are to be given '/'-delimited, without brackets.
- * We take care to make sure that the provided path actually maps to an existing
+ * We make sure that the provided path actually maps to an existing
  * device, BUT nothing would prevent some foolish user to set the path to some
  * PCI bridge or even a CPU...
  * A better work around would be to make sure we are at the end of a device tree
@@ -298,17 +312,19 @@
 	}
 	
 	/* So far so good, let's get in deep */
+	write_lock(&entry->rw_lock);
 	entry->ready = 0;
 	entry->dev = dev;
 	
 	/* Now, dive in. Write back to the hardware */
-	WARN_ON(pdcspath_store(entry));	/* this warn should *NEVER* happen */
+	pdcspath_store(entry);
 	
 	/* Update the symlink to the real device */
 	sysfs_remove_link(&entry->kobj, "device");
 	sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+	write_unlock(&entry->rw_lock);
 	
-	printk(KERN_INFO "PDC Stable Storage: changed \"%s\" path to \"%s\"\n",
+	printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" path to \"%s\"\n",
 		entry->name, buf);
 	
 	return count;
@@ -326,14 +342,17 @@
 {
 	char *out = buf;
 	struct device_path *devpath;
-	unsigned short i;
+	short i;
 
 	if (!entry || !buf)
 		return -EINVAL;
 	
+	read_lock(&entry->rw_lock);
 	devpath = &entry->devpath;
+	i = entry->ready;
+	read_unlock(&entry->rw_lock);
 
-	if (!entry->ready)
+	if (!i)	/* entry is not ready */
 		return -ENODATA;
 	
 	for (i = 0; devpath->layers[i] && (likely(i < 6)); i++)
@@ -388,15 +407,17 @@
 	}
 		
 	/* So far so good, let's get in deep */
+	write_lock(&entry->rw_lock);
 	
 	/* First, overwrite the current layers with the new ones, not touching
 	   the hardware path. */
 	memcpy(&entry->devpath.layers, &layers, sizeof(layers));
 	
 	/* Now, dive in. Write back to the hardware */
-	WARN_ON(pdcspath_store(entry));	/* this warn should *NEVER* happen */
+	pdcspath_store(entry);
+	write_unlock(&entry->rw_lock);
 	
-	printk(KERN_INFO "PDC Stable Storage: changed \"%s\" layers to \"%s\"\n",
+	printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" layers to \"%s\"\n",
 		entry->name, buf);
 	
 	return count;
@@ -415,9 +436,6 @@
 	struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr);
 	ssize_t ret = 0;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
 	if (pdcs_attr->show)
 		ret = pdcs_attr->show(entry, buf);
 
@@ -454,8 +472,8 @@
 };
 
 /* These are the two attributes of any PDC path. */
-static PATHS_ATTR(hwpath, 0600, pdcspath_hwpath_read, pdcspath_hwpath_write);
-static PATHS_ATTR(layer, 0600, pdcspath_layer_read, pdcspath_layer_write);
+static PATHS_ATTR(hwpath, 0644, pdcspath_hwpath_read, pdcspath_hwpath_write);
+static PATHS_ATTR(layer, 0644, pdcspath_layer_read, pdcspath_layer_write);
 
 static struct attribute *paths_subsys_attrs[] = {
 	&paths_attr_hwpath.attr,
@@ -484,36 +502,119 @@
 	NULL,
 };
 
+
+/* For more insight of what's going on here, refer to PDC Procedures doc,
+ * Section PDC_STABLE */
+
 /**
- * pdcs_info_read - Pretty printing of the remaining useful data.
+ * pdcs_size_read - Stable Storage size output.
  * @entry: An allocated and populated subsytem struct. We don't use it tho.
  * @buf: The output buffer to write to.
- * 
- * We will call this function to format the output of the 'info' attribute file.
- * Please refer to PDC Procedures documentation, section PDC_STABLE to get a
- * better insight of what we're doing here.
  */
 static ssize_t
-pdcs_info_read(struct subsystem *entry, char *buf)
+pdcs_size_read(struct subsystem *entry, char *buf)
 {
 	char *out = buf;
-	__u32 result;
-	struct device_path devpath;
-	char *tmpstr = NULL;
 	
 	if (!entry || !buf)
 		return -EINVAL;
 		
 	/* show the size of the stable storage */
-	out += sprintf(out, "Stable Storage size: %ld bytes\n", pdcs_size);
+	out += sprintf(out, "%ld\n", pdcs_size);
 
-	/* deal with flags */
-	if (pdc_stable_read(PDCS_ADDR_PPRI, &devpath, sizeof(devpath)) != PDC_OK)
-		return -EIO;
+	return out - buf;
+}
+
+/**
+ * pdcs_auto_read - Stable Storage autoboot/search flag output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
+ */
+static ssize_t
+pdcs_auto_read(struct subsystem *entry, char *buf, int knob)
+{
+	char *out = buf;
+	struct pdcspath_entry *pathentry;
 	
-	out += sprintf(out, "Autoboot: %s\n", (devpath.flags & PF_AUTOBOOT) ? "On" : "Off");
-	out += sprintf(out, "Autosearch: %s\n", (devpath.flags & PF_AUTOSEARCH) ? "On" : "Off");
-	out += sprintf(out, "Timer: %u s\n", (devpath.flags & PF_TIMER) ? (1 << (devpath.flags & PF_TIMER)) : 0);
+	if (!entry || !buf)
+		return -EINVAL;
+
+	/* Current flags are stored in primary boot path entry */
+	pathentry = &pdcspath_entry_primary;
+
+	read_lock(&pathentry->rw_lock);
+	out += sprintf(out, "%s\n", (pathentry->devpath.flags & knob) ?
+					"On" : "Off");
+	read_unlock(&pathentry->rw_lock);
+
+	return out - buf;
+}
+
+/**
+ * pdcs_autoboot_read - Stable Storage autoboot flag output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ */
+static inline ssize_t
+pdcs_autoboot_read(struct subsystem *entry, char *buf)
+{
+	return pdcs_auto_read(entry, buf, PF_AUTOBOOT);
+}
+
+/**
+ * pdcs_autosearch_read - Stable Storage autoboot flag output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ */
+static inline ssize_t
+pdcs_autosearch_read(struct subsystem *entry, char *buf)
+{
+	return pdcs_auto_read(entry, buf, PF_AUTOSEARCH);
+}
+
+/**
+ * pdcs_timer_read - Stable Storage timer count output (in seconds).
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * The value of the timer field correponds to a number of seconds in powers of 2.
+ */
+static ssize_t
+pdcs_timer_read(struct subsystem *entry, char *buf)
+{
+	char *out = buf;
+	struct pdcspath_entry *pathentry;
+
+	if (!entry || !buf)
+		return -EINVAL;
+
+	/* Current flags are stored in primary boot path entry */
+	pathentry = &pdcspath_entry_primary;
+
+	/* print the timer value in seconds */
+	read_lock(&pathentry->rw_lock);
+	out += sprintf(out, "%u\n", (pathentry->devpath.flags & PF_TIMER) ?
+				(1 << (pathentry->devpath.flags & PF_TIMER)) : 0);
+	read_unlock(&pathentry->rw_lock);
+
+	return out - buf;
+}
+
+/**
+ * pdcs_osid_read - Stable Storage OS ID register output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ */
+static ssize_t
+pdcs_osid_read(struct subsystem *entry, char *buf)
+{
+	char *out = buf;
+	__u32 result;
+	char *tmpstr = NULL;
+
+	if (!entry || !buf)
+		return -EINVAL;
 
 	/* get OSID */
 	if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK)
@@ -529,13 +630,31 @@
 		case 0x0005:	tmpstr = "Novell Netware dependent data"; break;
 		default:	tmpstr = "Unknown"; break;
 	}
-	out += sprintf(out, "OS ID: %s (0x%.4x)\n", tmpstr, (result >> 16));
+	out += sprintf(out, "%s (0x%.4x)\n", tmpstr, (result >> 16));
+
+	return out - buf;
+}
+
+/**
+ * pdcs_fastsize_read - Stable Storage FastSize register output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * This register holds the amount of system RAM to be tested during boot sequence.
+ */
+static ssize_t
+pdcs_fastsize_read(struct subsystem *entry, char *buf)
+{
+	char *out = buf;
+	__u32 result;
+
+	if (!entry || !buf)
+		return -EINVAL;
 
 	/* get fast-size */
 	if (pdc_stable_read(PDCS_ADDR_FSIZ, &result, sizeof(result)) != PDC_OK)
 		return -EIO;
 
-	out += sprintf(out, "Memory tested: ");
 	if ((result & 0x0F) < 0x0E)
 		out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256);
 	else
@@ -546,22 +665,18 @@
 }
 
 /**
- * pdcs_info_write - This function handles boot flag modifying.
+ * pdcs_auto_write - This function handles autoboot/search flag modifying.
  * @entry: An allocated and populated subsytem struct. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
+ * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
  * 
- * We will call this function to change the current boot flags.
+ * We will call this function to change the current autoboot flag.
  * We expect a precise syntax:
- *	\"n n\" (n == 0 or 1) to toggle respectively AutoBoot and AutoSearch
- *
- * As of now there is no incentive on my side to provide more "knobs" to that
- * interface, since modifying the rest of the data is pretty meaningless when
- * the machine is running and for the expected use of that facility, such as
- * PALO setting up the boot disk when installing a Linux distribution...
+ *	\"n\" (n == 0 or 1) to toggle AutoBoot Off or On
  */
 static ssize_t
-pdcs_info_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob)
 {
 	struct pdcspath_entry *pathentry;
 	unsigned char flags;
@@ -582,7 +697,9 @@
 	pathentry = &pdcspath_entry_primary;
 	
 	/* Be nice to the existing flag record */
+	read_lock(&pathentry->rw_lock);
 	flags = pathentry->devpath.flags;
+	read_unlock(&pathentry->rw_lock);
 	
 	DPRINTK("%s: flags before: 0x%X\n", __func__, flags);
 			
@@ -595,50 +712,85 @@
 	if ((c != 0) && (c != 1))
 		goto parse_error;
 	if (c == 0)
-		flags &= ~PF_AUTOBOOT;
+		flags &= ~knob;
 	else
-		flags |= PF_AUTOBOOT;
-	
-	if (*temp++ != ' ')
-		goto parse_error;
-	
-	c = *temp++ - '0';
-	if ((c != 0) && (c != 1))
-		goto parse_error;
-	if (c == 0)
-		flags &= ~PF_AUTOSEARCH;
-	else
-		flags |= PF_AUTOSEARCH;
+		flags |= knob;
 	
 	DPRINTK("%s: flags after: 0x%X\n", __func__, flags);
 		
 	/* So far so good, let's get in deep */
+	write_lock(&pathentry->rw_lock);
 	
 	/* Change the path entry flags first */
 	pathentry->devpath.flags = flags;
 		
 	/* Now, dive in. Write back to the hardware */
-	WARN_ON(pdcspath_store(pathentry));	/* this warn should *NEVER* happen */
+	pdcspath_store(pathentry);
+	write_unlock(&pathentry->rw_lock);
 	
-	printk(KERN_INFO "PDC Stable Storage: changed flags to \"%s\"\n", buf);
+	printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" to \"%s\"\n",
+		(knob & PF_AUTOBOOT) ? "autoboot" : "autosearch",
+		(flags & knob) ? "On" : "Off");
 	
 	return count;
 
 parse_error:
-	printk(KERN_WARNING "%s: Parse error: expect \"n n\" (n == 0 or 1) for AB and AS\n", __func__);
+	printk(KERN_WARNING "%s: Parse error: expect \"n\" (n == 0 or 1)\n", __func__);
 	return -EINVAL;
 }
 
-/* The last attribute (the 'root' one actually) with all remaining data. */
-static PDCS_ATTR(info, 0600, pdcs_info_read, pdcs_info_write);
+/**
+ * pdcs_autoboot_write - This function handles autoboot flag modifying.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * We will call this function to change the current boot flags.
+ * We expect a precise syntax:
+ *	\"n\" (n == 0 or 1) to toggle AutoSearch Off or On
+ */
+static inline ssize_t
+pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count)
+{
+	return pdcs_auto_write(entry, buf, count, PF_AUTOBOOT);
+}
+
+/**
+ * pdcs_autosearch_write - This function handles autosearch flag modifying.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * We will call this function to change the current boot flags.
+ * We expect a precise syntax:
+ *	\"n\" (n == 0 or 1) to toggle AutoSearch Off or On
+ */
+static inline ssize_t
+pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count)
+{
+	return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH);
+}
+
+/* The remaining attributes. */
+static PDCS_ATTR(size, 0444, pdcs_size_read, NULL);
+static PDCS_ATTR(autoboot, 0644, pdcs_autoboot_read, pdcs_autoboot_write);
+static PDCS_ATTR(autosearch, 0644, pdcs_autosearch_read, pdcs_autosearch_write);
+static PDCS_ATTR(timer, 0444, pdcs_timer_read, NULL);
+static PDCS_ATTR(osid, 0400, pdcs_osid_read, NULL);
+static PDCS_ATTR(fastsize, 0400, pdcs_fastsize_read, NULL);
 
 static struct subsys_attribute *pdcs_subsys_attrs[] = {
-	&pdcs_attr_info,
-	NULL,	/* maybe more in the future? */
+	&pdcs_attr_size,
+	&pdcs_attr_autoboot,
+	&pdcs_attr_autosearch,
+	&pdcs_attr_timer,
+	&pdcs_attr_osid,
+	&pdcs_attr_fastsize,
+	NULL,
 };
 
 static decl_subsys(paths, &ktype_pdcspath, NULL);
-static decl_subsys(pdc, NULL, NULL);
+static decl_subsys(stable, NULL, NULL);
 
 /**
  * pdcs_register_pathentries - Prepares path entries kobjects for sysfs usage.
@@ -656,8 +808,16 @@
 	struct pdcspath_entry *entry;
 	int err;
 	
+	/* Initialize the entries rw_lock before anything else */
+	for (i = 0; (entry = pdcspath_entries[i]); i++)
+		rwlock_init(&entry->rw_lock);
+
 	for (i = 0; (entry = pdcspath_entries[i]); i++) {
-		if (pdcspath_fetch(entry) < 0)
+		write_lock(&entry->rw_lock);
+		err = pdcspath_fetch(entry);
+		write_unlock(&entry->rw_lock);
+
+		if (err < 0)
 			continue;
 
 		if ((err = kobject_set_name(&entry->kobj, "%s", entry->name)))
@@ -667,13 +827,14 @@
 			return err;
 		
 		/* kobject is now registered */
+		write_lock(&entry->rw_lock);
 		entry->ready = 2;
 		
-		if (!entry->dev)
-			continue;
-
 		/* Add a nice symlink to the real device */
-		sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+		if (entry->dev)
+			sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+
+		write_unlock(&entry->rw_lock);
 	}
 	
 	return 0;
@@ -688,14 +849,17 @@
 	unsigned short i;
 	struct pdcspath_entry *entry;
 	
-	for (i = 0; (entry = pdcspath_entries[i]); i++)
+	for (i = 0; (entry = pdcspath_entries[i]); i++) {
+		read_lock(&entry->rw_lock);
 		if (entry->ready >= 2)
-			kobject_unregister(&entry->kobj);	
+			kobject_unregister(&entry->kobj);
+		read_unlock(&entry->rw_lock);
+	}
 }
 
 /*
- * For now we register the pdc subsystem with the firmware subsystem
- * and the paths subsystem with the pdc subsystem
+ * For now we register the stable subsystem with the firmware subsystem
+ * and the paths subsystem with the stable subsystem
  */
 static int __init
 pdc_stable_init(void)
@@ -707,19 +871,23 @@
 	if (pdc_stable_get_size(&pdcs_size) != PDC_OK) 
 		return -ENODEV;
 
-	printk(KERN_INFO "PDC Stable Storage facility v%s\n", PDCS_VERSION);
+	/* make sure we have enough data */
+	if (pdcs_size < 96)
+		return -ENODATA;
 
-	/* For now we'll register the pdc subsys within this driver */
-	if ((rc = firmware_register(&pdc_subsys)))
+	printk(KERN_INFO PDCS_PREFIX " facility v%s\n", PDCS_VERSION);
+
+	/* For now we'll register the stable subsys within this driver */
+	if ((rc = firmware_register(&stable_subsys)))
 		goto fail_firmreg;
 
-	/* Don't forget the info entry */
+	/* Don't forget the root entries */
 	for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++)
 		if (attr->show)
-			error = subsys_create_file(&pdc_subsys, attr);
+			error = subsys_create_file(&stable_subsys, attr);
 	
-	/* register the paths subsys as a subsystem of pdc subsys */
-	kset_set_kset_s(&paths_subsys, pdc_subsys);
+	/* register the paths subsys as a subsystem of stable subsys */
+	kset_set_kset_s(&paths_subsys, stable_subsys);
 	if ((rc= subsystem_register(&paths_subsys)))
 		goto fail_subsysreg;
 
@@ -734,10 +902,10 @@
 	subsystem_unregister(&paths_subsys);
 	
 fail_subsysreg:
-	firmware_unregister(&pdc_subsys);
+	firmware_unregister(&stable_subsys);
 	
 fail_firmreg:
-	printk(KERN_INFO "PDC Stable Storage bailing out\n");
+	printk(KERN_INFO PDCS_PREFIX " bailing out\n");
 	return rc;
 }
 
@@ -747,7 +915,7 @@
 	pdcs_unregister_pathentries();
 	subsystem_unregister(&paths_subsys);
 
-	firmware_unregister(&pdc_subsys);
+	firmware_unregister(&stable_subsys);
 }
 
 
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index c85653f..52f265e 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -2064,14 +2064,13 @@
 	printk(KERN_INFO "%s found %s at 0x%lx\n",
 		MODULE_NAME, version, dev->hpa.start);
 
-	sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
+	sba_dev = kzalloc(sizeof(struct sba_device), GFP_KERNEL);
 	if (!sba_dev) {
 		printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n");
 		return -ENOMEM;
 	}
 
 	parisc_set_drvdata(dev, sba_dev);
-	memset(sba_dev, 0, sizeof(struct sba_device));
 
 	for(i=0; i<MAX_IOC; i++)
 		spin_lock_init(&(sba_dev->ioc[i].res_lock));
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index d14888e..ba971fe 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -89,6 +89,9 @@
 #define DBG_INIT(x...)
 #endif
 
+#define SUPERIO	"SuperIO"
+#define PFX	SUPERIO ": "
+
 static irqreturn_t
 superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
 {
@@ -117,7 +120,7 @@
 	local_irq = results & 0x0f;
 
 	if (local_irq == 2 || local_irq > 7) {
-		printk(KERN_ERR "SuperIO: slave interrupted!\n");
+		printk(KERN_ERR PFX "slave interrupted!\n");
 		return IRQ_HANDLED;
 	}
 
@@ -128,7 +131,7 @@
 		outb(OCW3_ISR,IC_PIC1+0);
 		results = inb(IC_PIC1+0);
 		if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */
-			printk(KERN_WARNING "SuperIO: spurious interrupt!\n");
+			printk(KERN_WARNING PFX "spurious interrupt!\n");
 			return IRQ_HANDLED;
 		}
 	}
@@ -163,27 +166,27 @@
 	/* ...then properly fixup the USB to point at suckyio PIC */
 	sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev);
 
-	printk(KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
+	printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
 	       pci_name(pdev), pdev->irq);
 
 	pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base);
 	sio->sp1_base &= ~1;
-	printk (KERN_INFO "SuperIO: Serial port 1 at 0x%x\n", sio->sp1_base);
+	printk(KERN_INFO PFX "Serial port 1 at 0x%x\n", sio->sp1_base);
 
 	pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base);
 	sio->sp2_base &= ~1;
-	printk (KERN_INFO "SuperIO: Serial port 2 at 0x%x\n", sio->sp2_base);
+	printk(KERN_INFO PFX "Serial port 2 at 0x%x\n", sio->sp2_base);
 
 	pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base);
 	sio->pp_base &= ~1;
-	printk (KERN_INFO "SuperIO: Parallel port at 0x%x\n", sio->pp_base);
+	printk(KERN_INFO PFX "Parallel port at 0x%x\n", sio->pp_base);
 
 	pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base);
 	sio->fdc_base &= ~1;
-	printk (KERN_INFO "SuperIO: Floppy controller at 0x%x\n", sio->fdc_base);
+	printk(KERN_INFO PFX "Floppy controller at 0x%x\n", sio->fdc_base);
 	pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base);
 	sio->acpi_base &= ~1;
-	printk (KERN_INFO "SuperIO: ACPI at 0x%x\n", sio->acpi_base);
+	printk(KERN_INFO PFX "ACPI at 0x%x\n", sio->acpi_base);
 
 	request_region (IC_PIC1, 0x1f, "pic1");
 	request_region (IC_PIC2, 0x1f, "pic2");
@@ -263,14 +266,14 @@
 	/* Setup USB power regulation */
 	outb(1, sio->acpi_base + USB_REG_CR);
 	if (inb(sio->acpi_base + USB_REG_CR) & 1)
-		printk(KERN_INFO "SuperIO: USB regulator enabled\n");
+		printk(KERN_INFO PFX "USB regulator enabled\n");
 	else
-		printk(KERN_ERR "USB regulator not initialized!\n");
+		printk(KERN_ERR PFX "USB regulator not initialized!\n");
 
 	if (request_irq(pdev->irq, superio_interrupt, SA_INTERRUPT,
-			"SuperIO", (void *)sio)) {
+			SUPERIO, (void *)sio)) {
 
-		printk(KERN_ERR "SuperIO: could not get irq\n");
+		printk(KERN_ERR PFX "could not get irq\n");
 		BUG();
 		return;
 	}
@@ -284,7 +287,7 @@
 	u8 r8;
 
 	if ((irq < 1) || (irq == 2) || (irq > 7)) {
-		printk(KERN_ERR "SuperIO: Illegal irq number.\n");
+		printk(KERN_ERR PFX "Illegal irq number.\n");
 		BUG();
 		return;
 	}
@@ -301,7 +304,7 @@
 	u8 r8;
 
 	if ((irq < 1) || (irq == 2) || (irq > 7)) {
-		printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", irq);
+		printk(KERN_ERR PFX "Illegal irq number (%d).\n", irq);
 		BUG();
 		return;
 	}
@@ -319,7 +322,7 @@
 }
 
 static struct hw_interrupt_type superio_interrupt_type = {
-	.typename =	"SuperIO",
+	.typename =	SUPERIO,
 	.startup =	superio_startup_irq,
 	.shutdown =	superio_disable_irq,
 	.enable =	superio_enable_irq,
@@ -413,7 +416,7 @@
 
 	retval = early_serial_setup(&serial[0]);
 	if (retval < 0) {
-		printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n");
+		printk(KERN_WARNING PFX "Register Serial #0 failed.\n");
 		return;
 	}
 
@@ -423,7 +426,7 @@
 	retval = early_serial_setup(&serial[1]);
 
 	if (retval < 0)
-		printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n");
+		printk(KERN_WARNING PFX "Register Serial #1 failed.\n");
 #endif /* CONFIG_SERIAL_8250 */
 }
 
@@ -437,7 +440,7 @@
 			PARPORT_DMA_NONE /* dma */,
 			NULL /*struct pci_dev* */) )
 
-		printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n");
+		printk(KERN_WARNING PFX "Probing parallel port failed.\n");
 #endif	/* CONFIG_PARPORT_PC */
 }
 
@@ -499,7 +502,7 @@
 };
 
 static struct pci_driver superio_driver = {
-	.name =         "SuperIO",
+	.name =         SUPERIO,
 	.id_table =     superio_tbl,
 	.probe =        superio_probe,
 };
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
index 17dce2a..813c2c2 100644
--- a/drivers/parisc/wax.c
+++ b/drivers/parisc/wax.c
@@ -76,7 +76,7 @@
 	struct gsc_irq gsc_irq;
 	int ret;
 
-	wax = kmalloc(sizeof(*wax), GFP_KERNEL);
+	wax = kzalloc(sizeof(*wax), GFP_KERNEL);
 	if (!wax)
 		return -ENOMEM;
 
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index f605dea..f63c387 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -90,6 +90,15 @@
 	depends on ARM && PARPORT
 	select PARPORT_NOT_PC
 
+config PARPORT_IP32
+	tristate "SGI IP32 builtin port (EXPERIMENTAL)"
+	depends on SGI_IP32 && PARPORT && EXPERIMENTAL
+	select PARPORT_NOT_PC
+	help
+	  Say Y here if you need support for the parallel port on
+	  SGI O2 machines. This code is also available as a module (say M),
+	  called parport_ip32.  If in doubt, saying N is the safe plan.
+
 config PARPORT_AMIGA
 	tristate "Amiga builtin port"
 	depends on AMIGA && PARPORT
diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile
index 5372212..a19de35 100644
--- a/drivers/parport/Makefile
+++ b/drivers/parport/Makefile
@@ -17,3 +17,4 @@
 obj-$(CONFIG_PARPORT_ATARI)	+= parport_atari.o
 obj-$(CONFIG_PARPORT_SUNBPP)	+= parport_sunbpp.o
 obj-$(CONFIG_PARPORT_GSC)	+= parport_gsc.o
+obj-$(CONFIG_PARPORT_IP32)	+= parport_ip32.o
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index 5b887ba..690b239 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -61,10 +61,10 @@
  *	set to zero, it returns immediately.
  *
  *	If an interrupt occurs before the timeout period elapses, this
- *	function returns one immediately.  If it times out, it returns
- *	a value greater than zero.  An error code less than zero
- *	indicates an error (most likely a pending signal), and the
- *	calling code should finish what it's doing as soon as it can.
+ *	function returns zero immediately.  If it times out, it returns
+ *	one.  An error code less than zero indicates an error (most
+ *	likely a pending signal), and the calling code should finish
+ *	what it's doing as soon as it can.
  */
 
 int parport_wait_event (struct parport *port, signed long timeout)
@@ -110,7 +110,7 @@
  *
  *	If the status lines take on the desired values before the
  *	timeout period elapses, parport_poll_peripheral() returns zero
- *	immediately.  A zero return value greater than zero indicates
+ *	immediately.  A return value greater than zero indicates
  *	a timeout.  An error code (less than zero) indicates an error,
  *	most likely a signal that arrived, and the caller should
  *	finish what it is doing as soon as possible.
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index fde29a7..1de52d9 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -249,7 +249,7 @@
 	struct parport tmp;
 	struct parport *p = &tmp;
 
-	priv = kmalloc (sizeof (struct parport_gsc_private), GFP_KERNEL);
+	priv = kzalloc (sizeof (struct parport_gsc_private), GFP_KERNEL);
 	if (!priv) {
 		printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
 		return NULL;
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c
new file mode 100644
index 0000000..46e06e5
--- /dev/null
+++ b/drivers/parport/parport_ip32.c
@@ -0,0 +1,2253 @@
+/* Low-level parallel port routines for built-in port on SGI IP32
+ *
+ * Author: Arnaud Giersch <arnaud.giersch@free.fr>
+ *
+ * Based on parport_pc.c by
+ *	Phil Blundell, Tim Waugh, Jose Renau, David Campbell,
+ *	Andrea Arcangeli, et al.
+ *
+ * Thanks to Ilya A. Volynets-Evenbakh for his help.
+ *
+ * Copyright (C) 2005, 2006 Arnaud Giersch.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU 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.
+ */
+
+/* Current status:
+ *
+ *	Basic SPP and PS2 modes are supported.
+ *	Support for parallel port IRQ is present.
+ *	Hardware SPP (a.k.a. compatibility), EPP, and ECP modes are
+ *	supported.
+ *	SPP/ECP FIFO can be driven in PIO or DMA mode.  PIO mode can work with
+ *	or without interrupt support.
+ *
+ *	Hardware ECP mode is not fully implemented (ecp_read_data and
+ *	ecp_write_addr are actually missing).
+ *
+ * To do:
+ *
+ *	Fully implement ECP mode.
+ *	EPP and ECP mode need to be tested.  I currently do not own any
+ *	peripheral supporting these extended mode, and cannot test them.
+ *	If DMA mode works well, decide if support for PIO FIFO modes should be
+ *	dropped.
+ *	Use the io{read,write} family functions when they become available in
+ *	the linux-mips.org tree.  Note: the MIPS specific functions readsb()
+ *	and writesb() are to be translated by ioread8_rep() and iowrite8_rep()
+ *	respectively.
+ */
+
+/* The built-in parallel port on the SGI 02 workstation (a.k.a. IP32) is an
+ * IEEE 1284 parallel port driven by a Texas Instrument TL16PIR552PH chip[1].
+ * This chip supports SPP, bidirectional, EPP and ECP modes.  It has a 16 byte
+ * FIFO buffer and supports DMA transfers.
+ *
+ * [1] http://focus.ti.com/docs/prod/folders/print/tl16pir552.html
+ *
+ * Theoretically, we could simply use the parport_pc module.  It is however
+ * not so simple.  The parport_pc code assumes that the parallel port
+ * registers are port-mapped.  On the O2, they are memory-mapped.
+ * Furthermore, each register is replicated on 256 consecutive addresses (as
+ * it is for the built-in serial ports on the same chip).
+ */
+
+/*--- Some configuration defines ---------------------------------------*/
+
+/* DEBUG_PARPORT_IP32
+ *	0	disable debug
+ *	1	standard level: pr_debug1 is enabled
+ *	2	parport_ip32_dump_state is enabled
+ *	>=3	verbose level: pr_debug is enabled
+ */
+#if !defined(DEBUG_PARPORT_IP32)
+#	define DEBUG_PARPORT_IP32  0	/* 0 (disabled) for production */
+#endif
+
+/*----------------------------------------------------------------------*/
+
+/* Setup DEBUG macros.  This is done before any includes, just in case we
+ * activate pr_debug() with DEBUG_PARPORT_IP32 >= 3.
+ */
+#if DEBUG_PARPORT_IP32 == 1
+#	warning DEBUG_PARPORT_IP32 == 1
+#elif DEBUG_PARPORT_IP32 == 2
+#	warning DEBUG_PARPORT_IP32 == 2
+#elif DEBUG_PARPORT_IP32 >= 3
+#	warning DEBUG_PARPORT_IP32 >= 3
+#	if !defined(DEBUG)
+#		define DEBUG /* enable pr_debug() in kernel.h */
+#	endif
+#endif
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/parport.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/ip32/ip32_ints.h>
+#include <asm/ip32/mace.h>
+
+/*--- Global variables -------------------------------------------------*/
+
+/* Verbose probing on by default for debugging. */
+#if DEBUG_PARPORT_IP32 >= 1
+#	define DEFAULT_VERBOSE_PROBING	1
+#else
+#	define DEFAULT_VERBOSE_PROBING	0
+#endif
+
+/* Default prefix for printk */
+#define PPIP32 "parport_ip32: "
+
+/*
+ * These are the module parameters:
+ * @features:		bit mask of features to enable/disable
+ *			(all enabled by default)
+ * @verbose_probing:	log chit-chat during initialization
+ */
+#define PARPORT_IP32_ENABLE_IRQ	(1U << 0)
+#define PARPORT_IP32_ENABLE_DMA	(1U << 1)
+#define PARPORT_IP32_ENABLE_SPP	(1U << 2)
+#define PARPORT_IP32_ENABLE_EPP	(1U << 3)
+#define PARPORT_IP32_ENABLE_ECP	(1U << 4)
+static unsigned int features =	~0U;
+static int verbose_probing =	DEFAULT_VERBOSE_PROBING;
+
+/* We do not support more than one port. */
+static struct parport *this_port = NULL;
+
+/* Timing constants for FIFO modes.  */
+#define FIFO_NFAULT_TIMEOUT	100	/* milliseconds */
+#define FIFO_POLLING_INTERVAL	50	/* microseconds */
+
+/*--- I/O register definitions -----------------------------------------*/
+
+/**
+ * struct parport_ip32_regs - virtual addresses of parallel port registers
+ * @data:	Data Register
+ * @dsr:	Device Status Register
+ * @dcr:	Device Control Register
+ * @eppAddr:	EPP Address Register
+ * @eppData0:	EPP Data Register 0
+ * @eppData1:	EPP Data Register 1
+ * @eppData2:	EPP Data Register 2
+ * @eppData3:	EPP Data Register 3
+ * @ecpAFifo:	ECP Address FIFO
+ * @fifo:	General FIFO register.  The same address is used for:
+ *		- cFifo, the Parallel Port DATA FIFO
+ *		- ecpDFifo, the ECP Data FIFO
+ *		- tFifo, the ECP Test FIFO
+ * @cnfgA:	Configuration Register A
+ * @cnfgB:	Configuration Register B
+ * @ecr:	Extended Control Register
+ */
+struct parport_ip32_regs {
+	void __iomem *data;
+	void __iomem *dsr;
+	void __iomem *dcr;
+	void __iomem *eppAddr;
+	void __iomem *eppData0;
+	void __iomem *eppData1;
+	void __iomem *eppData2;
+	void __iomem *eppData3;
+	void __iomem *ecpAFifo;
+	void __iomem *fifo;
+	void __iomem *cnfgA;
+	void __iomem *cnfgB;
+	void __iomem *ecr;
+};
+
+/* Device Status Register */
+#define DSR_nBUSY		(1U << 7)	/* PARPORT_STATUS_BUSY */
+#define DSR_nACK		(1U << 6)	/* PARPORT_STATUS_ACK */
+#define DSR_PERROR		(1U << 5)	/* PARPORT_STATUS_PAPEROUT */
+#define DSR_SELECT		(1U << 4)	/* PARPORT_STATUS_SELECT */
+#define DSR_nFAULT		(1U << 3)	/* PARPORT_STATUS_ERROR */
+#define DSR_nPRINT		(1U << 2)	/* specific to TL16PIR552 */
+/* #define DSR_reserved		(1U << 1) */
+#define DSR_TIMEOUT		(1U << 0)	/* EPP timeout */
+
+/* Device Control Register */
+/* #define DCR_reserved		(1U << 7) | (1U <<  6) */
+#define DCR_DIR			(1U << 5)	/* direction */
+#define DCR_IRQ			(1U << 4)	/* interrupt on nAck */
+#define DCR_SELECT		(1U << 3)	/* PARPORT_CONTROL_SELECT */
+#define DCR_nINIT		(1U << 2)	/* PARPORT_CONTROL_INIT */
+#define DCR_AUTOFD		(1U << 1)	/* PARPORT_CONTROL_AUTOFD */
+#define DCR_STROBE		(1U << 0)	/* PARPORT_CONTROL_STROBE */
+
+/* ECP Configuration Register A */
+#define CNFGA_IRQ		(1U << 7)
+#define CNFGA_ID_MASK		((1U << 6) | (1U << 5) | (1U << 4))
+#define CNFGA_ID_SHIFT		4
+#define CNFGA_ID_16		(00U << CNFGA_ID_SHIFT)
+#define CNFGA_ID_8		(01U << CNFGA_ID_SHIFT)
+#define CNFGA_ID_32		(02U << CNFGA_ID_SHIFT)
+/* #define CNFGA_reserved	(1U << 3) */
+#define CNFGA_nBYTEINTRANS	(1U << 2)
+#define CNFGA_PWORDLEFT		((1U << 1) | (1U << 0))
+
+/* ECP Configuration Register B */
+#define CNFGB_COMPRESS		(1U << 7)
+#define CNFGB_INTRVAL		(1U << 6)
+#define CNFGB_IRQ_MASK		((1U << 5) | (1U << 4) | (1U << 3))
+#define CNFGB_IRQ_SHIFT		3
+#define CNFGB_DMA_MASK		((1U << 2) | (1U << 1) | (1U << 0))
+#define CNFGB_DMA_SHIFT		0
+
+/* Extended Control Register */
+#define ECR_MODE_MASK		((1U << 7) | (1U << 6) | (1U << 5))
+#define ECR_MODE_SHIFT		5
+#define ECR_MODE_SPP		(00U << ECR_MODE_SHIFT)
+#define ECR_MODE_PS2		(01U << ECR_MODE_SHIFT)
+#define ECR_MODE_PPF		(02U << ECR_MODE_SHIFT)
+#define ECR_MODE_ECP		(03U << ECR_MODE_SHIFT)
+#define ECR_MODE_EPP		(04U << ECR_MODE_SHIFT)
+/* #define ECR_MODE_reserved	(05U << ECR_MODE_SHIFT) */
+#define ECR_MODE_TST		(06U << ECR_MODE_SHIFT)
+#define ECR_MODE_CFG		(07U << ECR_MODE_SHIFT)
+#define ECR_nERRINTR		(1U << 4)
+#define ECR_DMAEN		(1U << 3)
+#define ECR_SERVINTR		(1U << 2)
+#define ECR_F_FULL		(1U << 1)
+#define ECR_F_EMPTY		(1U << 0)
+
+/*--- Private data -----------------------------------------------------*/
+
+/**
+ * enum parport_ip32_irq_mode - operation mode of interrupt handler
+ * @PARPORT_IP32_IRQ_FWD:	forward interrupt to the upper parport layer
+ * @PARPORT_IP32_IRQ_HERE:	interrupt is handled locally
+ */
+enum parport_ip32_irq_mode { PARPORT_IP32_IRQ_FWD, PARPORT_IP32_IRQ_HERE };
+
+/**
+ * struct parport_ip32_private - private stuff for &struct parport
+ * @regs:		register addresses
+ * @dcr_cache:		cached contents of DCR
+ * @dcr_writable:	bit mask of writable DCR bits
+ * @pword:		number of bytes per PWord
+ * @fifo_depth:		number of PWords that FIFO will hold
+ * @readIntrThreshold:	minimum number of PWords we can read
+ *			if we get an interrupt
+ * @writeIntrThreshold:	minimum number of PWords we can write
+ *			if we get an interrupt
+ * @irq_mode:		operation mode of interrupt handler for this port
+ * @irq_complete:	mutex used to wait for an interrupt to occur
+ */
+struct parport_ip32_private {
+	struct parport_ip32_regs	regs;
+	unsigned int			dcr_cache;
+	unsigned int			dcr_writable;
+	unsigned int			pword;
+	unsigned int			fifo_depth;
+	unsigned int			readIntrThreshold;
+	unsigned int			writeIntrThreshold;
+	enum parport_ip32_irq_mode	irq_mode;
+	struct completion		irq_complete;
+};
+
+/*--- Debug code -------------------------------------------------------*/
+
+/*
+ * pr_debug1 - print debug messages
+ *
+ * This is like pr_debug(), but is defined for %DEBUG_PARPORT_IP32 >= 1
+ */
+#if DEBUG_PARPORT_IP32 >= 1
+#	define pr_debug1(...)	printk(KERN_DEBUG __VA_ARGS__)
+#else /* DEBUG_PARPORT_IP32 < 1 */
+#	define pr_debug1(...)	do { } while (0)
+#endif
+
+/*
+ * pr_trace, pr_trace1 - trace function calls
+ * @p:		pointer to &struct parport
+ * @fmt:	printk format string
+ * @...:	parameters for format string
+ *
+ * Macros used to trace function calls.  The given string is formatted after
+ * function name.  pr_trace() uses pr_debug(), and pr_trace1() uses
+ * pr_debug1().  __pr_trace() is the low-level macro and is not to be used
+ * directly.
+ */
+#define __pr_trace(pr, p, fmt, ...)					\
+	pr("%s: %s" fmt "\n",						\
+	   ({ const struct parport *__p = (p);				\
+		   __p ? __p->name : "parport_ip32"; }),		\
+	   __func__ , ##__VA_ARGS__)
+#define pr_trace(p, fmt, ...)	__pr_trace(pr_debug, p, fmt , ##__VA_ARGS__)
+#define pr_trace1(p, fmt, ...)	__pr_trace(pr_debug1, p, fmt , ##__VA_ARGS__)
+
+/*
+ * __pr_probe, pr_probe - print message if @verbose_probing is true
+ * @p:		pointer to &struct parport
+ * @fmt:	printk format string
+ * @...:	parameters for format string
+ *
+ * For new lines, use pr_probe().  Use __pr_probe() for continued lines.
+ */
+#define __pr_probe(...)							\
+	do { if (verbose_probing) printk(__VA_ARGS__); } while (0)
+#define pr_probe(p, fmt, ...)						\
+	__pr_probe(KERN_INFO PPIP32 "0x%lx: " fmt, (p)->base , ##__VA_ARGS__)
+
+/*
+ * parport_ip32_dump_state - print register status of parport
+ * @p:		pointer to &struct parport
+ * @str:	string to add in message
+ * @show_ecp_config:	shall we dump ECP configuration registers too?
+ *
+ * This function is only here for debugging purpose, and should be used with
+ * care.  Reading the parallel port registers may have undesired side effects.
+ * Especially if @show_ecp_config is true, the parallel port is resetted.
+ * This function is only defined if %DEBUG_PARPORT_IP32 >= 2.
+ */
+#if DEBUG_PARPORT_IP32 >= 2
+static void parport_ip32_dump_state(struct parport *p, char *str,
+				    unsigned int show_ecp_config)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	unsigned int i;
+
+	printk(KERN_DEBUG PPIP32 "%s: state (%s):\n", p->name, str);
+	{
+		static const char ecr_modes[8][4] = {"SPP", "PS2", "PPF",
+						     "ECP", "EPP", "???",
+						     "TST", "CFG"};
+		unsigned int ecr = readb(priv->regs.ecr);
+		printk(KERN_DEBUG PPIP32 "    ecr=0x%02x", ecr);
+		printk(" %s",
+		       ecr_modes[(ecr & ECR_MODE_MASK) >> ECR_MODE_SHIFT]);
+		if (ecr & ECR_nERRINTR)
+			printk(",nErrIntrEn");
+		if (ecr & ECR_DMAEN)
+			printk(",dmaEn");
+		if (ecr & ECR_SERVINTR)
+			printk(",serviceIntr");
+		if (ecr & ECR_F_FULL)
+			printk(",f_full");
+		if (ecr & ECR_F_EMPTY)
+			printk(",f_empty");
+		printk("\n");
+	}
+	if (show_ecp_config) {
+		unsigned int oecr, cnfgA, cnfgB;
+		oecr = readb(priv->regs.ecr);
+		writeb(ECR_MODE_PS2, priv->regs.ecr);
+		writeb(ECR_MODE_CFG, priv->regs.ecr);
+		cnfgA = readb(priv->regs.cnfgA);
+		cnfgB = readb(priv->regs.cnfgB);
+		writeb(ECR_MODE_PS2, priv->regs.ecr);
+		writeb(oecr, priv->regs.ecr);
+		printk(KERN_DEBUG PPIP32 "    cnfgA=0x%02x", cnfgA);
+		printk(" ISA-%s", (cnfgA & CNFGA_IRQ) ? "Level" : "Pulses");
+		switch (cnfgA & CNFGA_ID_MASK) {
+		case CNFGA_ID_8:
+			printk(",8 bits");
+			break;
+		case CNFGA_ID_16:
+			printk(",16 bits");
+			break;
+		case CNFGA_ID_32:
+			printk(",32 bits");
+			break;
+		default:
+			printk(",unknown ID");
+			break;
+		}
+		if (!(cnfgA & CNFGA_nBYTEINTRANS))
+			printk(",ByteInTrans");
+		if ((cnfgA & CNFGA_ID_MASK) != CNFGA_ID_8)
+			printk(",%d byte%s left", cnfgA & CNFGA_PWORDLEFT,
+			       ((cnfgA & CNFGA_PWORDLEFT) > 1) ? "s" : "");
+		printk("\n");
+		printk(KERN_DEBUG PPIP32 "    cnfgB=0x%02x", cnfgB);
+		printk(" irq=%u,dma=%u",
+		       (cnfgB & CNFGB_IRQ_MASK) >> CNFGB_IRQ_SHIFT,
+		       (cnfgB & CNFGB_DMA_MASK) >> CNFGB_DMA_SHIFT);
+		printk(",intrValue=%d", !!(cnfgB & CNFGB_INTRVAL));
+		if (cnfgB & CNFGB_COMPRESS)
+			printk(",compress");
+		printk("\n");
+	}
+	for (i = 0; i < 2; i++) {
+		unsigned int dcr = i ? priv->dcr_cache : readb(priv->regs.dcr);
+		printk(KERN_DEBUG PPIP32 "    dcr(%s)=0x%02x",
+		       i ? "soft" : "hard", dcr);
+		printk(" %s", (dcr & DCR_DIR) ? "rev" : "fwd");
+		if (dcr & DCR_IRQ)
+			printk(",ackIntEn");
+		if (!(dcr & DCR_SELECT))
+			printk(",nSelectIn");
+		if (dcr & DCR_nINIT)
+			printk(",nInit");
+		if (!(dcr & DCR_AUTOFD))
+			printk(",nAutoFD");
+		if (!(dcr & DCR_STROBE))
+			printk(",nStrobe");
+		printk("\n");
+	}
+#define sep (f++ ? ',' : ' ')
+	{
+		unsigned int f = 0;
+		unsigned int dsr = readb(priv->regs.dsr);
+		printk(KERN_DEBUG PPIP32 "    dsr=0x%02x", dsr);
+		if (!(dsr & DSR_nBUSY))
+			printk("%cBusy", sep);
+		if (dsr & DSR_nACK)
+			printk("%cnAck", sep);
+		if (dsr & DSR_PERROR)
+			printk("%cPError", sep);
+		if (dsr & DSR_SELECT)
+			printk("%cSelect", sep);
+		if (dsr & DSR_nFAULT)
+			printk("%cnFault", sep);
+		if (!(dsr & DSR_nPRINT))
+			printk("%c(Print)", sep);
+		if (dsr & DSR_TIMEOUT)
+			printk("%cTimeout", sep);
+		printk("\n");
+	}
+#undef sep
+}
+#else /* DEBUG_PARPORT_IP32 < 2 */
+#define parport_ip32_dump_state(...)	do { } while (0)
+#endif
+
+/*
+ * CHECK_EXTRA_BITS - track and log extra bits
+ * @p:		pointer to &struct parport
+ * @b:		byte to inspect
+ * @m:		bit mask of authorized bits
+ *
+ * This is used to track and log extra bits that should not be there in
+ * parport_ip32_write_control() and parport_ip32_frob_control().  It is only
+ * defined if %DEBUG_PARPORT_IP32 >= 1.
+ */
+#if DEBUG_PARPORT_IP32 >= 1
+#define CHECK_EXTRA_BITS(p, b, m)					\
+	do {								\
+		unsigned int __b = (b), __m = (m);			\
+		if (__b & ~__m)						\
+			pr_debug1(PPIP32 "%s: extra bits in %s(%s): "	\
+				  "0x%02x/0x%02x\n",			\
+				  (p)->name, __func__, #b, __b, __m);	\
+	} while (0)
+#else /* DEBUG_PARPORT_IP32 < 1 */
+#define CHECK_EXTRA_BITS(...)	do { } while (0)
+#endif
+
+/*--- IP32 parallel port DMA operations --------------------------------*/
+
+/**
+ * struct parport_ip32_dma_data - private data needed for DMA operation
+ * @dir:	DMA direction (from or to device)
+ * @buf:	buffer physical address
+ * @len:	buffer length
+ * @next:	address of next bytes to DMA transfer
+ * @left:	number of bytes remaining
+ * @ctx:	next context to write (0: context_a; 1: context_b)
+ * @irq_on:	are the DMA IRQs currently enabled?
+ * @lock:	spinlock to protect access to the structure
+ */
+struct parport_ip32_dma_data {
+	enum dma_data_direction		dir;
+	dma_addr_t			buf;
+	dma_addr_t			next;
+	size_t				len;
+	size_t				left;
+	unsigned int			ctx;
+	unsigned int			irq_on;
+	spinlock_t			lock;
+};
+static struct parport_ip32_dma_data parport_ip32_dma;
+
+/**
+ * parport_ip32_dma_setup_context - setup next DMA context
+ * @limit:	maximum data size for the context
+ *
+ * The alignment constraints must be verified in caller function, and the
+ * parameter @limit must be set accordingly.
+ */
+static void parport_ip32_dma_setup_context(unsigned int limit)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&parport_ip32_dma.lock, flags);
+	if (parport_ip32_dma.left > 0) {
+		/* Note: ctxreg is "volatile" here only because
+		 * mace->perif.ctrl.parport.context_a and context_b are
+		 * "volatile".  */
+		volatile u64 __iomem *ctxreg = (parport_ip32_dma.ctx == 0) ?
+			&mace->perif.ctrl.parport.context_a :
+			&mace->perif.ctrl.parport.context_b;
+		u64 count;
+		u64 ctxval;
+		if (parport_ip32_dma.left <= limit) {
+			count = parport_ip32_dma.left;
+			ctxval = MACEPAR_CONTEXT_LASTFLAG;
+		} else {
+			count = limit;
+			ctxval = 0;
+		}
+
+		pr_trace(NULL,
+			 "(%u): 0x%04x:0x%04x, %u -> %u%s",
+			 limit,
+			 (unsigned int)parport_ip32_dma.buf,
+			 (unsigned int)parport_ip32_dma.next,
+			 (unsigned int)count,
+			 parport_ip32_dma.ctx, ctxval ? "*" : "");
+
+		ctxval |= parport_ip32_dma.next &
+			MACEPAR_CONTEXT_BASEADDR_MASK;
+		ctxval |= ((count - 1) << MACEPAR_CONTEXT_DATALEN_SHIFT) &
+			MACEPAR_CONTEXT_DATALEN_MASK;
+		writeq(ctxval, ctxreg);
+		parport_ip32_dma.next += count;
+		parport_ip32_dma.left -= count;
+		parport_ip32_dma.ctx ^= 1U;
+	}
+	/* If there is nothing more to send, disable IRQs to avoid to
+	 * face an IRQ storm which can lock the machine.  Disable them
+	 * only once. */
+	if (parport_ip32_dma.left == 0 && parport_ip32_dma.irq_on) {
+		pr_debug(PPIP32 "IRQ off (ctx)\n");
+		disable_irq_nosync(MACEISA_PAR_CTXA_IRQ);
+		disable_irq_nosync(MACEISA_PAR_CTXB_IRQ);
+		parport_ip32_dma.irq_on = 0;
+	}
+	spin_unlock_irqrestore(&parport_ip32_dma.lock, flags);
+}
+
+/**
+ * parport_ip32_dma_interrupt - DMA interrupt handler
+ * @irq:	interrupt number
+ * @dev_id:	unused
+ * @regs:	pointer to &struct pt_regs
+ */
+static irqreturn_t parport_ip32_dma_interrupt(int irq, void *dev_id,
+					      struct pt_regs *regs)
+{
+	if (parport_ip32_dma.left)
+		pr_trace(NULL, "(%d): ctx=%d", irq, parport_ip32_dma.ctx);
+	parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND);
+	return IRQ_HANDLED;
+}
+
+#if DEBUG_PARPORT_IP32
+static irqreturn_t parport_ip32_merr_interrupt(int irq, void *dev_id,
+					       struct pt_regs *regs)
+{
+	pr_trace1(NULL, "(%d)", irq);
+	return IRQ_HANDLED;
+}
+#endif
+
+/**
+ * parport_ip32_dma_start - begins a DMA transfer
+ * @dir:	DMA direction: DMA_TO_DEVICE or DMA_FROM_DEVICE
+ * @addr:	pointer to data buffer
+ * @count:	buffer size
+ *
+ * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be
+ * correctly balanced.
+ */
+static int parport_ip32_dma_start(enum dma_data_direction dir,
+				  void *addr, size_t count)
+{
+	unsigned int limit;
+	u64 ctrl;
+
+	pr_trace(NULL, "(%d, %lu)", dir, (unsigned long)count);
+
+	/* FIXME - add support for DMA_FROM_DEVICE.  In this case, buffer must
+	 * be 64 bytes aligned. */
+	BUG_ON(dir != DMA_TO_DEVICE);
+
+	/* Reset DMA controller */
+	ctrl = MACEPAR_CTLSTAT_RESET;
+	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+
+	/* DMA IRQs should normally be enabled */
+	if (!parport_ip32_dma.irq_on) {
+		WARN_ON(1);
+		enable_irq(MACEISA_PAR_CTXA_IRQ);
+		enable_irq(MACEISA_PAR_CTXB_IRQ);
+		parport_ip32_dma.irq_on = 1;
+	}
+
+	/* Prepare DMA pointers */
+	parport_ip32_dma.dir = dir;
+	parport_ip32_dma.buf = dma_map_single(NULL, addr, count, dir);
+	parport_ip32_dma.len = count;
+	parport_ip32_dma.next = parport_ip32_dma.buf;
+	parport_ip32_dma.left = parport_ip32_dma.len;
+	parport_ip32_dma.ctx = 0;
+
+	/* Setup DMA direction and first two contexts */
+	ctrl = (dir == DMA_TO_DEVICE) ? 0 : MACEPAR_CTLSTAT_DIRECTION;
+	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+	/* Single transfer should not cross a 4K page boundary */
+	limit = MACEPAR_CONTEXT_DATA_BOUND -
+		(parport_ip32_dma.next & (MACEPAR_CONTEXT_DATA_BOUND - 1));
+	parport_ip32_dma_setup_context(limit);
+	parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND);
+
+	/* Real start of DMA transfer */
+	ctrl |= MACEPAR_CTLSTAT_ENABLE;
+	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+
+	return 0;
+}
+
+/**
+ * parport_ip32_dma_stop - ends a running DMA transfer
+ *
+ * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be
+ * correctly balanced.
+ */
+static void parport_ip32_dma_stop(void)
+{
+	u64 ctx_a;
+	u64 ctx_b;
+	u64 ctrl;
+	u64 diag;
+	size_t res[2];	/* {[0] = res_a, [1] = res_b} */
+
+	pr_trace(NULL, "()");
+
+	/* Disable IRQs */
+	spin_lock_irq(&parport_ip32_dma.lock);
+	if (parport_ip32_dma.irq_on) {
+		pr_debug(PPIP32 "IRQ off (stop)\n");
+		disable_irq_nosync(MACEISA_PAR_CTXA_IRQ);
+		disable_irq_nosync(MACEISA_PAR_CTXB_IRQ);
+		parport_ip32_dma.irq_on = 0;
+	}
+	spin_unlock_irq(&parport_ip32_dma.lock);
+	/* Force IRQ synchronization, even if the IRQs were disabled
+	 * elsewhere. */
+	synchronize_irq(MACEISA_PAR_CTXA_IRQ);
+	synchronize_irq(MACEISA_PAR_CTXB_IRQ);
+
+	/* Stop DMA transfer */
+	ctrl = readq(&mace->perif.ctrl.parport.cntlstat);
+	ctrl &= ~MACEPAR_CTLSTAT_ENABLE;
+	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+
+	/* Adjust residue (parport_ip32_dma.left) */
+	ctx_a = readq(&mace->perif.ctrl.parport.context_a);
+	ctx_b = readq(&mace->perif.ctrl.parport.context_b);
+	ctrl = readq(&mace->perif.ctrl.parport.cntlstat);
+	diag = readq(&mace->perif.ctrl.parport.diagnostic);
+	res[0] = (ctrl & MACEPAR_CTLSTAT_CTXA_VALID) ?
+		1 + ((ctx_a & MACEPAR_CONTEXT_DATALEN_MASK) >>
+		     MACEPAR_CONTEXT_DATALEN_SHIFT) :
+		0;
+	res[1] = (ctrl & MACEPAR_CTLSTAT_CTXB_VALID) ?
+		1 + ((ctx_b & MACEPAR_CONTEXT_DATALEN_MASK) >>
+		     MACEPAR_CONTEXT_DATALEN_SHIFT) :
+		0;
+	if (diag & MACEPAR_DIAG_DMACTIVE)
+		res[(diag & MACEPAR_DIAG_CTXINUSE) != 0] =
+			1 + ((diag & MACEPAR_DIAG_CTRMASK) >>
+			     MACEPAR_DIAG_CTRSHIFT);
+	parport_ip32_dma.left += res[0] + res[1];
+
+	/* Reset DMA controller, and re-enable IRQs */
+	ctrl = MACEPAR_CTLSTAT_RESET;
+	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+	pr_debug(PPIP32 "IRQ on (stop)\n");
+	enable_irq(MACEISA_PAR_CTXA_IRQ);
+	enable_irq(MACEISA_PAR_CTXB_IRQ);
+	parport_ip32_dma.irq_on = 1;
+
+	dma_unmap_single(NULL, parport_ip32_dma.buf, parport_ip32_dma.len,
+			 parport_ip32_dma.dir);
+}
+
+/**
+ * parport_ip32_dma_get_residue - get residue from last DMA transfer
+ *
+ * Returns the number of bytes remaining from last DMA transfer.
+ */
+static inline size_t parport_ip32_dma_get_residue(void)
+{
+	return parport_ip32_dma.left;
+}
+
+/**
+ * parport_ip32_dma_register - initialize DMA engine
+ *
+ * Returns zero for success.
+ */
+static int parport_ip32_dma_register(void)
+{
+	int err;
+
+	spin_lock_init(&parport_ip32_dma.lock);
+	parport_ip32_dma.irq_on = 1;
+
+	/* Reset DMA controller */
+	writeq(MACEPAR_CTLSTAT_RESET, &mace->perif.ctrl.parport.cntlstat);
+
+	/* Request IRQs */
+	err = request_irq(MACEISA_PAR_CTXA_IRQ, parport_ip32_dma_interrupt,
+			  0, "parport_ip32", NULL);
+	if (err)
+		goto fail_a;
+	err = request_irq(MACEISA_PAR_CTXB_IRQ, parport_ip32_dma_interrupt,
+			  0, "parport_ip32", NULL);
+	if (err)
+		goto fail_b;
+#if DEBUG_PARPORT_IP32
+	/* FIXME - what is this IRQ for? */
+	err = request_irq(MACEISA_PAR_MERR_IRQ, parport_ip32_merr_interrupt,
+			  0, "parport_ip32", NULL);
+	if (err)
+		goto fail_merr;
+#endif
+	return 0;
+
+#if DEBUG_PARPORT_IP32
+fail_merr:
+	free_irq(MACEISA_PAR_CTXB_IRQ, NULL);
+#endif
+fail_b:
+	free_irq(MACEISA_PAR_CTXA_IRQ, NULL);
+fail_a:
+	return err;
+}
+
+/**
+ * parport_ip32_dma_unregister - release and free resources for DMA engine
+ */
+static void parport_ip32_dma_unregister(void)
+{
+#if DEBUG_PARPORT_IP32
+	free_irq(MACEISA_PAR_MERR_IRQ, NULL);
+#endif
+	free_irq(MACEISA_PAR_CTXB_IRQ, NULL);
+	free_irq(MACEISA_PAR_CTXA_IRQ, NULL);
+}
+
+/*--- Interrupt handlers and associates --------------------------------*/
+
+/**
+ * parport_ip32_wakeup - wakes up code waiting for an interrupt
+ * @p:		pointer to &struct parport
+ */
+static inline void parport_ip32_wakeup(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	complete(&priv->irq_complete);
+}
+
+/**
+ * parport_ip32_interrupt - interrupt handler
+ * @irq:	interrupt number
+ * @dev_id:	pointer to &struct parport
+ * @regs:	pointer to &struct pt_regs
+ *
+ * Caught interrupts are forwarded to the upper parport layer if IRQ_mode is
+ * %PARPORT_IP32_IRQ_FWD.
+ */
+static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id,
+					  struct pt_regs *regs)
+{
+	struct parport * const p = dev_id;
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	enum parport_ip32_irq_mode irq_mode = priv->irq_mode;
+	switch (irq_mode) {
+	case PARPORT_IP32_IRQ_FWD:
+		parport_generic_irq(irq, p, regs);
+		break;
+	case PARPORT_IP32_IRQ_HERE:
+		parport_ip32_wakeup(p);
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+/*--- Some utility function to manipulate ECR register -----------------*/
+
+/**
+ * parport_ip32_read_econtrol - read contents of the ECR register
+ * @p:		pointer to &struct parport
+ */
+static inline unsigned int parport_ip32_read_econtrol(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	return readb(priv->regs.ecr);
+}
+
+/**
+ * parport_ip32_write_econtrol - write new contents to the ECR register
+ * @p:		pointer to &struct parport
+ * @c:		new value to write
+ */
+static inline void parport_ip32_write_econtrol(struct parport *p,
+					       unsigned int c)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	writeb(c, priv->regs.ecr);
+}
+
+/**
+ * parport_ip32_frob_econtrol - change bits from the ECR register
+ * @p:		pointer to &struct parport
+ * @mask:	bit mask of bits to change
+ * @val:	new value for changed bits
+ *
+ * Read from the ECR, mask out the bits in @mask, exclusive-or with the bits
+ * in @val, and write the result to the ECR.
+ */
+static inline void parport_ip32_frob_econtrol(struct parport *p,
+					      unsigned int mask,
+					      unsigned int val)
+{
+	unsigned int c;
+	c = (parport_ip32_read_econtrol(p) & ~mask) ^ val;
+	parport_ip32_write_econtrol(p, c);
+}
+
+/**
+ * parport_ip32_set_mode - change mode of ECP port
+ * @p:		pointer to &struct parport
+ * @mode:	new mode to write in ECR
+ *
+ * ECR is reset in a sane state (interrupts and DMA disabled), and placed in
+ * mode @mode.  Go through PS2 mode if needed.
+ */
+static void parport_ip32_set_mode(struct parport *p, unsigned int mode)
+{
+	unsigned int omode;
+
+	mode &= ECR_MODE_MASK;
+	omode = parport_ip32_read_econtrol(p) & ECR_MODE_MASK;
+
+	if (!(mode == ECR_MODE_SPP || mode == ECR_MODE_PS2
+	      || omode == ECR_MODE_SPP || omode == ECR_MODE_PS2)) {
+		/* We have to go through PS2 mode */
+		unsigned int ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR;
+		parport_ip32_write_econtrol(p, ecr);
+	}
+	parport_ip32_write_econtrol(p, mode | ECR_nERRINTR | ECR_SERVINTR);
+}
+
+/*--- Basic functions needed for parport -------------------------------*/
+
+/**
+ * parport_ip32_read_data - return current contents of the DATA register
+ * @p:		pointer to &struct parport
+ */
+static inline unsigned char parport_ip32_read_data(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	return readb(priv->regs.data);
+}
+
+/**
+ * parport_ip32_write_data - set new contents for the DATA register
+ * @p:		pointer to &struct parport
+ * @d:		new value to write
+ */
+static inline void parport_ip32_write_data(struct parport *p, unsigned char d)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	writeb(d, priv->regs.data);
+}
+
+/**
+ * parport_ip32_read_status - return current contents of the DSR register
+ * @p:		pointer to &struct parport
+ */
+static inline unsigned char parport_ip32_read_status(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	return readb(priv->regs.dsr);
+}
+
+/**
+ * __parport_ip32_read_control - return cached contents of the DCR register
+ * @p:		pointer to &struct parport
+ */
+static inline unsigned int __parport_ip32_read_control(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	return priv->dcr_cache; /* use soft copy */
+}
+
+/**
+ * __parport_ip32_write_control - set new contents for the DCR register
+ * @p:		pointer to &struct parport
+ * @c:		new value to write
+ */
+static inline void __parport_ip32_write_control(struct parport *p,
+						unsigned int c)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	CHECK_EXTRA_BITS(p, c, priv->dcr_writable);
+	c &= priv->dcr_writable; /* only writable bits */
+	writeb(c, priv->regs.dcr);
+	priv->dcr_cache = c;		/* update soft copy */
+}
+
+/**
+ * __parport_ip32_frob_control - change bits from the DCR register
+ * @p:		pointer to &struct parport
+ * @mask:	bit mask of bits to change
+ * @val:	new value for changed bits
+ *
+ * This is equivalent to read from the DCR, mask out the bits in @mask,
+ * exclusive-or with the bits in @val, and write the result to the DCR.
+ * Actually, the cached contents of the DCR is used.
+ */
+static inline void __parport_ip32_frob_control(struct parport *p,
+					       unsigned int mask,
+					       unsigned int val)
+{
+	unsigned int c;
+	c = (__parport_ip32_read_control(p) & ~mask) ^ val;
+	__parport_ip32_write_control(p, c);
+}
+
+/**
+ * parport_ip32_read_control - return cached contents of the DCR register
+ * @p:		pointer to &struct parport
+ *
+ * The return value is masked so as to only return the value of %DCR_STROBE,
+ * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT.
+ */
+static inline unsigned char parport_ip32_read_control(struct parport *p)
+{
+	const unsigned int rm =
+		DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT;
+	return __parport_ip32_read_control(p) & rm;
+}
+
+/**
+ * parport_ip32_write_control - set new contents for the DCR register
+ * @p:		pointer to &struct parport
+ * @c:		new value to write
+ *
+ * The value is masked so as to only change the value of %DCR_STROBE,
+ * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT.
+ */
+static inline void parport_ip32_write_control(struct parport *p,
+					      unsigned char c)
+{
+	const unsigned int wm =
+		DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT;
+	CHECK_EXTRA_BITS(p, c, wm);
+	__parport_ip32_frob_control(p, wm, c & wm);
+}
+
+/**
+ * parport_ip32_frob_control - change bits from the DCR register
+ * @p:		pointer to &struct parport
+ * @mask:	bit mask of bits to change
+ * @val:	new value for changed bits
+ *
+ * This differs from __parport_ip32_frob_control() in that it only allows to
+ * change the value of %DCR_STROBE, %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT.
+ */
+static inline unsigned char parport_ip32_frob_control(struct parport *p,
+						      unsigned char mask,
+						      unsigned char val)
+{
+	const unsigned int wm =
+		DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT;
+	CHECK_EXTRA_BITS(p, mask, wm);
+	CHECK_EXTRA_BITS(p, val, wm);
+	__parport_ip32_frob_control(p, mask & wm, val & wm);
+	return parport_ip32_read_control(p);
+}
+
+/**
+ * parport_ip32_disable_irq - disable interrupts on the rising edge of nACK
+ * @p:		pointer to &struct parport
+ */
+static inline void parport_ip32_disable_irq(struct parport *p)
+{
+	__parport_ip32_frob_control(p, DCR_IRQ, 0);
+}
+
+/**
+ * parport_ip32_enable_irq - enable interrupts on the rising edge of nACK
+ * @p:		pointer to &struct parport
+ */
+static inline void parport_ip32_enable_irq(struct parport *p)
+{
+	__parport_ip32_frob_control(p, DCR_IRQ, DCR_IRQ);
+}
+
+/**
+ * parport_ip32_data_forward - enable host-to-peripheral communications
+ * @p:		pointer to &struct parport
+ *
+ * Enable the data line drivers, for 8-bit host-to-peripheral communications.
+ */
+static inline void parport_ip32_data_forward(struct parport *p)
+{
+	__parport_ip32_frob_control(p, DCR_DIR, 0);
+}
+
+/**
+ * parport_ip32_data_reverse - enable peripheral-to-host communications
+ * @p:		pointer to &struct parport
+ *
+ * Place the data bus in a high impedance state, if @p->modes has the
+ * PARPORT_MODE_TRISTATE bit set.
+ */
+static inline void parport_ip32_data_reverse(struct parport *p)
+{
+	__parport_ip32_frob_control(p, DCR_DIR, DCR_DIR);
+}
+
+/**
+ * parport_ip32_init_state - for core parport code
+ * @dev:	pointer to &struct pardevice
+ * @s:		pointer to &struct parport_state to initialize
+ */
+static void parport_ip32_init_state(struct pardevice *dev,
+				    struct parport_state *s)
+{
+	s->u.ip32.dcr = DCR_SELECT | DCR_nINIT;
+	s->u.ip32.ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR;
+}
+
+/**
+ * parport_ip32_save_state - for core parport code
+ * @p:		pointer to &struct parport
+ * @s:		pointer to &struct parport_state to save state to
+ */
+static void parport_ip32_save_state(struct parport *p,
+				    struct parport_state *s)
+{
+	s->u.ip32.dcr = __parport_ip32_read_control(p);
+	s->u.ip32.ecr = parport_ip32_read_econtrol(p);
+}
+
+/**
+ * parport_ip32_restore_state - for core parport code
+ * @p:		pointer to &struct parport
+ * @s:		pointer to &struct parport_state to restore state from
+ */
+static void parport_ip32_restore_state(struct parport *p,
+				       struct parport_state *s)
+{
+	parport_ip32_set_mode(p, s->u.ip32.ecr & ECR_MODE_MASK);
+	parport_ip32_write_econtrol(p, s->u.ip32.ecr);
+	__parport_ip32_write_control(p, s->u.ip32.dcr);
+}
+
+/*--- EPP mode functions -----------------------------------------------*/
+
+/**
+ * parport_ip32_clear_epp_timeout - clear Timeout bit in EPP mode
+ * @p:		pointer to &struct parport
+ *
+ * Returns 1 if the Timeout bit is clear, and 0 otherwise.
+ */
+static unsigned int parport_ip32_clear_epp_timeout(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	unsigned int cleared;
+
+	if (!(parport_ip32_read_status(p) & DSR_TIMEOUT))
+		cleared = 1;
+	else {
+		unsigned int r;
+		/* To clear timeout some chips require double read */
+		parport_ip32_read_status(p);
+		r = parport_ip32_read_status(p);
+		/* Some reset by writing 1 */
+		writeb(r | DSR_TIMEOUT, priv->regs.dsr);
+		/* Others by writing 0 */
+		writeb(r & ~DSR_TIMEOUT, priv->regs.dsr);
+
+		r = parport_ip32_read_status(p);
+		cleared = !(r & DSR_TIMEOUT);
+	}
+
+	pr_trace(p, "(): %s", cleared ? "cleared" : "failed");
+	return cleared;
+}
+
+/**
+ * parport_ip32_epp_read - generic EPP read function
+ * @eppreg:	I/O register to read from
+ * @p:		pointer to &struct parport
+ * @buf:	buffer to store read data
+ * @len:	length of buffer @buf
+ * @flags:	may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_read(void __iomem *eppreg,
+				    struct parport *p, void *buf,
+				    size_t len, int flags)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	size_t got;
+	parport_ip32_set_mode(p, ECR_MODE_EPP);
+	parport_ip32_data_reverse(p);
+	parport_ip32_write_control(p, DCR_nINIT);
+	if ((flags & PARPORT_EPP_FAST) && (len > 1)) {
+		readsb(eppreg, buf, len);
+		if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
+			parport_ip32_clear_epp_timeout(p);
+			return -EIO;
+		}
+		got = len;
+	} else {
+		u8 *bufp = buf;
+		for (got = 0; got < len; got++) {
+			*bufp++ = readb(eppreg);
+			if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
+				parport_ip32_clear_epp_timeout(p);
+				break;
+			}
+		}
+	}
+	parport_ip32_data_forward(p);
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	return got;
+}
+
+/**
+ * parport_ip32_epp_write - generic EPP write function
+ * @eppreg:	I/O register to write to
+ * @p:		pointer to &struct parport
+ * @buf:	buffer of data to write
+ * @len:	length of buffer @buf
+ * @flags:	may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_write(void __iomem *eppreg,
+				     struct parport *p, const void *buf,
+				     size_t len, int flags)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	size_t written;
+	parport_ip32_set_mode(p, ECR_MODE_EPP);
+	parport_ip32_data_forward(p);
+	parport_ip32_write_control(p, DCR_nINIT);
+	if ((flags & PARPORT_EPP_FAST) && (len > 1)) {
+		writesb(eppreg, buf, len);
+		if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
+			parport_ip32_clear_epp_timeout(p);
+			return -EIO;
+		}
+		written = len;
+	} else {
+		const u8 *bufp = buf;
+		for (written = 0; written < len; written++) {
+			writeb(*bufp++, eppreg);
+			if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
+				parport_ip32_clear_epp_timeout(p);
+				break;
+			}
+		}
+	}
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	return written;
+}
+
+/**
+ * parport_ip32_epp_read_data - read a block of data in EPP mode
+ * @p:		pointer to &struct parport
+ * @buf:	buffer to store read data
+ * @len:	length of buffer @buf
+ * @flags:	may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_read_data(struct parport *p, void *buf,
+					 size_t len, int flags)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	return parport_ip32_epp_read(priv->regs.eppData0, p, buf, len, flags);
+}
+
+/**
+ * parport_ip32_epp_write_data - write a block of data in EPP mode
+ * @p:		pointer to &struct parport
+ * @buf:	buffer of data to write
+ * @len:	length of buffer @buf
+ * @flags:	may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_write_data(struct parport *p, const void *buf,
+					  size_t len, int flags)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	return parport_ip32_epp_write(priv->regs.eppData0, p, buf, len, flags);
+}
+
+/**
+ * parport_ip32_epp_read_addr - read a block of addresses in EPP mode
+ * @p:		pointer to &struct parport
+ * @buf:	buffer to store read data
+ * @len:	length of buffer @buf
+ * @flags:	may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_read_addr(struct parport *p, void *buf,
+					 size_t len, int flags)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	return parport_ip32_epp_read(priv->regs.eppAddr, p, buf, len, flags);
+}
+
+/**
+ * parport_ip32_epp_write_addr - write a block of addresses in EPP mode
+ * @p:		pointer to &struct parport
+ * @buf:	buffer of data to write
+ * @len:	length of buffer @buf
+ * @flags:	may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_write_addr(struct parport *p, const void *buf,
+					  size_t len, int flags)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	return parport_ip32_epp_write(priv->regs.eppAddr, p, buf, len, flags);
+}
+
+/*--- ECP mode functions (FIFO) ----------------------------------------*/
+
+/**
+ * parport_ip32_fifo_wait_break - check if the waiting function should return
+ * @p:		pointer to &struct parport
+ * @expire:	timeout expiring date, in jiffies
+ *
+ * parport_ip32_fifo_wait_break() checks if the waiting function should return
+ * immediately or not.  The break conditions are:
+ *	- expired timeout;
+ *	- a pending signal;
+ *	- nFault asserted low.
+ * This function also calls cond_resched().
+ */
+static unsigned int parport_ip32_fifo_wait_break(struct parport *p,
+						 unsigned long expire)
+{
+	cond_resched();
+	if (time_after(jiffies, expire)) {
+		pr_debug1(PPIP32 "%s: FIFO write timed out\n", p->name);
+		return 1;
+	}
+	if (signal_pending(current)) {
+		pr_debug1(PPIP32 "%s: Signal pending\n", p->name);
+		return 1;
+	}
+	if (!(parport_ip32_read_status(p) & DSR_nFAULT)) {
+		pr_debug1(PPIP32 "%s: nFault asserted low\n", p->name);
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * parport_ip32_fwp_wait_polling - wait for FIFO to empty (polling)
+ * @p:		pointer to &struct parport
+ *
+ * Returns the number of bytes that can safely be written in the FIFO.  A
+ * return value of zero means that the calling function should terminate as
+ * fast as possible.
+ */
+static unsigned int parport_ip32_fwp_wait_polling(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	struct parport * const physport = p->physport;
+	unsigned long expire;
+	unsigned int count;
+	unsigned int ecr;
+
+	expire = jiffies + physport->cad->timeout;
+	count = 0;
+	while (1) {
+		if (parport_ip32_fifo_wait_break(p, expire))
+			break;
+
+		/* Check FIFO state.  We do nothing when the FIFO is nor full,
+		 * nor empty.  It appears that the FIFO full bit is not always
+		 * reliable, the FIFO state is sometimes wrongly reported, and
+		 * the chip gets confused if we give it another byte. */
+		ecr = parport_ip32_read_econtrol(p);
+		if (ecr & ECR_F_EMPTY) {
+			/* FIFO is empty, fill it up */
+			count = priv->fifo_depth;
+			break;
+		}
+
+		/* Wait a moment... */
+		udelay(FIFO_POLLING_INTERVAL);
+	} /* while (1) */
+
+	return count;
+}
+
+/**
+ * parport_ip32_fwp_wait_interrupt - wait for FIFO to empty (interrupt-driven)
+ * @p:		pointer to &struct parport
+ *
+ * Returns the number of bytes that can safely be written in the FIFO.  A
+ * return value of zero means that the calling function should terminate as
+ * fast as possible.
+ */
+static unsigned int parport_ip32_fwp_wait_interrupt(struct parport *p)
+{
+	static unsigned int lost_interrupt = 0;
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	struct parport * const physport = p->physport;
+	unsigned long nfault_timeout;
+	unsigned long expire;
+	unsigned int count;
+	unsigned int ecr;
+
+	nfault_timeout = min((unsigned long)physport->cad->timeout,
+			     msecs_to_jiffies(FIFO_NFAULT_TIMEOUT));
+	expire = jiffies + physport->cad->timeout;
+	count = 0;
+	while (1) {
+		if (parport_ip32_fifo_wait_break(p, expire))
+			break;
+
+		/* Initialize mutex used to take interrupts into account */
+		INIT_COMPLETION(priv->irq_complete);
+
+		/* Enable serviceIntr */
+		parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0);
+
+		/* Enabling serviceIntr while the FIFO is empty does not
+		 * always generate an interrupt, so check for emptiness
+		 * now. */
+		ecr = parport_ip32_read_econtrol(p);
+		if (!(ecr & ECR_F_EMPTY)) {
+			/* FIFO is not empty: wait for an interrupt or a
+			 * timeout to occur */
+			wait_for_completion_interruptible_timeout(
+				&priv->irq_complete, nfault_timeout);
+			ecr = parport_ip32_read_econtrol(p);
+			if ((ecr & ECR_F_EMPTY) && !(ecr & ECR_SERVINTR)
+			    && !lost_interrupt) {
+				printk(KERN_WARNING PPIP32
+				       "%s: lost interrupt in %s\n",
+				       p->name, __func__);
+				lost_interrupt = 1;
+			}
+		}
+
+		/* Disable serviceIntr */
+		parport_ip32_frob_econtrol(p, ECR_SERVINTR, ECR_SERVINTR);
+
+		/* Check FIFO state */
+		if (ecr & ECR_F_EMPTY) {
+			/* FIFO is empty, fill it up */
+			count = priv->fifo_depth;
+			break;
+		} else if (ecr & ECR_SERVINTR) {
+			/* FIFO is not empty, but we know that can safely push
+			 * writeIntrThreshold bytes into it */
+			count = priv->writeIntrThreshold;
+			break;
+		}
+		/* FIFO is not empty, and we did not get any interrupt.
+		 * Either it's time to check for nFault, or a signal is
+		 * pending.  This is verified in
+		 * parport_ip32_fifo_wait_break(), so we continue the loop. */
+	} /* while (1) */
+
+	return count;
+}
+
+/**
+ * parport_ip32_fifo_write_block_pio - write a block of data (PIO mode)
+ * @p:		pointer to &struct parport
+ * @buf:	buffer of data to write
+ * @len:	length of buffer @buf
+ *
+ * Uses PIO to write the contents of the buffer @buf into the parallel port
+ * FIFO.  Returns the number of bytes that were actually written.  It can work
+ * with or without the help of interrupts.  The parallel port must be
+ * correctly initialized before calling parport_ip32_fifo_write_block_pio().
+ */
+static size_t parport_ip32_fifo_write_block_pio(struct parport *p,
+						const void *buf, size_t len)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	const u8 *bufp = buf;
+	size_t left = len;
+
+	priv->irq_mode = PARPORT_IP32_IRQ_HERE;
+
+	while (left > 0) {
+		unsigned int count;
+
+		count = (p->irq == PARPORT_IRQ_NONE) ?
+			parport_ip32_fwp_wait_polling(p) :
+			parport_ip32_fwp_wait_interrupt(p);
+		if (count == 0)
+			break;	/* Transmission should be stopped */
+		if (count > left)
+			count = left;
+		if (count == 1) {
+			writeb(*bufp, priv->regs.fifo);
+			bufp++, left--;
+		} else {
+			writesb(priv->regs.fifo, bufp, count);
+			bufp += count, left -= count;
+		}
+	}
+
+	priv->irq_mode = PARPORT_IP32_IRQ_FWD;
+
+	return len - left;
+}
+
+/**
+ * parport_ip32_fifo_write_block_dma - write a block of data (DMA mode)
+ * @p:		pointer to &struct parport
+ * @buf:	buffer of data to write
+ * @len:	length of buffer @buf
+ *
+ * Uses DMA to write the contents of the buffer @buf into the parallel port
+ * FIFO.  Returns the number of bytes that were actually written.  The
+ * parallel port must be correctly initialized before calling
+ * parport_ip32_fifo_write_block_dma().
+ */
+static size_t parport_ip32_fifo_write_block_dma(struct parport *p,
+						const void *buf, size_t len)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	struct parport * const physport = p->physport;
+	unsigned long nfault_timeout;
+	unsigned long expire;
+	size_t written;
+	unsigned int ecr;
+
+	priv->irq_mode = PARPORT_IP32_IRQ_HERE;
+
+	parport_ip32_dma_start(DMA_TO_DEVICE, (void *)buf, len);
+	INIT_COMPLETION(priv->irq_complete);
+	parport_ip32_frob_econtrol(p, ECR_DMAEN | ECR_SERVINTR, ECR_DMAEN);
+
+	nfault_timeout = min((unsigned long)physport->cad->timeout,
+			     msecs_to_jiffies(FIFO_NFAULT_TIMEOUT));
+	expire = jiffies + physport->cad->timeout;
+	while (1) {
+		if (parport_ip32_fifo_wait_break(p, expire))
+			break;
+		wait_for_completion_interruptible_timeout(&priv->irq_complete,
+							  nfault_timeout);
+		ecr = parport_ip32_read_econtrol(p);
+		if (ecr & ECR_SERVINTR)
+			break;	/* DMA transfer just finished */
+	}
+	parport_ip32_dma_stop();
+	written = len - parport_ip32_dma_get_residue();
+
+	priv->irq_mode = PARPORT_IP32_IRQ_FWD;
+
+	return written;
+}
+
+/**
+ * parport_ip32_fifo_write_block - write a block of data
+ * @p:		pointer to &struct parport
+ * @buf:	buffer of data to write
+ * @len:	length of buffer @buf
+ *
+ * Uses PIO or DMA to write the contents of the buffer @buf into the parallel
+ * p FIFO.  Returns the number of bytes that were actually written.
+ */
+static size_t parport_ip32_fifo_write_block(struct parport *p,
+					    const void *buf, size_t len)
+{
+	size_t written = 0;
+	if (len)
+		/* FIXME - Maybe some threshold value should be set for @len
+		 * under which we revert to PIO mode? */
+		written = (p->modes & PARPORT_MODE_DMA) ?
+			parport_ip32_fifo_write_block_dma(p, buf, len) :
+			parport_ip32_fifo_write_block_pio(p, buf, len);
+	return written;
+}
+
+/**
+ * parport_ip32_drain_fifo - wait for FIFO to empty
+ * @p:		pointer to &struct parport
+ * @timeout:	timeout, in jiffies
+ *
+ * This function waits for FIFO to empty.  It returns 1 when FIFO is empty, or
+ * 0 if the timeout @timeout is reached before, or if a signal is pending.
+ */
+static unsigned int parport_ip32_drain_fifo(struct parport *p,
+					    unsigned long timeout)
+{
+	unsigned long expire = jiffies + timeout;
+	unsigned int polling_interval;
+	unsigned int counter;
+
+	/* Busy wait for approx. 200us */
+	for (counter = 0; counter < 40; counter++) {
+		if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY)
+			break;
+		if (time_after(jiffies, expire))
+			break;
+		if (signal_pending(current))
+			break;
+		udelay(5);
+	}
+	/* Poll slowly.  Polling interval starts with 1 millisecond, and is
+	 * increased exponentially until 128.  */
+	polling_interval = 1; /* msecs */
+	while (!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY)) {
+		if (time_after_eq(jiffies, expire))
+			break;
+		msleep_interruptible(polling_interval);
+		if (signal_pending(current))
+			break;
+		if (polling_interval < 128)
+			polling_interval *= 2;
+	}
+
+	return !!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY);
+}
+
+/**
+ * parport_ip32_get_fifo_residue - reset FIFO
+ * @p:		pointer to &struct parport
+ * @mode:	current operation mode (ECR_MODE_PPF or ECR_MODE_ECP)
+ *
+ * This function resets FIFO, and returns the number of bytes remaining in it.
+ */
+static unsigned int parport_ip32_get_fifo_residue(struct parport *p,
+						  unsigned int mode)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	unsigned int residue;
+	unsigned int cnfga;
+
+	/* FIXME - We are missing one byte if the printer is off-line.  I
+	 * don't know how to detect this.  It looks that the full bit is not
+	 * always reliable.  For the moment, the problem is avoided in most
+	 * cases by testing for BUSY in parport_ip32_compat_write_data().
+	 */
+	if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY)
+		residue = 0;
+	else {
+		pr_debug1(PPIP32 "%s: FIFO is stuck\n", p->name);
+
+		/* Stop all transfers.
+		 *
+		 * Microsoft's document instructs to drive DCR_STROBE to 0,
+		 * but it doesn't work (at least in Compatibility mode, not
+		 * tested in ECP mode).  Switching directly to Test mode (as
+		 * in parport_pc) is not an option: it does confuse the port,
+		 * ECP service interrupts are no more working after that.  A
+		 * hard reset is then needed to revert to a sane state.
+		 *
+		 * Let's hope that the FIFO is really stuck and that the
+		 * peripheral doesn't wake up now.
+		 */
+		parport_ip32_frob_control(p, DCR_STROBE, 0);
+
+		/* Fill up FIFO */
+		for (residue = priv->fifo_depth; residue > 0; residue--) {
+			if (parport_ip32_read_econtrol(p) & ECR_F_FULL)
+				break;
+			writeb(0x00, priv->regs.fifo);
+		}
+	}
+	if (residue)
+		pr_debug1(PPIP32 "%s: %d PWord%s left in FIFO\n",
+			  p->name, residue,
+			  (residue == 1) ? " was" : "s were");
+
+	/* Now reset the FIFO */
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+
+	/* Host recovery for ECP mode */
+	if (mode == ECR_MODE_ECP) {
+		parport_ip32_data_reverse(p);
+		parport_ip32_frob_control(p, DCR_nINIT, 0);
+		if (parport_wait_peripheral(p, DSR_PERROR, 0))
+			pr_debug1(PPIP32 "%s: PEerror timeout 1 in %s\n",
+				  p->name, __func__);
+		parport_ip32_frob_control(p, DCR_STROBE, DCR_STROBE);
+		parport_ip32_frob_control(p, DCR_nINIT, DCR_nINIT);
+		if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR))
+			pr_debug1(PPIP32 "%s: PEerror timeout 2 in %s\n",
+				  p->name, __func__);
+	}
+
+	/* Adjust residue if needed */
+	parport_ip32_set_mode(p, ECR_MODE_CFG);
+	cnfga = readb(priv->regs.cnfgA);
+	if (!(cnfga & CNFGA_nBYTEINTRANS)) {
+		pr_debug1(PPIP32 "%s: cnfgA contains 0x%02x\n",
+			  p->name, cnfga);
+		pr_debug1(PPIP32 "%s: Accounting for extra byte\n",
+			  p->name);
+		residue++;
+	}
+
+	/* Don't care about partial PWords since we do not support
+	 * PWord != 1 byte. */
+
+	/* Back to forward PS2 mode. */
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	parport_ip32_data_forward(p);
+
+	return residue;
+}
+
+/**
+ * parport_ip32_compat_write_data - write a block of data in SPP mode
+ * @p:		pointer to &struct parport
+ * @buf:	buffer of data to write
+ * @len:	length of buffer @buf
+ * @flags:	ignored
+ */
+static size_t parport_ip32_compat_write_data(struct parport *p,
+					     const void *buf, size_t len,
+					     int flags)
+{
+	static unsigned int ready_before = 1;
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	struct parport * const physport = p->physport;
+	size_t written = 0;
+
+	/* Special case: a timeout of zero means we cannot call schedule().
+	 * Also if O_NONBLOCK is set then use the default implementation. */
+	if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK)
+		return parport_ieee1284_write_compat(p, buf, len, flags);
+
+	/* Reset FIFO, go in forward mode, and disable ackIntEn */
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
+	parport_ip32_data_forward(p);
+	parport_ip32_disable_irq(p);
+	parport_ip32_set_mode(p, ECR_MODE_PPF);
+	physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+
+	/* Wait for peripheral to become ready */
+	if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT,
+				       DSR_nBUSY | DSR_nFAULT)) {
+		/* Avoid to flood the logs */
+		if (ready_before)
+			printk(KERN_INFO PPIP32 "%s: not ready in %s\n",
+			       p->name, __func__);
+		ready_before = 0;
+		goto stop;
+	}
+	ready_before = 1;
+
+	written = parport_ip32_fifo_write_block(p, buf, len);
+
+	/* Wait FIFO to empty.  Timeout is proportional to FIFO_depth.  */
+	parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth);
+
+	/* Check for a potential residue */
+	written -= parport_ip32_get_fifo_residue(p, ECR_MODE_PPF);
+
+	/* Then, wait for BUSY to get low. */
+	if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY))
+		printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n",
+		       p->name, __func__);
+
+stop:
+	/* Reset FIFO */
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+	return written;
+}
+
+/*
+ * FIXME - Insert here parport_ip32_ecp_read_data().
+ */
+
+/**
+ * parport_ip32_ecp_write_data - write a block of data in ECP mode
+ * @p:		pointer to &struct parport
+ * @buf:	buffer of data to write
+ * @len:	length of buffer @buf
+ * @flags:	ignored
+ */
+static size_t parport_ip32_ecp_write_data(struct parport *p,
+					  const void *buf, size_t len,
+					  int flags)
+{
+	static unsigned int ready_before = 1;
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	struct parport * const physport = p->physport;
+	size_t written = 0;
+
+	/* Special case: a timeout of zero means we cannot call schedule().
+	 * Also if O_NONBLOCK is set then use the default implementation. */
+	if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK)
+		return parport_ieee1284_ecp_write_data(p, buf, len, flags);
+
+	/* Negotiate to forward mode if necessary. */
+	if (physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) {
+		/* Event 47: Set nInit high. */
+		parport_ip32_frob_control(p, DCR_nINIT | DCR_AUTOFD,
+					     DCR_nINIT | DCR_AUTOFD);
+
+		/* Event 49: PError goes high. */
+		if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) {
+			printk(KERN_DEBUG PPIP32 "%s: PError timeout in %s",
+			       p->name, __func__);
+			physport->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN;
+			return 0;
+		}
+	}
+
+	/* Reset FIFO, go in forward mode, and disable ackIntEn */
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
+	parport_ip32_data_forward(p);
+	parport_ip32_disable_irq(p);
+	parport_ip32_set_mode(p, ECR_MODE_ECP);
+	physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+
+	/* Wait for peripheral to become ready */
+	if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT,
+				       DSR_nBUSY | DSR_nFAULT)) {
+		/* Avoid to flood the logs */
+		if (ready_before)
+			printk(KERN_INFO PPIP32 "%s: not ready in %s\n",
+			       p->name, __func__);
+		ready_before = 0;
+		goto stop;
+	}
+	ready_before = 1;
+
+	written = parport_ip32_fifo_write_block(p, buf, len);
+
+	/* Wait FIFO to empty.  Timeout is proportional to FIFO_depth.  */
+	parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth);
+
+	/* Check for a potential residue */
+	written -= parport_ip32_get_fifo_residue(p, ECR_MODE_ECP);
+
+	/* Then, wait for BUSY to get low. */
+	if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY))
+		printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n",
+		       p->name, __func__);
+
+stop:
+	/* Reset FIFO */
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+	return written;
+}
+
+/*
+ * FIXME - Insert here parport_ip32_ecp_write_addr().
+ */
+
+/*--- Default parport operations ---------------------------------------*/
+
+static __initdata struct parport_operations parport_ip32_ops = {
+	.write_data		= parport_ip32_write_data,
+	.read_data		= parport_ip32_read_data,
+
+	.write_control		= parport_ip32_write_control,
+	.read_control		= parport_ip32_read_control,
+	.frob_control		= parport_ip32_frob_control,
+
+	.read_status		= parport_ip32_read_status,
+
+	.enable_irq		= parport_ip32_enable_irq,
+	.disable_irq		= parport_ip32_disable_irq,
+
+	.data_forward		= parport_ip32_data_forward,
+	.data_reverse		= parport_ip32_data_reverse,
+
+	.init_state		= parport_ip32_init_state,
+	.save_state		= parport_ip32_save_state,
+	.restore_state		= parport_ip32_restore_state,
+
+	.epp_write_data		= parport_ieee1284_epp_write_data,
+	.epp_read_data		= parport_ieee1284_epp_read_data,
+	.epp_write_addr		= parport_ieee1284_epp_write_addr,
+	.epp_read_addr		= parport_ieee1284_epp_read_addr,
+
+	.ecp_write_data		= parport_ieee1284_ecp_write_data,
+	.ecp_read_data		= parport_ieee1284_ecp_read_data,
+	.ecp_write_addr		= parport_ieee1284_ecp_write_addr,
+
+	.compat_write_data	= parport_ieee1284_write_compat,
+	.nibble_read_data	= parport_ieee1284_read_nibble,
+	.byte_read_data		= parport_ieee1284_read_byte,
+
+	.owner			= THIS_MODULE,
+};
+
+/*--- Device detection -------------------------------------------------*/
+
+/**
+ * parport_ip32_ecp_supported - check for an ECP port
+ * @p:		pointer to the &parport structure
+ *
+ * Returns 1 if an ECP port is found, and 0 otherwise.  This function actually
+ * checks if an Extended Control Register seems to be present.  On successful
+ * return, the port is placed in SPP mode.
+ */
+static __init unsigned int parport_ip32_ecp_supported(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	unsigned int ecr;
+
+	ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR;
+	writeb(ecr, priv->regs.ecr);
+	if (readb(priv->regs.ecr) != (ecr | ECR_F_EMPTY))
+		goto fail;
+
+	pr_probe(p, "Found working ECR register\n");
+	parport_ip32_set_mode(p, ECR_MODE_SPP);
+	parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
+	return 1;
+
+fail:
+	pr_probe(p, "ECR register not found\n");
+	return 0;
+}
+
+/**
+ * parport_ip32_fifo_supported - check for FIFO parameters
+ * @p:		pointer to the &parport structure
+ *
+ * Check for FIFO parameters of an Extended Capabilities Port.  Returns 1 on
+ * success, and 0 otherwise.  Adjust FIFO parameters in the parport structure.
+ * On return, the port is placed in SPP mode.
+ */
+static __init unsigned int parport_ip32_fifo_supported(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	unsigned int configa, configb;
+	unsigned int pword;
+	unsigned int i;
+
+	/* Configuration mode */
+	parport_ip32_set_mode(p, ECR_MODE_CFG);
+	configa = readb(priv->regs.cnfgA);
+	configb = readb(priv->regs.cnfgB);
+
+	/* Find out PWord size */
+	switch (configa & CNFGA_ID_MASK) {
+	case CNFGA_ID_8:
+		pword = 1;
+		break;
+	case CNFGA_ID_16:
+		pword = 2;
+		break;
+	case CNFGA_ID_32:
+		pword = 4;
+		break;
+	default:
+		pr_probe(p, "Unknown implementation ID: 0x%0x\n",
+			 (configa & CNFGA_ID_MASK) >> CNFGA_ID_SHIFT);
+		goto fail;
+		break;
+	}
+	if (pword != 1) {
+		pr_probe(p, "Unsupported PWord size: %u\n", pword);
+		goto fail;
+	}
+	priv->pword = pword;
+	pr_probe(p, "PWord is %u bits\n", 8 * priv->pword);
+
+	/* Check for compression support */
+	writeb(configb | CNFGB_COMPRESS, priv->regs.cnfgB);
+	if (readb(priv->regs.cnfgB) & CNFGB_COMPRESS)
+		pr_probe(p, "Hardware compression detected (unsupported)\n");
+	writeb(configb & ~CNFGB_COMPRESS, priv->regs.cnfgB);
+
+	/* Reset FIFO and go in test mode (no interrupt, no DMA) */
+	parport_ip32_set_mode(p, ECR_MODE_TST);
+
+	/* FIFO must be empty now */
+	if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) {
+		pr_probe(p, "FIFO not reset\n");
+		goto fail;
+	}
+
+	/* Find out FIFO depth. */
+	priv->fifo_depth = 0;
+	for (i = 0; i < 1024; i++) {
+		if (readb(priv->regs.ecr) & ECR_F_FULL) {
+			/* FIFO full */
+			priv->fifo_depth = i;
+			break;
+		}
+		writeb((u8)i, priv->regs.fifo);
+	}
+	if (i >= 1024) {
+		pr_probe(p, "Can't fill FIFO\n");
+		goto fail;
+	}
+	if (!priv->fifo_depth) {
+		pr_probe(p, "Can't get FIFO depth\n");
+		goto fail;
+	}
+	pr_probe(p, "FIFO is %u PWords deep\n", priv->fifo_depth);
+
+	/* Enable interrupts */
+	parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0);
+
+	/* Find out writeIntrThreshold: number of PWords we know we can write
+	 * if we get an interrupt. */
+	priv->writeIntrThreshold = 0;
+	for (i = 0; i < priv->fifo_depth; i++) {
+		if (readb(priv->regs.fifo) != (u8)i) {
+			pr_probe(p, "Invalid data in FIFO\n");
+			goto fail;
+		}
+		if (!priv->writeIntrThreshold
+		    && readb(priv->regs.ecr) & ECR_SERVINTR)
+			/* writeIntrThreshold reached */
+			priv->writeIntrThreshold = i + 1;
+		if (i + 1 < priv->fifo_depth
+		    && readb(priv->regs.ecr) & ECR_F_EMPTY) {
+			/* FIFO empty before the last byte? */
+			pr_probe(p, "Data lost in FIFO\n");
+			goto fail;
+		}
+	}
+	if (!priv->writeIntrThreshold) {
+		pr_probe(p, "Can't get writeIntrThreshold\n");
+		goto fail;
+	}
+	pr_probe(p, "writeIntrThreshold is %u\n", priv->writeIntrThreshold);
+
+	/* FIFO must be empty now */
+	if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) {
+		pr_probe(p, "Can't empty FIFO\n");
+		goto fail;
+	}
+
+	/* Reset FIFO */
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	/* Set reverse direction (must be in PS2 mode) */
+	parport_ip32_data_reverse(p);
+	/* Test FIFO, no interrupt, no DMA */
+	parport_ip32_set_mode(p, ECR_MODE_TST);
+	/* Enable interrupts */
+	parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0);
+
+	/* Find out readIntrThreshold: number of PWords we can read if we get
+	 * an interrupt. */
+	priv->readIntrThreshold = 0;
+	for (i = 0; i < priv->fifo_depth; i++) {
+		writeb(0xaa, priv->regs.fifo);
+		if (readb(priv->regs.ecr) & ECR_SERVINTR) {
+			/* readIntrThreshold reached */
+			priv->readIntrThreshold = i + 1;
+			break;
+		}
+	}
+	if (!priv->readIntrThreshold) {
+		pr_probe(p, "Can't get readIntrThreshold\n");
+		goto fail;
+	}
+	pr_probe(p, "readIntrThreshold is %u\n", priv->readIntrThreshold);
+
+	/* Reset ECR */
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	parport_ip32_data_forward(p);
+	parport_ip32_set_mode(p, ECR_MODE_SPP);
+	return 1;
+
+fail:
+	priv->fifo_depth = 0;
+	parport_ip32_set_mode(p, ECR_MODE_SPP);
+	return 0;
+}
+
+/*--- Initialization code ----------------------------------------------*/
+
+/**
+ * parport_ip32_make_isa_registers - compute (ISA) register addresses
+ * @regs:	pointer to &struct parport_ip32_regs to fill
+ * @base:	base address of standard and EPP registers
+ * @base_hi:	base address of ECP registers
+ * @regshift:	how much to shift register offset by
+ *
+ * Compute register addresses, according to the ISA standard.  The addresses
+ * of the standard and EPP registers are computed from address @base.  The
+ * addresses of the ECP registers are computed from address @base_hi.
+ */
+static void __init
+parport_ip32_make_isa_registers(struct parport_ip32_regs *regs,
+				void __iomem *base, void __iomem *base_hi,
+				unsigned int regshift)
+{
+#define r_base(offset)    ((u8 __iomem *)base    + ((offset) << regshift))
+#define r_base_hi(offset) ((u8 __iomem *)base_hi + ((offset) << regshift))
+	*regs = (struct parport_ip32_regs){
+		.data		= r_base(0),
+		.dsr		= r_base(1),
+		.dcr		= r_base(2),
+		.eppAddr	= r_base(3),
+		.eppData0	= r_base(4),
+		.eppData1	= r_base(5),
+		.eppData2	= r_base(6),
+		.eppData3	= r_base(7),
+		.ecpAFifo	= r_base(0),
+		.fifo		= r_base_hi(0),
+		.cnfgA		= r_base_hi(0),
+		.cnfgB		= r_base_hi(1),
+		.ecr		= r_base_hi(2)
+	};
+#undef r_base_hi
+#undef r_base
+}
+
+/**
+ * parport_ip32_probe_port - probe and register IP32 built-in parallel port
+ *
+ * Returns the new allocated &parport structure.  On error, an error code is
+ * encoded in return value with the ERR_PTR function.
+ */
+static __init struct parport *parport_ip32_probe_port(void)
+{
+	struct parport_ip32_regs regs;
+	struct parport_ip32_private *priv = NULL;
+	struct parport_operations *ops = NULL;
+	struct parport *p = NULL;
+	int err;
+
+	parport_ip32_make_isa_registers(&regs, &mace->isa.parallel,
+					&mace->isa.ecp1284, 8 /* regshift */);
+
+	ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
+	priv = kmalloc(sizeof(struct parport_ip32_private), GFP_KERNEL);
+	p = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, ops);
+	if (ops == NULL || priv == NULL || p == NULL) {
+		err = -ENOMEM;
+		goto fail;
+	}
+	p->base = MACE_BASE + offsetof(struct sgi_mace, isa.parallel);
+	p->base_hi = MACE_BASE + offsetof(struct sgi_mace, isa.ecp1284);
+	p->private_data = priv;
+
+	*ops = parport_ip32_ops;
+	*priv = (struct parport_ip32_private){
+		.regs			= regs,
+		.dcr_writable		= DCR_DIR | DCR_SELECT | DCR_nINIT |
+					  DCR_AUTOFD | DCR_STROBE,
+		.irq_mode		= PARPORT_IP32_IRQ_FWD,
+	};
+	init_completion(&priv->irq_complete);
+
+	/* Probe port. */
+	if (!parport_ip32_ecp_supported(p)) {
+		err = -ENODEV;
+		goto fail;
+	}
+	parport_ip32_dump_state(p, "begin init", 0);
+
+	/* We found what looks like a working ECR register.  Simply assume
+	 * that all modes are correctly supported.  Enable basic modes. */
+	p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
+	p->modes |= PARPORT_MODE_TRISTATE;
+
+	if (!parport_ip32_fifo_supported(p)) {
+		printk(KERN_WARNING PPIP32
+		       "%s: error: FIFO disabled\n", p->name);
+		/* Disable hardware modes depending on a working FIFO. */
+		features &= ~PARPORT_IP32_ENABLE_SPP;
+		features &= ~PARPORT_IP32_ENABLE_ECP;
+		/* DMA is not needed if FIFO is not supported.  */
+		features &= ~PARPORT_IP32_ENABLE_DMA;
+	}
+
+	/* Request IRQ */
+	if (features & PARPORT_IP32_ENABLE_IRQ) {
+		int irq = MACEISA_PARALLEL_IRQ;
+		if (request_irq(irq, parport_ip32_interrupt, 0, p->name, p)) {
+			printk(KERN_WARNING PPIP32
+			       "%s: error: IRQ disabled\n", p->name);
+			/* DMA cannot work without interrupts. */
+			features &= ~PARPORT_IP32_ENABLE_DMA;
+		} else {
+			pr_probe(p, "Interrupt support enabled\n");
+			p->irq = irq;
+			priv->dcr_writable |= DCR_IRQ;
+		}
+	}
+
+	/* Allocate DMA resources */
+	if (features & PARPORT_IP32_ENABLE_DMA) {
+		if (parport_ip32_dma_register())
+			printk(KERN_WARNING PPIP32
+			       "%s: error: DMA disabled\n", p->name);
+		else {
+			pr_probe(p, "DMA support enabled\n");
+			p->dma = 0; /* arbitrary value != PARPORT_DMA_NONE */
+			p->modes |= PARPORT_MODE_DMA;
+		}
+	}
+
+	if (features & PARPORT_IP32_ENABLE_SPP) {
+		/* Enable compatibility FIFO mode */
+		p->ops->compat_write_data = parport_ip32_compat_write_data;
+		p->modes |= PARPORT_MODE_COMPAT;
+		pr_probe(p, "Hardware support for SPP mode enabled\n");
+	}
+	if (features & PARPORT_IP32_ENABLE_EPP) {
+		/* Set up access functions to use EPP hardware. */
+		p->ops->epp_read_data = parport_ip32_epp_read_data;
+		p->ops->epp_write_data = parport_ip32_epp_write_data;
+		p->ops->epp_read_addr = parport_ip32_epp_read_addr;
+		p->ops->epp_write_addr = parport_ip32_epp_write_addr;
+		p->modes |= PARPORT_MODE_EPP;
+		pr_probe(p, "Hardware support for EPP mode enabled\n");
+	}
+	if (features & PARPORT_IP32_ENABLE_ECP) {
+		/* Enable ECP FIFO mode */
+		p->ops->ecp_write_data = parport_ip32_ecp_write_data;
+		/* FIXME - not implemented */
+/*		p->ops->ecp_read_data  = parport_ip32_ecp_read_data; */
+/*		p->ops->ecp_write_addr = parport_ip32_ecp_write_addr; */
+		p->modes |= PARPORT_MODE_ECP;
+		pr_probe(p, "Hardware support for ECP mode enabled\n");
+	}
+
+	/* Initialize the port with sensible values */
+	parport_ip32_set_mode(p, ECR_MODE_PS2);
+	parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
+	parport_ip32_data_forward(p);
+	parport_ip32_disable_irq(p);
+	parport_ip32_write_data(p, 0x00);
+	parport_ip32_dump_state(p, "end init", 0);
+
+	/* Print out what we found */
+	printk(KERN_INFO "%s: SGI IP32 at 0x%lx (0x%lx)",
+	       p->name, p->base, p->base_hi);
+	if (p->irq != PARPORT_IRQ_NONE)
+		printk(", irq %d", p->irq);
+	printk(" [");
+#define printmode(x)	if (p->modes & PARPORT_MODE_##x)		\
+				printk("%s%s", f++ ? "," : "", #x)
+	{
+		unsigned int f = 0;
+		printmode(PCSPP);
+		printmode(TRISTATE);
+		printmode(COMPAT);
+		printmode(EPP);
+		printmode(ECP);
+		printmode(DMA);
+	}
+#undef printmode
+	printk("]\n");
+
+	parport_announce_port(p);
+	return p;
+
+fail:
+	if (p)
+		parport_put_port(p);
+	kfree(priv);
+	kfree(ops);
+	return ERR_PTR(err);
+}
+
+/**
+ * parport_ip32_unregister_port - unregister a parallel port
+ * @p:		pointer to the &struct parport
+ *
+ * Unregisters a parallel port and free previously allocated resources
+ * (memory, IRQ, ...).
+ */
+static __exit void parport_ip32_unregister_port(struct parport *p)
+{
+	struct parport_ip32_private * const priv = p->physport->private_data;
+	struct parport_operations *ops = p->ops;
+
+	parport_remove_port(p);
+	if (p->modes & PARPORT_MODE_DMA)
+		parport_ip32_dma_unregister();
+	if (p->irq != PARPORT_IRQ_NONE)
+		free_irq(p->irq, p);
+	parport_put_port(p);
+	kfree(priv);
+	kfree(ops);
+}
+
+/**
+ * parport_ip32_init - module initialization function
+ */
+static int __init parport_ip32_init(void)
+{
+	pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n");
+	pr_debug1(PPIP32 "Compiled on %s, %s\n", __DATE__, __TIME__);
+	this_port = parport_ip32_probe_port();
+	return IS_ERR(this_port) ? PTR_ERR(this_port) : 0;
+}
+
+/**
+ * parport_ip32_exit - module termination function
+ */
+static void __exit parport_ip32_exit(void)
+{
+	parport_ip32_unregister_port(this_port);
+}
+
+/*--- Module stuff -----------------------------------------------------*/
+
+MODULE_AUTHOR("Arnaud Giersch <arnaud.giersch@free.fr>");
+MODULE_DESCRIPTION("SGI IP32 built-in parallel port driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.6");		/* update in parport_ip32_init() too */
+
+module_init(parport_ip32_init);
+module_exit(parport_ip32_exit);
+
+module_param(verbose_probing, bool, S_IRUGO);
+MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialization");
+
+module_param(features, uint, S_IRUGO);
+MODULE_PARM_DESC(features,
+		 "Bit mask of features to enable"
+		 ", bit 0: IRQ support"
+		 ", bit 1: DMA support"
+		 ", bit 2: hardware SPP mode"
+		 ", bit 3: hardware EPP mode"
+		 ", bit 4: hardware ECP mode");
+
+/*--- Inform (X)Emacs about preferred coding style ---------------------*/
+/*
+ * Local Variables:
+ * mode: c
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * tab-width: 8
+ * fill-column: 78
+ * ispell-local-dictionary: "american"
+ * End:
+ */
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 76dd077..166de35 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -329,9 +329,9 @@
 
 		if (priv->num_par == ARRAY_SIZE (priv->port)) {
 			printk (KERN_WARNING
-				"parport_serial: %s: only %u parallel ports "
+				"parport_serial: %s: only %zu parallel ports "
 				"supported (%d reported)\n", pci_name (dev),
-				ARRAY_SIZE (priv->port), card->numports);
+				ARRAY_SIZE(priv->port), card->numports);
 			break;
 		}
 
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index b62aee8..ea83b70 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -199,7 +199,7 @@
 
 		if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) {
 			if (belen != len) {
-				printk (KERN_DEBUG "%s: Device ID was %d bytes"
+				printk (KERN_DEBUG "%s: Device ID was %zd bytes"
 					" while device told it would be %d"
 					" bytes\n",
 					port->name, len, belen);
@@ -214,7 +214,7 @@
 		if (buffer[len-1] == ';') {
  			printk (KERN_DEBUG "%s: Device ID reading stopped"
 				" before device told data not available. "
-				"Current idlen %d of %d, len bytes %02X %02X\n",
+				"Current idlen %u of %u, len bytes %02X %02X\n",
 				port->name, current_idlen, numidlens,
 				length[0], length[1]);
 			goto done;
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 2f1289e..222a1cc 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -11,8 +11,7 @@
 	---help---
 	  Say Y here if you have a motherboard with a PCI Hotplug controller.
 	  This allows you to add and remove PCI cards while the machine is
-	  powered up and running.  The file system pcihpfs must be mounted
-	  in order to interact with any PCI Hotplug controllers.
+	  powered up and running.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called pci_hotplug.
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 7e7f913..317457d 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -302,7 +302,7 @@
 	}
 
 	package = (union acpi_object *) buffer.pointer;
-	if(!(package) ||
+	if (!(package) ||
 			(package->type != ACPI_TYPE_PACKAGE) ||
 			!(package->package.elements)) {
 		err("%s:  Invalid APCI object\n", __FUNCTION__);
@@ -405,7 +405,7 @@
 	}
 	info.hardware_id.value[sizeof(info.hardware_id.value) - 1] = '\0';
 
-	if(info.current_status && (info.valid & ACPI_VALID_HID) &&
+	if (info.current_status && (info.valid & ACPI_VALID_HID) &&
 			(!strcmp(info.hardware_id.value, IBM_HARDWARE_ID1) ||
 			!strcmp(info.hardware_id.value, IBM_HARDWARE_ID2))) {
 		dbg("found hardware: %s, handle: %p\n", info.hardware_id.value,
@@ -449,13 +449,11 @@
 	}
 
 	ibm_note.device = device;
-	status = acpi_install_notify_handler(
-			ibm_acpi_handle,
-			ACPI_DEVICE_NOTIFY,
-			ibm_handle_events,
+	status = acpi_install_notify_handler(ibm_acpi_handle,
+			ACPI_DEVICE_NOTIFY, ibm_handle_events,
 			&ibm_note);
 	if (ACPI_FAILURE(status)) {
-		err("%s:  Failed to register notification handler\n",
+		err("%s: Failed to register notification handler\n",
 				__FUNCTION__);
 		retval = -EBUSY;
 		goto init_cleanup;
@@ -482,14 +480,13 @@
 	if (acpiphp_unregister_attention(&ibm_attention_info))
 		err("%s: attention info deregistration failed", __FUNCTION__);
 
-	   status = acpi_remove_notify_handler(
+	status = acpi_remove_notify_handler(
 			   ibm_acpi_handle,
 			   ACPI_DEVICE_NOTIFY,
 			   ibm_handle_events);
-	   if (ACPI_FAILURE(status))
-		   err("%s:  Notification handler removal failed\n",
-				   __FUNCTION__);
-	// remove the /sys entries
+	if (ACPI_FAILURE(status))
+		err("%s: Notification handler removal failed\n", __FUNCTION__);
+	/* remove the /sys entries */
 	if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr))
 		err("%s: removal of sysfs file apci_table failed\n",
 				__FUNCTION__);
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index aabf1e7..dc59da6 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -235,12 +235,12 @@
 {
 	int rc = 0;
 	struct slot *pslot;
-	u8 cmd;
+	u8 cmd = 0x00;     /* avoid compiler warning */
 
 	debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n",
 			(ulong) hotplug_slot, value);
 	ibmphp_lock_operations();
-	cmd = 0x00;     // avoid compiler warning
+
 
 	if (hotplug_slot) {
 		switch (value) {
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 7d93dba..3eefe2c 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -103,13 +103,13 @@
 	struct list_head *tmp, *n;
 	struct slot *slot;
 
-        list_for_each_safe(tmp, n, &rpaphp_slot_head) {
-                slot = list_entry(tmp, struct slot, rpaphp_slot_list);
-                if (slot->dn == dn)
-                        return slot;
-        }
+	list_for_each_safe(tmp, n, &rpaphp_slot_head) {
+		slot = list_entry(tmp, struct slot, rpaphp_slot_list);
+		if (slot->dn == dn)
+			return slot;
+	}
 
-        return NULL;
+	return NULL;
 }
 
 static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
@@ -126,9 +126,9 @@
 	return NULL;
 }
 
-static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
+static void dlpar_pci_add_bus(struct device_node *dn)
 {
-	struct pci_dn *pdn = dn->data;
+	struct pci_dn *pdn = PCI_DN(dn);
 	struct pci_controller *phb = pdn->phb;
 	struct pci_dev *dev = NULL;
 
@@ -139,52 +139,52 @@
 	if (!dev) {
 		printk(KERN_ERR "%s: failed to create pci dev for %s\n",
 				__FUNCTION__, dn->full_name);
-		return NULL;
+		return;
 	}
 
 	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 	    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 		of_scan_pci_bridge(dn, dev);
 
-	rpaphp_init_new_devs(dev->subordinate);
+	pcibios_fixup_new_pci_devices(dev->subordinate,0);
 
 	/* Claim new bus resources */
 	pcibios_claim_one_bus(dev->bus);
 
 	/* ioremap() for child bus, which may or may not succeed */
-	(void) remap_bus_range(dev->bus);
+	remap_bus_range(dev->subordinate);
 
 	/* Add new devices to global lists.  Register in proc, sysfs. */
 	pci_bus_add_devices(phb->bus);
-
-	/* Confirm new bridge dev was created */
-	dev = dlpar_find_new_dev(phb->bus, dn);
-	if (dev) {
-		if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
-			printk(KERN_ERR "%s: unexpected header type %d\n",
-				__FUNCTION__, dev->hdr_type);
-			return NULL;
-		}
-	}
-
-	return dev;
 }
 
 static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
 {
 	struct pci_dev *dev;
+	struct pci_controller *phb;
 
-	if (rpaphp_find_pci_bus(dn))
+	if (pcibios_find_pci_bus(dn))
 		return -EINVAL;
 
 	/* Add pci bus */
-	dev = dlpar_pci_add_bus(dn);
+	dlpar_pci_add_bus(dn);
+
+	/* Confirm new bridge dev was created */
+	phb = PCI_DN(dn)->phb;
+	dev = dlpar_find_new_dev(phb->bus, dn);
+
 	if (!dev) {
 		printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__,
 			drc_name);
 		return -EIO;
 	}
 
+	if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+		printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n",
+			__FUNCTION__, dev->hdr_type, drc_name);
+		return -EIO;
+	}
+
 	/* Add hotplug slot */
 	if (rpaphp_add_slot(dn)) {
 		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
@@ -221,13 +221,13 @@
 	struct pci_dn *pdn;
 	int rc = 0;
 
-	if (!rpaphp_find_pci_bus(dn))
+	if (!pcibios_find_pci_bus(dn))
 		return -EINVAL;
 
 	slot = find_slot(dn);
 	if (slot) {
 		/* Remove hotplug slot */
-		if (rpaphp_remove_slot(slot)) {
+		if (rpaphp_deregister_slot(slot)) {
 			printk(KERN_ERR
 				"%s: unable to remove hotplug slot %s\n",
 				__FUNCTION__, drc_name);
@@ -366,21 +366,25 @@
 	struct pci_bus *bus;
 	struct slot *slot;
 
-	bus = rpaphp_find_pci_bus(dn);
+	bus = pcibios_find_pci_bus(dn);
 	if (!bus)
 		return -EINVAL;
 
 	slot = find_slot(dn);
 	if (slot) {
 		/* Remove hotplug slot */
-		if (rpaphp_remove_slot(slot)) {
+		if (rpaphp_deregister_slot(slot)) {
 			printk(KERN_ERR
 				"%s: unable to remove hotplug slot %s\n",
 				__FUNCTION__, drc_name);
 			return -EIO;
 		}
 	} else {
-		rpaphp_unconfig_pci_adapter(bus);
+		struct pci_dev *dev, *tmp;
+		list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
+			eeh_remove_bus_device(dev);
+			pci_remove_bus_device(dev);
+		}
 	}
 
 	if (unmap_bus_range(bus)) {
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 57ea71a..310b618 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -88,16 +88,10 @@
 /* function prototypes */
 
 /* rpaphp_pci.c */
-extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn);
-extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
 extern int rpaphp_enable_pci_slot(struct slot *slot);
-extern int register_pci_slot(struct slot *slot);
+extern int rpaphp_register_pci_slot(struct slot *slot);
 extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
-extern void rpaphp_init_new_devs(struct pci_bus *bus);
-extern void rpaphp_eeh_init_nodes(struct device_node *dn);
-
-extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
-extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
+extern int rpaphp_get_sensor_state(struct slot *slot, int *state);
 
 /* rpaphp_core.c */
 extern int rpaphp_add_slot(struct device_node *dn);
@@ -108,8 +102,8 @@
 /* rpaphp_slot.c */
 extern void dealloc_slot_struct(struct slot *slot);
 extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
-extern int register_slot(struct slot *slot);
-extern int deregister_slot(struct slot *slot);
+extern int rpaphp_register_slot(struct slot *slot);
+extern int rpaphp_deregister_slot(struct slot *slot);
 extern int rpaphp_get_power_status(struct slot *slot, u8 * value);
 extern int rpaphp_set_attention_status(struct slot *slot, u8 status);
 	
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index cf075c3..6e79f56 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -56,25 +56,6 @@
 
 module_param(debug, bool, 0644);
 
-static int enable_slot(struct hotplug_slot *slot);
-static int disable_slot(struct hotplug_slot *slot);
-static int set_attention_status(struct hotplug_slot *slot, u8 value);
-static int get_power_status(struct hotplug_slot *slot, u8 * value);
-static int get_attention_status(struct hotplug_slot *slot, u8 * value);
-static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
-static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value);
-
-struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
-	.owner = THIS_MODULE,
-	.enable_slot = enable_slot,
-	.disable_slot = disable_slot,
-	.set_attention_status = set_attention_status,
-	.get_power_status = get_power_status,
-	.get_attention_status = get_attention_status,
-	.get_adapter_status = get_adapter_status,
-	.get_max_bus_speed = get_max_bus_speed,
-};
-
 static int rpaphp_get_attention_status(struct slot *slot)
 {
 	return slot->hotplug_slot->info->attention_status;
@@ -196,11 +177,6 @@
 	return 0;
 }
 
-int rpaphp_remove_slot(struct slot *slot)
-{
-	return deregister_slot(slot);
-}
-
 static int get_children_props(struct device_node *dn, int **drc_indexes,
 		int **drc_names, int **drc_types, int **drc_power_domains)
 {
@@ -307,13 +283,15 @@
 	return 0;
 }
 
-/****************************************************************
+/**
+ * rpaphp_add_slot -- add hotplug or dlpar slot
+ *
  *	rpaphp not only registers PCI hotplug slots(HOTPLUG), 
  *	but also logical DR slots(EMBEDDED).
  *	HOTPLUG slot: An adapter can be physically added/removed. 
  *	EMBEDDED slot: An adapter can be logically removed/added
  *		  from/to a partition with the slot.
- ***************************************************************/
+ */
 int rpaphp_add_slot(struct device_node *dn)
 {
 	struct slot *slot;
@@ -344,7 +322,7 @@
 			dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
 					indexes[i + 1], name, type);
 
-			retval = register_pci_slot(slot);
+			retval = rpaphp_register_pci_slot(slot);
 		}
 	}
 exit:
@@ -393,53 +371,85 @@
 	cleanup_slots();
 }
 
+static int __enable_slot(struct slot *slot)
+{
+	int state;
+	int retval;
+
+	if (slot->state == CONFIGURED)
+		return 0;
+
+	retval = rpaphp_get_sensor_state(slot, &state);
+	if (retval)
+		return retval;
+
+	if (state == PRESENT) {
+		pcibios_add_pci_devices(slot->bus);
+		slot->state = CONFIGURED;
+	} else if (state == EMPTY) {
+		slot->state = EMPTY;
+	} else {
+		err("%s: slot[%s] is in invalid state\n", __FUNCTION__, slot->name);
+		slot->state = NOT_VALID;
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int enable_slot(struct hotplug_slot *hotplug_slot)
 {
-	int retval = 0;
+	int retval;
 	struct slot *slot = (struct slot *)hotplug_slot->private;
 
-	if (slot->state == CONFIGURED) {
-		dbg("%s: %s is already enabled\n", __FUNCTION__, slot->name);
-		goto exit;
+	down(&rpaphp_sem);
+	retval = __enable_slot(slot);
+	up(&rpaphp_sem);
+
+	return retval;
+}
+
+static int __disable_slot(struct slot *slot)
+{
+	struct pci_dev *dev, *tmp;
+
+	if (slot->state == NOT_CONFIGURED)
+		return -EINVAL;
+
+	list_for_each_entry_safe(dev, tmp, &slot->bus->devices, bus_list) {
+		eeh_remove_bus_device(dev);
+		pci_remove_bus_device(dev);
 	}
 
-	dbg("ENABLING SLOT %s\n", slot->name);
-	down(&rpaphp_sem);
-	retval = rpaphp_enable_pci_slot(slot);
-	up(&rpaphp_sem);
-exit:
-	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
-	return retval;
+	slot->state = NOT_CONFIGURED;
+	return 0;
 }
 
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
-	int retval = -EINVAL;
 	struct slot *slot = (struct slot *)hotplug_slot->private;
+	int retval;
 
-	dbg("%s - Entry: slot[%s]\n", __FUNCTION__, slot->name);
-
-	if (slot->state == NOT_CONFIGURED) {
-		dbg("%s: %s is already disabled\n", __FUNCTION__, slot->name);
-		goto exit;
-	}
-
-	dbg("DISABLING SLOT %s\n", slot->name);
 	down(&rpaphp_sem);
-	retval = rpaphp_unconfig_pci_adapter(slot->bus);
+	retval = __disable_slot (slot);
 	up(&rpaphp_sem);
-	slot->state = NOT_CONFIGURED;
-	info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
-	     slot->name);
-exit:
-	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
+
 	return retval;
 }
 
+struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
+	.owner = THIS_MODULE,
+	.enable_slot = enable_slot,
+	.disable_slot = disable_slot,
+	.set_attention_status = set_attention_status,
+	.get_power_status = get_power_status,
+	.get_attention_status = get_attention_status,
+	.get_adapter_status = get_adapter_status,
+	.get_max_bus_speed = get_max_bus_speed,
+};
+
 module_init(rpaphp_init);
 module_exit(rpaphp_exit);
 
 EXPORT_SYMBOL_GPL(rpaphp_add_slot);
-EXPORT_SYMBOL_GPL(rpaphp_remove_slot);
 EXPORT_SYMBOL_GPL(rpaphp_slot_head);
 EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 396b54b..6f6cbed 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -32,37 +32,7 @@
 #include "../pci.h"		/* for pci_add_new_bus */
 #include "rpaphp.h"
 
-static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
-					struct device_node *dn)
-{
-	struct pci_bus *child = NULL;
-	struct list_head *tmp;
-	struct device_node *busdn;
-
-	busdn = pci_bus_to_OF_node(bus);
-	if (busdn == dn)
-		return bus;
-
-	list_for_each(tmp, &bus->children) {
-		child = find_bus_among_children(pci_bus_b(tmp), dn);
-		if (child)
-			break;
-	}
-	return child;
-}
-
-struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
-{
-	struct pci_dn *pdn = dn->data;
-
-	if (!pdn  || !pdn->phb || !pdn->phb->bus)
-		return NULL;
-
-	return find_bus_among_children(pdn->phb->bus, dn);
-}
-EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
-
-static int rpaphp_get_sensor_state(struct slot *slot, int *state)
+int rpaphp_get_sensor_state(struct slot *slot, int *state)
 {
 	int rc;
 	int setlevel;
@@ -120,7 +90,7 @@
 			/* config/unconfig adapter */
 			*value = slot->state;
 		} else {
-			bus = rpaphp_find_pci_bus(slot->dn);
+			bus = pcibios_find_pci_bus(slot->dn);
 			if (bus && !list_empty(&bus->devices))
 				*value = CONFIGURED;
 			else
@@ -131,140 +101,6 @@
 	return rc;
 }
 
-/* Must be called before pci_bus_add_devices */
-void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
-{
-	struct pci_dev *dev;
-
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		/*
-		 * Skip already-present devices (which are on the
-		 * global device list.)
-		 */
-		if (list_empty(&dev->global_list)) {
-			int i;
-			
-			/* Need to setup IOMMU tables */
-			ppc_md.iommu_dev_setup(dev);
-
-			if(fix_bus)
-				pcibios_fixup_device_resources(dev, bus);
-			pci_read_irq_line(dev);
-			for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-				struct resource *r = &dev->resource[i];
-
-				if (r->parent || !r->start || !r->flags)
-					continue;
-				pci_claim_resource(dev, i);
-			}
-		}
-	}
-}
-
-static void rpaphp_eeh_add_bus_device(struct pci_bus *bus)
-{
-	struct pci_dev *dev;
-
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		eeh_add_device_late(dev);
-		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-			struct pci_bus *subbus = dev->subordinate;
-			if (subbus)
-				rpaphp_eeh_add_bus_device (subbus);
-		}
-	}
-}
-
-static int rpaphp_pci_config_bridge(struct pci_dev *dev)
-{
-	u8 sec_busno;
-	struct pci_bus *child_bus;
-	struct pci_dev *child_dev;
-
-	dbg("Enter %s:  BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev));
-
-	/* get busno of downstream bus */
-	pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
-		
-	/* add to children of PCI bridge dev->bus */
-	child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
-	if (!child_bus) {
-		err("%s: could not add second bus\n", __FUNCTION__);
-		return -EIO;
-	}
-	sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
-	/* do pci_scan_child_bus */
-	pci_scan_child_bus(child_bus);
-
-	list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
-		eeh_add_device_late(child_dev);
-	}
-
-	 /* fixup new pci devices without touching bus struct */
-	rpaphp_fixup_new_pci_devices(child_bus, 0);
-
-	/* Make the discovered devices available */
-	pci_bus_add_devices(child_bus);
-	return 0;
-}
-
-void rpaphp_init_new_devs(struct pci_bus *bus)
-{
-	rpaphp_fixup_new_pci_devices(bus, 0);
-	rpaphp_eeh_add_bus_device(bus);
-}
-EXPORT_SYMBOL_GPL(rpaphp_init_new_devs);
-
-/*****************************************************************************
- rpaphp_pci_config_slot() will  configure all devices under the
- given slot->dn and return the the first pci_dev.
- *****************************************************************************/
-static struct pci_dev *
-rpaphp_pci_config_slot(struct pci_bus *bus)
-{
-	struct device_node *dn = pci_bus_to_OF_node(bus);
-	struct pci_dev *dev = NULL;
-	int slotno;
-	int num;
-
-	dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
-	if (!dn || !dn->child)
-		return NULL;
-
-	if (_machine == PLATFORM_PSERIES_LPAR) {
-		of_scan_bus(dn, bus);
-		if (list_empty(&bus->devices)) {
-			err("%s: No new device found\n", __FUNCTION__);
-			return NULL;
-		}
-
-		rpaphp_init_new_devs(bus);
-		pci_bus_add_devices(bus);
-		dev = list_entry(&bus->devices, struct pci_dev, bus_list);
-	} else {
-		slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
-
-		/* pci_scan_slot should find all children */
-		num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
-		if (num) {
-			rpaphp_fixup_new_pci_devices(bus, 1);
-			pci_bus_add_devices(bus);
-		}
-		if (list_empty(&bus->devices)) {
-			err("%s: No new device found\n", __FUNCTION__);
-			return NULL;
-		}
-		list_for_each_entry(dev, &bus->devices, bus_list) {
-			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
-				rpaphp_pci_config_bridge(dev);
-
-			rpaphp_eeh_add_bus_device(bus);
-		}
-	}
-
-	return dev;
-}
-
 static void print_slot_pci_funcs(struct pci_bus *bus)
 {
 	struct device_node *dn;
@@ -280,60 +116,6 @@
 	return;
 }
 
-int rpaphp_config_pci_adapter(struct pci_bus *bus)
-{
-	struct device_node *dn = pci_bus_to_OF_node(bus);
-	struct pci_dev *dev;
-	int rc = -ENODEV;
-
-	dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name);
-	if (!dn)
-		goto exit;
-
-	eeh_add_device_tree_early(dn);
-	dev = rpaphp_pci_config_slot(bus);
-	if (!dev) {
-		err("%s: can't find any devices.\n", __FUNCTION__);
-		goto exit;
-	}
-	print_slot_pci_funcs(bus);
-	rc = 0;
-exit:
-	dbg("Exit %s:  rc=%d\n", __FUNCTION__, rc);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter);
-
-static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
-{
-	eeh_remove_device(dev);
-	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-		struct pci_bus *bus = dev->subordinate;
-		struct list_head *ln;
-		if (!bus)
-			return; 
-		for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
-			struct pci_dev *pdev = pci_dev_b(ln);
-			if (pdev)
-				rpaphp_eeh_remove_bus_device(pdev);
-		}
-
-	}
-	return;
-}
-
-int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
-{
-	struct pci_dev *dev, *tmp;
-
-	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
-		rpaphp_eeh_remove_bus_device(dev);
-		pci_remove_bus_device(dev);
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
-
 static int setup_pci_hotplug_slot_info(struct slot *slot)
 {
 	struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info;
@@ -370,7 +152,7 @@
 	struct pci_bus *bus;
 
 	BUG_ON(!dn);
-	bus = rpaphp_find_pci_bus(dn);
+	bus = pcibios_find_pci_bus(dn);
 	if (!bus) {
 		err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
 		goto exit_rc;
@@ -395,10 +177,7 @@
 		if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
 			dbg("%s CONFIGURING pci adapter in slot[%s]\n",  
 				__FUNCTION__, slot->name);
-			if (rpaphp_config_pci_adapter(slot->bus)) {
-				err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
-				goto exit_rc;		
-			}
+			pcibios_add_pci_devices(slot->bus);
 
 		} else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) {
 			err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
@@ -420,7 +199,7 @@
 	return -EINVAL;
 }
 
-int register_pci_slot(struct slot *slot)
+int rpaphp_register_pci_slot(struct slot *slot)
 {
 	int rc = -EINVAL;
 
@@ -428,42 +207,8 @@
 		goto exit_rc;
 	if (setup_pci_slot(slot))
 		goto exit_rc;
-	rc = register_slot(slot);
+	rc = rpaphp_register_slot(slot);
 exit_rc:
 	return rc;
 }
 
-int rpaphp_enable_pci_slot(struct slot *slot)
-{
-	int retval = 0, state;
-
-	retval = rpaphp_get_sensor_state(slot, &state);
-	if (retval)
-		goto exit;
-	dbg("%s: sensor state[%d]\n", __FUNCTION__, state);
-	/* if slot is not empty, enable the adapter */
-	if (state == PRESENT) {
-		dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name);
-		retval = rpaphp_config_pci_adapter(slot->bus);
-		if (!retval) {
-			slot->state = CONFIGURED;
-			info("%s: devices in slot[%s] configured\n",
-					__FUNCTION__, slot->name);
-		} else {
-			slot->state = NOT_CONFIGURED;
-			dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
-			    __FUNCTION__, slot->name);
-		}
-	} else if (state == EMPTY) {
-		dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name);
-		slot->state = EMPTY;
-	} else {
-		err("%s: slot[%s] is in invalid state\n", __FUNCTION__,
-		    slot->name);
-		slot->state = NOT_VALID;
-		retval = -EINVAL;
-	}
-exit:
-	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
-	return retval;
-}
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index daa89ae..78943e0 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -35,16 +35,16 @@
 
 static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
 {
-        char *value;
-        int retval = -ENOENT;
+	char *value;
+	int retval = -ENOENT;
 	struct slot *slot = (struct slot *)php_slot->private;
 
 	if (!slot)
 		return retval;
 
-        value = slot->location;
-        retval = sprintf (buf, "%s\n", value);
-        return retval;
+	value = slot->location;
+	retval = sprintf (buf, "%s\n", value);
+	return retval;
 }
 
 static struct hotplug_slot_attribute hotplug_slot_attr_location = {
@@ -137,7 +137,7 @@
 	return 0;
 }
 
-int deregister_slot(struct slot *slot)
+int rpaphp_deregister_slot(struct slot *slot)
 {
 	int retval = 0;
 	struct hotplug_slot *php_slot = slot->hotplug_slot;
@@ -159,8 +159,9 @@
 	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
 	return retval;
 }
+EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
 
-int register_slot(struct slot *slot)
+int rpaphp_register_slot(struct slot *slot)
 {
 	int retval;
 
@@ -169,7 +170,7 @@
 		slot->power_domain, slot->type);
 	/* should not try to register the same slot twice */
 	if (is_registered(slot)) { /* should't be here */
-		err("register_slot: slot[%s] is already registered\n", slot->name);
+		err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
 		rpaphp_release_slot(slot->hotplug_slot);
 		return -EAGAIN;
 	}	
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index ce0e9b6..7d6f521 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -95,6 +95,7 @@
 	u8 function;
 	u8 slot_device_offset;
 	u8 add_support;
+	u32 pcix_misc2_reg;	/* for amd pogo errata */
 	enum pci_bus_speed speed;
 	u32 first_slot;		/* First physical slot number */
 	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
@@ -113,6 +114,26 @@
 
 /* Define AMD SHPC ID  */
 #define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450 
+#define PCI_DEVICE_ID_AMD_POGO_7458	0x7458
+
+/* AMD PCIX bridge registers */
+
+#define PCIX_MEM_BASE_LIMIT_OFFSET	0x1C
+#define PCIX_MISCII_OFFSET		0x48
+#define PCIX_MISC_BRIDGE_ERRORS_OFFSET	0x80
+
+/* AMD PCIX_MISCII masks and offsets */
+#define PERRNONFATALENABLE_MASK		0x00040000
+#define PERRFATALENABLE_MASK		0x00080000
+#define PERRFLOODENABLE_MASK		0x00100000
+#define SERRNONFATALENABLE_MASK		0x00200000
+#define SERRFATALENABLE_MASK		0x00400000
+
+/* AMD PCIX_MISC_BRIDGE_ERRORS masks and offsets */
+#define PERR_OBSERVED_MASK		0x00000001
+
+/* AMD PCIX_MEM_BASE_LIMIT masks */
+#define RSE_MASK			0x40000000
 
 #define INT_BUTTON_IGNORE		0
 #define INT_PRESENCE_ON			1
@@ -333,6 +354,79 @@
 	return retval;
 }
 
+static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot)
+{
+	u32 pcix_misc2_temp;
+
+	/* save MiscII register */
+	pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp);
+
+	p_slot->ctrl->pcix_misc2_reg = pcix_misc2_temp;
+
+	/* clear SERR/PERR enable bits */
+	pcix_misc2_temp &= ~SERRFATALENABLE_MASK;
+	pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK;
+	pcix_misc2_temp &= ~PERRFLOODENABLE_MASK;
+	pcix_misc2_temp &= ~PERRFATALENABLE_MASK;
+	pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK;
+	pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
+}
+
+static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
+{
+	u32 pcix_misc2_temp;
+	u32 pcix_bridge_errors_reg;
+	u32 pcix_mem_base_reg;
+	u8  perr_set;
+	u8  rse_set;
+
+	/* write-one-to-clear Bridge_Errors[ PERR_OBSERVED ] */
+	pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, &pcix_bridge_errors_reg);
+	perr_set = pcix_bridge_errors_reg & PERR_OBSERVED_MASK;
+	if (perr_set) {
+		dbg ("%s  W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__FUNCTION__ , perr_set);
+
+		pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, perr_set);
+	}
+
+	/* write-one-to-clear Memory_Base_Limit[ RSE ] */
+	pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, &pcix_mem_base_reg);
+	rse_set = pcix_mem_base_reg & RSE_MASK;
+	if (rse_set) {
+		dbg ("%s  W1C: Memory_Base_Limit[ RSE ]\n",__FUNCTION__ );
+
+		pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set);
+	}
+	/* restore MiscII register */
+	pci_read_config_dword( p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp );
+
+	if (p_slot->ctrl->pcix_misc2_reg & SERRFATALENABLE_MASK)
+		pcix_misc2_temp |= SERRFATALENABLE_MASK;
+	else
+		pcix_misc2_temp &= ~SERRFATALENABLE_MASK;
+
+	if (p_slot->ctrl->pcix_misc2_reg & SERRNONFATALENABLE_MASK)
+		pcix_misc2_temp |= SERRNONFATALENABLE_MASK;
+	else
+		pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK;
+
+	if (p_slot->ctrl->pcix_misc2_reg & PERRFLOODENABLE_MASK)
+		pcix_misc2_temp |= PERRFLOODENABLE_MASK;
+	else
+		pcix_misc2_temp &= ~PERRFLOODENABLE_MASK;
+
+	if (p_slot->ctrl->pcix_misc2_reg & PERRFATALENABLE_MASK)
+		pcix_misc2_temp |= PERRFATALENABLE_MASK;
+	else
+		pcix_misc2_temp &= ~PERRFATALENABLE_MASK;
+
+	if (p_slot->ctrl->pcix_misc2_reg & PERRNONFATALENABLE_MASK)
+		pcix_misc2_temp |= PERRNONFATALENABLE_MASK;
+	else
+		pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK;
+	pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
+}
+
 #define SLOT_NAME_SIZE 10
 
 static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 25ccb0e..643252d 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -894,7 +894,17 @@
 	dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 
-	rc = board_added(p_slot);
+	if(((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) ||
+	    (p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458))
+	     && p_slot->ctrl->num_slots == 1) {
+		/* handle amd pogo errata; this must be done before enable  */
+		amd_pogo_errata_save_misc_reg(p_slot);
+		rc = board_added(p_slot);
+		/* handle amd pogo errata; this must be done after enable  */
+		amd_pogo_errata_restore_misc_reg(p_slot);
+	} else
+		rc = board_added(p_slot);
+
 	if (rc) {
 		p_slot->hpc_ops->get_adapter_status(p_slot,
 				&(p_slot->presence_save));
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 202b750..48723d6 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -137,6 +137,8 @@
 		break;
 	}
 }
+#else
+#define set_msi_affinity NULL
 #endif /* CONFIG_SMP */
 
 static void mask_MSI_irq(unsigned int vector)
@@ -214,7 +216,7 @@
 	.disable	= mask_MSI_irq,
 	.ack		= mask_MSI_irq,
 	.end		= end_msi_irq_w_maskbit,
-	.set_affinity	= set_msi_irq_affinity
+	.set_affinity	= set_msi_affinity
 };
 
 /*
@@ -230,7 +232,7 @@
 	.disable	= mask_MSI_irq,
 	.ack		= mask_MSI_irq,
 	.end		= end_msi_irq_w_maskbit,
-	.set_affinity	= set_msi_irq_affinity
+	.set_affinity	= set_msi_affinity
 };
 
 /*
@@ -246,7 +248,7 @@
 	.disable	= do_nothing,
 	.ack		= do_nothing,
 	.end		= end_msi_irq_wo_maskbit,
-	.set_affinity	= set_msi_irq_affinity
+	.set_affinity	= set_msi_affinity
 };
 
 static void msi_data_init(struct msg_data *msi_data,
@@ -416,7 +418,9 @@
 
 static void irq_handler_init(int cap_id, int pos, int mask)
 {
-	spin_lock(&irq_desc[pos].lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&irq_desc[pos].lock, flags);
 	if (cap_id == PCI_CAP_ID_MSIX)
 		irq_desc[pos].handler = &msix_irq_type;
 	else {
@@ -425,7 +429,7 @@
 		else
 			irq_desc[pos].handler = &msi_irq_w_maskbit_type;
 	}
-	spin_unlock(&irq_desc[pos].lock);
+	spin_unlock_irqrestore(&irq_desc[pos].lock, flags);
 }
 
 static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 402136a..4ac52d4 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -22,12 +22,6 @@
 extern void (*interrupt[NR_IRQS])(void);
 extern int pci_vector_resources(int last, int nr_released);
 
-#ifdef CONFIG_SMP
-#define set_msi_irq_affinity	set_msi_affinity
-#else
-#define set_msi_irq_affinity	NULL
-#endif
-
 /*
  * MSI-X Address Register
  */
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index d2a633e..d2d1879 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -163,6 +163,7 @@
 	return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap);
 }
 
+#if 0
 /**
  * pci_find_ext_capability - Find an extended capability
  * @dev: PCI device to query
@@ -210,6 +211,7 @@
 
 	return 0;
 }
+#endif  /*  0  */
 
 /**
  * pci_find_parent_resource - return resource region of parent bus of given region
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 50d6685..ea9277b 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -112,6 +112,7 @@
 
 	return err;
 }
+EXPORT_SYMBOL_GPL(pci_claim_resource);
 
 int pci_assign_resource(struct pci_dev *dev, int resno)
 {
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 0ecbe4e..aaa568a 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -363,7 +363,7 @@
 
 int pnp_register_card_driver(struct pnp_card_driver * drv)
 {
-	int count = 0;
+	int count;
 	struct list_head *pos, *temp;
 
 	drv->link.name = drv->name;
@@ -374,10 +374,15 @@
 	drv->link.suspend = drv->suspend ? card_suspend : NULL;
 	drv->link.resume = drv->resume ? card_resume : NULL;
 
+	count = pnp_register_driver(&drv->link);
+	if (count < 0)
+		return count;
+
 	spin_lock(&pnp_lock);
 	list_add_tail(&drv->global_list, &pnp_card_drivers);
 	spin_unlock(&pnp_lock);
-	pnp_register_driver(&drv->link);
+
+	count = 0;
 
 	list_for_each_safe(pos,temp,&pnp_cards){
 		struct pnp_card *card = list_entry(pos, struct pnp_card, global_list);
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 816479a..f104577 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -27,12 +27,15 @@
 
 static int num = 0;
 
+/* We need only to blacklist devices that have already an acpi driver that
+ * can't use pnp layer. We don't need to blacklist device that are directly
+ * used by the kernel (PCI root, ...), as it is harmless and there were
+ * already present in pnpbios. But there is an exception for devices that
+ * have irqs (PIC, Timer) because we call acpi_register_gsi.
+ * Finaly only devices that have a CRS method need to be in this list.
+ */
 static char __initdata excluded_id_list[] =
-	"PNP0C0A," /* Battery */
-	"PNP0C0C,PNP0C0E,PNP0C0D," /* Button */
 	"PNP0C09," /* EC */
-	"PNP0C0B," /* Fan */
-	"PNP0A03," /* PCI root */
 	"PNP0C0F," /* Link device */
 	"PNP0000," /* PIC */
 	"PNP0100," /* Timer */
@@ -131,7 +134,8 @@
 	struct pnp_id *dev_id;
 	struct pnp_dev *dev;
 
-	if (!ispnpidacpi(acpi_device_hid(device)) ||
+	status = acpi_get_handle(device->handle, "_CRS", &temp);
+	if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
 		is_exclusive_device(device))
 		return 0;
 
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 416d30d..407b4ea 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
  * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2, or (at your option) any
@@ -32,17 +32,17 @@
 /*
  * Allocated Resources
  */
-static int irq_flags(int edge_level, int active_high_low)
+static int irq_flags(int triggering, int polarity)
 {
 	int flag;
-	if (edge_level == ACPI_LEVEL_SENSITIVE) {
-		if(active_high_low == ACPI_ACTIVE_LOW)
+	if (triggering == ACPI_LEVEL_SENSITIVE) {
+		if(polarity == ACPI_ACTIVE_LOW)
 			flag = IORESOURCE_IRQ_LOWLEVEL;
 		else
 			flag = IORESOURCE_IRQ_HIGHLEVEL;
 	}
 	else {
-		if(active_high_low == ACPI_ACTIVE_LOW)
+		if(polarity == ACPI_ACTIVE_LOW)
 			flag = IORESOURCE_IRQ_LOWEDGE;
 		else
 			flag = IORESOURCE_IRQ_HIGHEDGE;
@@ -50,31 +50,31 @@
 	return flag;
 }
 
-static void decode_irq_flags(int flag, int *edge_level, int *active_high_low)
+static void decode_irq_flags(int flag, int *triggering, int *polarity)
 {
 	switch (flag) {
 	case IORESOURCE_IRQ_LOWLEVEL:
-		*edge_level = ACPI_LEVEL_SENSITIVE;
-		*active_high_low = ACPI_ACTIVE_LOW;
+		*triggering = ACPI_LEVEL_SENSITIVE;
+		*polarity = ACPI_ACTIVE_LOW;
 		break;
 	case IORESOURCE_IRQ_HIGHLEVEL:	
-		*edge_level = ACPI_LEVEL_SENSITIVE;
-		*active_high_low = ACPI_ACTIVE_HIGH;
+		*triggering = ACPI_LEVEL_SENSITIVE;
+		*polarity = ACPI_ACTIVE_HIGH;
 		break;
 	case IORESOURCE_IRQ_LOWEDGE:
-		*edge_level = ACPI_EDGE_SENSITIVE;
-		*active_high_low = ACPI_ACTIVE_LOW;
+		*triggering = ACPI_EDGE_SENSITIVE;
+		*polarity = ACPI_ACTIVE_LOW;
 		break;
 	case IORESOURCE_IRQ_HIGHEDGE:
-		*edge_level = ACPI_EDGE_SENSITIVE;
-		*active_high_low = ACPI_ACTIVE_HIGH;
+		*triggering = ACPI_EDGE_SENSITIVE;
+		*polarity = ACPI_ACTIVE_HIGH;
 		break;
 	}
 }
 
 static void
 pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
-	int edge_level, int active_high_low)
+	int triggering, int polarity)
 {
 	int i = 0;
 	int irq;
@@ -89,7 +89,7 @@
 		return;
 
 	res->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
-	irq = acpi_register_gsi(gsi, edge_level, active_high_low);
+	irq = acpi_register_gsi(gsi, triggering, polarity);
 	if (irq < 0) {
 		res->irq_resource[i].flags |= IORESOURCE_DISABLED;
 		return;
@@ -163,77 +163,96 @@
 	struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
 	int i;
 
-	switch (res->id) {
-	case ACPI_RSTYPE_IRQ:
+	switch (res->type) {
+	case ACPI_RESOURCE_TYPE_IRQ:
 		/*
 		 * Per spec, only one interrupt per descriptor is allowed in
 		 * _CRS, but some firmware violates this, so parse them all.
 		 */
-		for (i = 0; i < res->data.irq.number_of_interrupts; i++) {
+		for (i = 0; i < res->data.irq.interrupt_count; i++) {
 			pnpacpi_parse_allocated_irqresource(res_table,
 				res->data.irq.interrupts[i],
-				res->data.irq.edge_level,
-				res->data.irq.active_high_low);
+				res->data.irq.triggering,
+				res->data.irq.polarity);
 		}
 		break;
 
-	case ACPI_RSTYPE_EXT_IRQ:
-		for (i = 0; i < res->data.extended_irq.number_of_interrupts; i++) {
-			pnpacpi_parse_allocated_irqresource(res_table,
-				res->data.extended_irq.interrupts[i],
-				res->data.extended_irq.edge_level,
-				res->data.extended_irq.active_high_low);
-		}
-		break;
-	case ACPI_RSTYPE_DMA:
-		if (res->data.dma.number_of_channels > 0)
-			pnpacpi_parse_allocated_dmaresource(res_table, 
+	case ACPI_RESOURCE_TYPE_DMA:
+		if (res->data.dma.channel_count > 0)
+			pnpacpi_parse_allocated_dmaresource(res_table,
 					res->data.dma.channels[0]);
 		break;
-	case ACPI_RSTYPE_IO:
-		pnpacpi_parse_allocated_ioresource(res_table, 
-				res->data.io.min_base_address, 
-				res->data.io.range_length);
+
+	case ACPI_RESOURCE_TYPE_IO:
+		pnpacpi_parse_allocated_ioresource(res_table,
+				res->data.io.minimum,
+				res->data.io.address_length);
 		break;
-	case ACPI_RSTYPE_FIXED_IO:
-		pnpacpi_parse_allocated_ioresource(res_table, 
-				res->data.fixed_io.base_address, 
-				res->data.fixed_io.range_length);
+
+	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 		break;
-	case ACPI_RSTYPE_MEM24:
-		pnpacpi_parse_allocated_memresource(res_table, 
-				res->data.memory24.min_base_address, 
-				res->data.memory24.range_length);
+
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		pnpacpi_parse_allocated_ioresource(res_table,
+				res->data.fixed_io.address,
+				res->data.fixed_io.address_length);
 		break;
-	case ACPI_RSTYPE_MEM32:
-		pnpacpi_parse_allocated_memresource(res_table, 
-				res->data.memory32.min_base_address, 
-				res->data.memory32.range_length);
+
+	case ACPI_RESOURCE_TYPE_VENDOR:
 		break;
-	case ACPI_RSTYPE_FIXED_MEM32:
-		pnpacpi_parse_allocated_memresource(res_table, 
-				res->data.fixed_memory32.range_base_address, 
-				res->data.fixed_memory32.range_length);
+
+	case ACPI_RESOURCE_TYPE_END_TAG:
 		break;
-	case ACPI_RSTYPE_ADDRESS16:
-		pnpacpi_parse_allocated_memresource(res_table, 
-				res->data.address16.min_address_range, 
+
+	case ACPI_RESOURCE_TYPE_MEMORY24:
+		pnpacpi_parse_allocated_memresource(res_table,
+				res->data.memory24.minimum,
+				res->data.memory24.address_length);
+		break;
+	case ACPI_RESOURCE_TYPE_MEMORY32:
+		pnpacpi_parse_allocated_memresource(res_table,
+				res->data.memory32.minimum,
+				res->data.memory32.address_length);
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+		pnpacpi_parse_allocated_memresource(res_table,
+				res->data.fixed_memory32.address,
+				res->data.fixed_memory32.address_length);
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+		pnpacpi_parse_allocated_memresource(res_table,
+				res->data.address16.minimum,
 				res->data.address16.address_length);
 		break;
-	case ACPI_RSTYPE_ADDRESS32:
-		pnpacpi_parse_allocated_memresource(res_table, 
-				res->data.address32.min_address_range, 
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+		pnpacpi_parse_allocated_memresource(res_table,
+				res->data.address32.minimum,
 				res->data.address32.address_length);
 		break;
-	case ACPI_RSTYPE_ADDRESS64:
-		pnpacpi_parse_allocated_memresource(res_table, 
-		res->data.address64.min_address_range, 
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		pnpacpi_parse_allocated_memresource(res_table,
+		res->data.address64.minimum,
 		res->data.address64.address_length);
 		break;
-	case ACPI_RSTYPE_VENDOR:
+
+	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 		break;
+
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+		for (i = 0; i < res->data.extended_irq.interrupt_count; i++) {
+			pnpacpi_parse_allocated_irqresource(res_table,
+				res->data.extended_irq.interrupts[i],
+				res->data.extended_irq.triggering,
+				res->data.extended_irq.polarity);
+		}
+		break;
+
+	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
+		break;
+
 	default:
-		pnp_warn("PnPACPI: unknown resource type %d", res->id);
+		pnp_warn("PnPACPI: unknown resource type %d", res->type);
 		return AE_ERROR;
 	}
 			
@@ -253,13 +272,13 @@
 	int i;
 	struct pnp_dma * dma;
 
-	if (p->number_of_channels == 0)
+	if (p->channel_count == 0)
 		return;
 	dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
 	if (!dma)
 		return;
 
-	for(i = 0; i < p->number_of_channels; i++)
+	for(i = 0; i < p->channel_count; i++)
 		dma->map |= 1 << p->channels[i];
 	dma->flags = 0;
 	if (p->bus_master)
@@ -309,37 +328,37 @@
 	int i;
 	struct pnp_irq * irq;
 	
-	if (p->number_of_interrupts == 0)
+	if (p->interrupt_count == 0)
 		return;
 	irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
 	if (!irq)
 		return;
 
-	for(i = 0; i < p->number_of_interrupts; i++)
+	for(i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[i])
 			__set_bit(p->interrupts[i], irq->map);
-	irq->flags = irq_flags(p->edge_level, p->active_high_low);
+	irq->flags = irq_flags(p->triggering, p->polarity);
 
 	pnp_register_irq_resource(option, irq);
 	return;
 }
 
 static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
-	struct acpi_resource_ext_irq *p)
+	struct acpi_resource_extended_irq *p)
 {
 	int i;
 	struct pnp_irq * irq;
 
-	if (p->number_of_interrupts == 0)
+	if (p->interrupt_count == 0)
 		return;
 	irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
 	if (!irq)
 		return;
 
-	for(i = 0; i < p->number_of_interrupts; i++)
+	for(i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[i])
 			__set_bit(p->interrupts[i], irq->map);
-	irq->flags = irq_flags(p->edge_level, p->active_high_low);
+	irq->flags = irq_flags(p->triggering, p->polarity);
 
 	pnp_register_irq_resource(option, irq);
 	return;
@@ -351,16 +370,16 @@
 {
 	struct pnp_port * port;
 
-	if (io->range_length == 0)
+	if (io->address_length == 0)
 		return;
 	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
 	if (!port)
 		return;
-	port->min = io->min_base_address;
-	port->max = io->max_base_address;
+	port->min = io->minimum;
+	port->max = io->maximum;
 	port->align = io->alignment;
-	port->size = io->range_length;
-	port->flags = ACPI_DECODE_16 == io->io_decode ? 
+	port->size = io->address_length;
+	port->flags = ACPI_DECODE_16 == io->io_decode ?
 		PNP_PORT_FLAG_16BITADDR : 0;
 	pnp_register_port_resource(option,port);
 	return;
@@ -372,13 +391,13 @@
 {
 	struct pnp_port * port;
 
-	if (io->range_length == 0)
+	if (io->address_length == 0)
 		return;
 	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
 	if (!port)
 		return;
-	port->min = port->max = io->base_address;
-	port->size = io->range_length;
+	port->min = port->max = io->address;
+	port->size = io->address_length;
 	port->align = 0;
 	port->flags = PNP_PORT_FLAG_FIXED;
 	pnp_register_port_resource(option,port);
@@ -387,21 +406,21 @@
 
 static void
 pnpacpi_parse_mem24_option(struct pnp_option *option,
-	struct acpi_resource_mem24 *p)
+	struct acpi_resource_memory24 *p)
 {
 	struct pnp_mem * mem;
 
-	if (p->range_length == 0)
+	if (p->address_length == 0)
 		return;
 	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
-	mem->min = p->min_base_address;
-	mem->max = p->max_base_address;
+	mem->min = p->minimum;
+	mem->max = p->maximum;
 	mem->align = p->alignment;
-	mem->size = p->range_length;
+	mem->size = p->address_length;
 
-	mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
+	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
 			IORESOURCE_MEM_WRITEABLE : 0;
 
 	pnp_register_mem_resource(option,mem);
@@ -410,21 +429,21 @@
 
 static void
 pnpacpi_parse_mem32_option(struct pnp_option *option,
-	struct acpi_resource_mem32 *p)
+	struct acpi_resource_memory32 *p)
 {
 	struct pnp_mem * mem;
 
-	if (p->range_length == 0)
+	if (p->address_length == 0)
 		return;
 	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
-	mem->min = p->min_base_address;
-	mem->max = p->max_base_address;
+	mem->min = p->minimum;
+	mem->max = p->maximum;
 	mem->align = p->alignment;
-	mem->size = p->range_length;
+	mem->size = p->address_length;
 
-	mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
+	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
 			IORESOURCE_MEM_WRITEABLE : 0;
 
 	pnp_register_mem_resource(option,mem);
@@ -433,33 +452,72 @@
 
 static void
 pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
-	struct acpi_resource_fixed_mem32 *p)
+	struct acpi_resource_fixed_memory32 *p)
 {
 	struct pnp_mem * mem;
 
-	if (p->range_length == 0)
+	if (p->address_length == 0)
 		return;
 	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
-	mem->min = mem->max = p->range_base_address;
-	mem->size = p->range_length;
+	mem->min = mem->max = p->address;
+	mem->size = p->address_length;
 	mem->align = 0;
 
-	mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
+	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
 			IORESOURCE_MEM_WRITEABLE : 0;
 
 	pnp_register_mem_resource(option,mem);
 	return;
 }
 
+static void
+pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r)
+{
+	struct acpi_resource_address64 addr, *p = &addr;
+	acpi_status status;
+	struct pnp_mem * mem;
+	struct pnp_port * port;
+
+	status = acpi_resource_to_address64(r, p);
+	if (!ACPI_SUCCESS(status)) {
+		pnp_warn("PnPACPI: failed to convert resource type %d", r->type);
+		return;
+	}
+
+	if (p->address_length == 0)
+		return;
+
+	if (p->resource_type == ACPI_MEMORY_RANGE) {
+		mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+		if (!mem)
+			return;
+		mem->min = mem->max = p->minimum;
+		mem->size = p->address_length;
+		mem->align = 0;
+		mem->flags = (p->info.mem.write_protect ==
+		    ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0;
+		pnp_register_mem_resource(option,mem);
+	} else if (p->resource_type == ACPI_IO_RANGE) {
+		port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+		if (!port)
+			return;
+		port->min = port->max = p->minimum;
+		port->size = p->address_length;
+		port->align = 0;
+		port->flags = PNP_PORT_FLAG_FIXED;
+		pnp_register_port_resource(option,port);
+	}
+}
+
 struct acpipnp_parse_option_s {
 	struct pnp_option *option;
 	struct pnp_option *option_independent;
 	struct pnp_dev *dev;
 };
 
-static acpi_status pnpacpi_option_resource(struct acpi_resource *res, 
+static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
 	void *data)
 {
 	int priority = 0;
@@ -467,35 +525,16 @@
 	struct pnp_dev *dev = parse_data->dev;
 	struct pnp_option *option = parse_data->option;
 
-	switch (res->id) {
-		case ACPI_RSTYPE_IRQ:
+	switch (res->type) {
+		case ACPI_RESOURCE_TYPE_IRQ:
 			pnpacpi_parse_irq_option(option, &res->data.irq);
 			break;
-		case ACPI_RSTYPE_EXT_IRQ:
-			pnpacpi_parse_ext_irq_option(option,
-				&res->data.extended_irq);
-			break;
-		case ACPI_RSTYPE_DMA:
+
+		case ACPI_RESOURCE_TYPE_DMA:
 			pnpacpi_parse_dma_option(option, &res->data.dma);	
 			break;
-		case ACPI_RSTYPE_IO:
-			pnpacpi_parse_port_option(option, &res->data.io);
-			break;
-		case ACPI_RSTYPE_FIXED_IO:
-			pnpacpi_parse_fixed_port_option(option,
-				&res->data.fixed_io);
-			break;
-		case ACPI_RSTYPE_MEM24:
-			pnpacpi_parse_mem24_option(option, &res->data.memory24);
-			break;
-		case ACPI_RSTYPE_MEM32:
-			pnpacpi_parse_mem32_option(option, &res->data.memory32);
-			break;
-		case ACPI_RSTYPE_FIXED_MEM32:
-			pnpacpi_parse_fixed_mem32_option(option,
-				&res->data.fixed_memory32);
-			break;
-		case ACPI_RSTYPE_START_DPF:
+
+		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 			switch (res->data.start_dpf.compatibility_priority) {
 				case ACPI_GOOD_CONFIGURATION:
 					priority = PNP_RES_PRIORITY_PREFERRED;
@@ -518,7 +557,8 @@
 				return AE_ERROR;
 			parse_data->option = option;	
 			break;
-		case ACPI_RSTYPE_END_DPF:
+
+		case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 			/*only one EndDependentFn is allowed*/
 			if (!parse_data->option_independent) {
 				pnp_warn("PnPACPI: more than one EndDependentFn");
@@ -527,15 +567,59 @@
 			parse_data->option = parse_data->option_independent;
 			parse_data->option_independent = NULL;
 			break;
+
+		case ACPI_RESOURCE_TYPE_IO:
+			pnpacpi_parse_port_option(option, &res->data.io);
+			break;
+
+		case ACPI_RESOURCE_TYPE_FIXED_IO:
+			pnpacpi_parse_fixed_port_option(option,
+				&res->data.fixed_io);
+			break;
+
+		case ACPI_RESOURCE_TYPE_VENDOR:
+		case ACPI_RESOURCE_TYPE_END_TAG:
+			break;
+
+		case ACPI_RESOURCE_TYPE_MEMORY24:
+			pnpacpi_parse_mem24_option(option, &res->data.memory24);
+			break;
+
+		case ACPI_RESOURCE_TYPE_MEMORY32:
+			pnpacpi_parse_mem32_option(option, &res->data.memory32);
+			break;
+
+		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+			pnpacpi_parse_fixed_mem32_option(option,
+				&res->data.fixed_memory32);
+			break;
+
+		case ACPI_RESOURCE_TYPE_ADDRESS16:
+		case ACPI_RESOURCE_TYPE_ADDRESS32:
+		case ACPI_RESOURCE_TYPE_ADDRESS64:
+			pnpacpi_parse_address_option(option, res);
+			break;
+
+		case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+			break;
+
+		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+			pnpacpi_parse_ext_irq_option(option,
+				&res->data.extended_irq);
+			break;
+
+		case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
+			break;
+
 		default:
-			pnp_warn("PnPACPI: unknown resource type %d", res->id);
+			pnp_warn("PnPACPI: unknown resource type %d", res->type);
 			return AE_ERROR;
 	}
 			
 	return AE_OK;
 }
 
-acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, 
+acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
 	struct pnp_dev *dev)
 {
 	acpi_status status;
@@ -546,7 +630,7 @@
 		return AE_ERROR;
 	parse_data.option_independent = parse_data.option;
 	parse_data.dev = dev;
-	status = acpi_walk_resources(handle, METHOD_NAME__PRS, 
+	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
 		pnpacpi_option_resource, &parse_data);
 
 	return status;
@@ -559,21 +643,24 @@
 	void *data)
 {
 	int *res_cnt = (int *)data;
-	switch (res->id) {
-	case ACPI_RSTYPE_IRQ:
-	case ACPI_RSTYPE_EXT_IRQ:
-	case ACPI_RSTYPE_DMA:
-	case ACPI_RSTYPE_IO:
-	case ACPI_RSTYPE_FIXED_IO:
-	case ACPI_RSTYPE_MEM24:
-	case ACPI_RSTYPE_MEM32:
-	case ACPI_RSTYPE_FIXED_MEM32:
-#if 0
-	case ACPI_RSTYPE_ADDRESS16:
-	case ACPI_RSTYPE_ADDRESS32:
-	case ACPI_RSTYPE_ADDRESS64:
-#endif
+	switch (res->type) {
+	case ACPI_RESOURCE_TYPE_IRQ:
+	case ACPI_RESOURCE_TYPE_DMA:
+	case ACPI_RESOURCE_TYPE_IO:
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+	case ACPI_RESOURCE_TYPE_MEMORY24:
+	case ACPI_RESOURCE_TYPE_MEMORY32:
+	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		(*res_cnt) ++;
+	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+	case ACPI_RESOURCE_TYPE_VENDOR:
+	case ACPI_RESOURCE_TYPE_END_TAG:
+	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 	default:
 		return AE_OK;
 	}
@@ -584,22 +671,25 @@
 	void *data)
 {
 	struct acpi_resource **resource = (struct acpi_resource **)data;	
-	switch (res->id) {
-	case ACPI_RSTYPE_IRQ:
-	case ACPI_RSTYPE_EXT_IRQ:
-	case ACPI_RSTYPE_DMA:
-	case ACPI_RSTYPE_IO:
-	case ACPI_RSTYPE_FIXED_IO:
-	case ACPI_RSTYPE_MEM24:
-	case ACPI_RSTYPE_MEM32:
-	case ACPI_RSTYPE_FIXED_MEM32:
-#if 0
-	case ACPI_RSTYPE_ADDRESS16:
-	case ACPI_RSTYPE_ADDRESS32:
-	case ACPI_RSTYPE_ADDRESS64:
-#endif
-		(*resource)->id = res->id;
+	switch (res->type) {
+	case ACPI_RESOURCE_TYPE_IRQ:
+	case ACPI_RESOURCE_TYPE_DMA:
+	case ACPI_RESOURCE_TYPE_IO:
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+	case ACPI_RESOURCE_TYPE_MEMORY24:
+	case ACPI_RESOURCE_TYPE_MEMORY32:
+	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+		(*resource)->type = res->type;
 		(*resource)++;
+	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+	case ACPI_RESOURCE_TYPE_VENDOR:
+	case ACPI_RESOURCE_TYPE_END_TAG:
+	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 	default:
 		return AE_OK;
 	}
@@ -607,14 +697,14 @@
 	return AE_OK;
 }
 
-int pnpacpi_build_resource_template(acpi_handle handle, 
+int pnpacpi_build_resource_template(acpi_handle handle,
 	struct acpi_buffer *buffer)
 {
 	struct acpi_resource *resource;
 	int res_cnt = 0;
 	acpi_status status;
 
-	status = acpi_walk_resources(handle, METHOD_NAME__CRS, 
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
 		pnpacpi_count_resources, &res_cnt);
 	if (ACPI_FAILURE(status)) {
 		pnp_err("Evaluate _CRS failed");
@@ -628,7 +718,7 @@
 		return -ENOMEM;
 	pnp_dbg("Res cnt %d", res_cnt);
 	resource = (struct acpi_resource *)buffer->pointer;
-	status = acpi_walk_resources(handle, METHOD_NAME__CRS, 
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
 		pnpacpi_type_resources, &resource);
 	if (ACPI_FAILURE(status)) {
 		kfree(buffer->pointer);
@@ -636,54 +726,54 @@
 		return -EINVAL;
 	}
 	/* resource will pointer the end resource now */
-	resource->id = ACPI_RSTYPE_END_TAG;
+	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
 
 	return 0;
 }
 
-static void pnpacpi_encode_irq(struct acpi_resource *resource, 
+static void pnpacpi_encode_irq(struct acpi_resource *resource,
 	struct resource *p)
 {
-	int edge_level, active_high_low;
+	int triggering, polarity;
 	
-	decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, 
-		&active_high_low);
-	resource->id = ACPI_RSTYPE_IRQ;
+	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
+		&polarity);
+	resource->type = ACPI_RESOURCE_TYPE_IRQ;
 	resource->length = sizeof(struct acpi_resource);
-	resource->data.irq.edge_level = edge_level;
-	resource->data.irq.active_high_low = active_high_low;
-	if (edge_level == ACPI_EDGE_SENSITIVE)
-		resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+	resource->data.irq.triggering = triggering;
+	resource->data.irq.polarity = polarity;
+	if (triggering == ACPI_EDGE_SENSITIVE)
+		resource->data.irq.sharable = ACPI_EXCLUSIVE;
 	else
-		resource->data.irq.shared_exclusive = ACPI_SHARED;
-	resource->data.irq.number_of_interrupts = 1;
+		resource->data.irq.sharable = ACPI_SHARED;
+	resource->data.irq.interrupt_count = 1;
 	resource->data.irq.interrupts[0] = p->start;
 }
 
 static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
 	struct resource *p)
 {
-	int edge_level, active_high_low;
+	int triggering, polarity;
 	
-	decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, 
-		&active_high_low);
-	resource->id = ACPI_RSTYPE_EXT_IRQ;
+	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
+		&polarity);
+	resource->type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
 	resource->length = sizeof(struct acpi_resource);
 	resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
-	resource->data.extended_irq.edge_level = edge_level;
-	resource->data.extended_irq.active_high_low = active_high_low;
-	if (edge_level == ACPI_EDGE_SENSITIVE)
-		resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+	resource->data.extended_irq.triggering = triggering;
+	resource->data.extended_irq.polarity = polarity;
+	if (triggering == ACPI_EDGE_SENSITIVE)
+		resource->data.irq.sharable = ACPI_EXCLUSIVE;
 	else
-		resource->data.irq.shared_exclusive = ACPI_SHARED;
-	resource->data.extended_irq.number_of_interrupts = 1;
+		resource->data.irq.sharable = ACPI_SHARED;
+	resource->data.extended_irq.interrupt_count = 1;
 	resource->data.extended_irq.interrupts[0] = p->start;
 }
 
 static void pnpacpi_encode_dma(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->id = ACPI_RSTYPE_DMA;
+	resource->type = ACPI_RESOURCE_TYPE_DMA;
 	resource->length = sizeof(struct acpi_resource);
 	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
 	if (p->flags & IORESOURCE_DMA_COMPATIBLE)
@@ -701,75 +791,75 @@
 	else if (p->flags & IORESOURCE_DMA_16BIT)
 		resource->data.dma.transfer = ACPI_TRANSFER_16;
 	resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER;
-	resource->data.dma.number_of_channels = 1;
+	resource->data.dma.channel_count = 1;
 	resource->data.dma.channels[0] = p->start;
 }
 
 static void pnpacpi_encode_io(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->id = ACPI_RSTYPE_IO;
+	resource->type = ACPI_RESOURCE_TYPE_IO;
 	resource->length = sizeof(struct acpi_resource);
 	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
 	resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)?
-		ACPI_DECODE_16 : ACPI_DECODE_10; 
-	resource->data.io.min_base_address = p->start;
-	resource->data.io.max_base_address = p->end;
+		ACPI_DECODE_16 : ACPI_DECODE_10;
+	resource->data.io.minimum = p->start;
+	resource->data.io.maximum = p->end;
 	resource->data.io.alignment = 0; /* Correct? */
-	resource->data.io.range_length = p->end - p->start + 1;
+	resource->data.io.address_length = p->end - p->start + 1;
 }
 
 static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->id = ACPI_RSTYPE_FIXED_IO;
+	resource->type = ACPI_RESOURCE_TYPE_FIXED_IO;
 	resource->length = sizeof(struct acpi_resource);
-	resource->data.fixed_io.base_address = p->start;
-	resource->data.fixed_io.range_length = p->end - p->start + 1;
+	resource->data.fixed_io.address = p->start;
+	resource->data.fixed_io.address_length = p->end - p->start + 1;
 }
 
 static void pnpacpi_encode_mem24(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->id = ACPI_RSTYPE_MEM24;
+	resource->type = ACPI_RESOURCE_TYPE_MEMORY24;
 	resource->length = sizeof(struct acpi_resource);
 	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
-	resource->data.memory24.read_write_attribute =
+	resource->data.memory24.write_protect =
 		(p->flags & IORESOURCE_MEM_WRITEABLE) ?
 		ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
-	resource->data.memory24.min_base_address = p->start;
-	resource->data.memory24.max_base_address = p->end;
+	resource->data.memory24.minimum = p->start;
+	resource->data.memory24.maximum = p->end;
 	resource->data.memory24.alignment = 0;
-	resource->data.memory24.range_length = p->end - p->start + 1;
+	resource->data.memory24.address_length = p->end - p->start + 1;
 }
 
 static void pnpacpi_encode_mem32(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->id = ACPI_RSTYPE_MEM32;
+	resource->type = ACPI_RESOURCE_TYPE_MEMORY32;
 	resource->length = sizeof(struct acpi_resource);
-	resource->data.memory32.read_write_attribute =
+	resource->data.memory32.write_protect =
 		(p->flags & IORESOURCE_MEM_WRITEABLE) ?
 		ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
-	resource->data.memory32.min_base_address = p->start;
-	resource->data.memory32.max_base_address = p->end;
+	resource->data.memory32.minimum = p->start;
+	resource->data.memory32.maximum = p->end;
 	resource->data.memory32.alignment = 0;
-	resource->data.memory32.range_length = p->end - p->start + 1;
+	resource->data.memory32.address_length = p->end - p->start + 1;
 }
 
 static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->id = ACPI_RSTYPE_FIXED_MEM32;
+	resource->type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32;
 	resource->length = sizeof(struct acpi_resource);
-	resource->data.fixed_memory32.read_write_attribute =
+	resource->data.fixed_memory32.write_protect =
 		(p->flags & IORESOURCE_MEM_WRITEABLE) ?
 		ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
-	resource->data.fixed_memory32.range_base_address = p->start;
-	resource->data.fixed_memory32.range_length = p->end - p->start + 1;
+	resource->data.fixed_memory32.address = p->start;
+	resource->data.fixed_memory32.address_length = p->end - p->start + 1;
 }
 
-int pnpacpi_encode_resources(struct pnp_resource_table *res_table, 
+int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
 	struct acpi_buffer *buffer)
 {
 	int i = 0;
@@ -780,58 +870,67 @@
 
 	pnp_dbg("res cnt %d", res_cnt);
 	while (i < res_cnt) {
-		switch(resource->id) {
-		case ACPI_RSTYPE_IRQ:
+		switch(resource->type) {
+		case ACPI_RESOURCE_TYPE_IRQ:
 			pnp_dbg("Encode irq");
-			pnpacpi_encode_irq(resource, 
+			pnpacpi_encode_irq(resource,
 				&res_table->irq_resource[irq]);
 			irq++;
 			break;
 
-		case ACPI_RSTYPE_EXT_IRQ:
-			pnp_dbg("Encode ext irq");
-			pnpacpi_encode_ext_irq(resource, 
-				&res_table->irq_resource[irq]);
-			irq++;
-			break;
-		case ACPI_RSTYPE_DMA:
+		case ACPI_RESOURCE_TYPE_DMA:
 			pnp_dbg("Encode dma");
-			pnpacpi_encode_dma(resource, 
+			pnpacpi_encode_dma(resource,
 				&res_table->dma_resource[dma]);
 			dma ++;
 			break;
-		case ACPI_RSTYPE_IO:
+		case ACPI_RESOURCE_TYPE_IO:
 			pnp_dbg("Encode io");
-			pnpacpi_encode_io(resource, 
+			pnpacpi_encode_io(resource,
 				&res_table->port_resource[port]);
 			port ++;
 			break;
-		case ACPI_RSTYPE_FIXED_IO:
+		case ACPI_RESOURCE_TYPE_FIXED_IO:
 			pnp_dbg("Encode fixed io");
 			pnpacpi_encode_fixed_io(resource,
 				&res_table->port_resource[port]);
 			port ++;
 			break;
-		case ACPI_RSTYPE_MEM24:
+		case ACPI_RESOURCE_TYPE_MEMORY24:
 			pnp_dbg("Encode mem24");
 			pnpacpi_encode_mem24(resource,
 				&res_table->mem_resource[mem]);
 			mem ++;
 			break;
-		case ACPI_RSTYPE_MEM32:
+		case ACPI_RESOURCE_TYPE_MEMORY32:
 			pnp_dbg("Encode mem32");
 			pnpacpi_encode_mem32(resource,
 				&res_table->mem_resource[mem]);
 			mem ++;
 			break;
-		case ACPI_RSTYPE_FIXED_MEM32:
+		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 			pnp_dbg("Encode fixed mem32");
 			pnpacpi_encode_fixed_mem32(resource,
 				&res_table->mem_resource[mem]);
 			mem ++;
 			break;
+		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+			pnp_dbg("Encode ext irq");
+			pnpacpi_encode_ext_irq(resource,
+				&res_table->irq_resource[irq]);
+			irq++;
+			break;
+		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+		case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+		case ACPI_RESOURCE_TYPE_VENDOR:
+		case ACPI_RESOURCE_TYPE_END_TAG:
+		case ACPI_RESOURCE_TYPE_ADDRESS16:
+		case ACPI_RESOURCE_TYPE_ADDRESS32:
+		case ACPI_RESOURCE_TYPE_ADDRESS64:
+		case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 		default: /* other type */
-			pnp_warn("unknown resource type %d", resource->id);
+			pnp_warn("unknown resource type %d", resource->type);
 			return -EINVAL;
 		}
 		resource ++;
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig
index a86a650..721787c 100644
--- a/drivers/s390/Kconfig
+++ b/drivers/s390/Kconfig
@@ -51,6 +51,13 @@
 	  When not in use, each additional set of 256 PTYs occupy
 	  approximately 8 KB of kernel memory on 32-bit architectures.
 
+config HANGCHECK_TIMER
+	tristate "Hangcheck timer"
+	help
+	  The hangcheck-timer module detects when the system has gone
+	  out to lunch past a certain margin.  It can reboot the system
+	  or merely print a warning.
+
 source "drivers/char/watchdog/Kconfig"
 
 comment "S/390 character device drivers"
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 6f50cc9..6912399 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -55,13 +55,21 @@
 	  Disks under VM.  If you are not running under VM or unsure what it is,
 	  say "N".
 
+config DASD_EER
+	tristate "Extended error reporting (EER)"
+	depends on DASD
+	help
+	  This driver provides a character device interface to the
+          DASD extended error reporting. This is only needed if you want to
+          use applications written for the EER facility.
+
 config DASD_CMB
 	tristate "Compatibility interface for DASD channel measurement blocks"
 	depends on DASD
 	help
-	  This driver provides an additional interface to the channel measurement
-	  facility, which is normally accessed though sysfs, with a set of
-	  ioctl functions specific to the dasd driver.
+	  This driver provides an additional interface to the channel
+          measurement facility, which is normally accessed though sysfs, with
+          a set of ioctl functions specific to the dasd driver.
 	  This is only needed if you want to use applications written for
 	  linux-2.4 dasd channel measurement facility interface.
 
diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile
index 58c6780..0c0d871 100644
--- a/drivers/s390/block/Makefile
+++ b/drivers/s390/block/Makefile
@@ -5,6 +5,7 @@
 dasd_eckd_mod-objs := dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o
 dasd_fba_mod-objs  := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o
 dasd_diag_mod-objs := dasd_diag.o
+dasd_eer_mod-objs := dasd_eer.o
 dasd_mod-objs      := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \
 			dasd_genhd.o dasd_erp.o
 
@@ -13,5 +14,6 @@
 obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o
 obj-$(CONFIG_DASD_FBA)  += dasd_fba_mod.o
 obj-$(CONFIG_DASD_CMB)  += dasd_cmb.o
+obj-$(CONFIG_DASD_EER)  += dasd_eer.o
 obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o
 obj-$(CONFIG_DCSSBLK) += dcssblk.o
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index ef4c687..08c88fc 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.172 $
  */
 
 #include <linux/config.h>
@@ -19,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
 #include <linux/hdreg.h>
+#include <linux/notifier.h>
 
 #include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
@@ -58,6 +58,7 @@
 static void dasd_flush_ccw_queue(struct dasd_device *, int);
 static void dasd_tasklet(struct dasd_device *);
 static void do_kick_device(void *data);
+static void dasd_disable_eer(struct dasd_device *device);
 
 /*
  * SECTION: Operations on the device structure.
@@ -152,6 +153,8 @@
 static inline void
 dasd_state_known_to_new(struct dasd_device * device)
 {
+	/* disable extended error reporting for this device */
+	dasd_disable_eer(device);
 	/* Forget the discipline information. */
 	device->discipline = NULL;
 	device->state = DASD_STATE_NEW;
@@ -675,11 +678,8 @@
 		rc = ccw_device_clear(device->cdev, (long) cqr);
 		switch (rc) {
 		case 0:	/* termination successful */
-		        if (cqr->retries > 0) {
-				cqr->retries--;
-				cqr->status = DASD_CQR_CLEAR;
-			} else
-				cqr->status = DASD_CQR_FAILED;
+			cqr->retries--;
+			cqr->status = DASD_CQR_CLEAR;
 			cqr->stopclk = get_clock();
 			DBF_DEV_EVENT(DBF_DEBUG, device,
 				      "terminate cqr %p successful",
@@ -871,6 +871,9 @@
 	struct dasd_ccw_req *cqr;
 	struct list_head *l, *n;
 
+	/* first of all call extended error reporting */
+	dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL);
+
 	device->stopped &= ~DASD_STOPPED_PENDING;
 
         /* restart all 'running' IO on queue */
@@ -1090,6 +1093,19 @@
 			}
 			goto restart;
 		}
+
+		/* first of all call extended error reporting */
+		if (device->eer && cqr->status == DASD_CQR_FAILED) {
+			dasd_write_eer_trigger(DASD_EER_FATALERROR,
+					       device, cqr);
+
+			/* restart request  */
+			cqr->status = DASD_CQR_QUEUED;
+			cqr->retries = 255;
+			device->stopped |= DASD_STOPPED_QUIESCE;
+			goto restart;
+		}
+
 		/* Process finished ERP request. */
 		if (cqr->refers) {
 			__dasd_process_erp(device, cqr);
@@ -1227,7 +1243,8 @@
 	cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
         /* check FAILFAST */
 	if (device->stopped & ~DASD_STOPPED_PENDING &&
-	    test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) {
+	    test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
+	    (!device->eer)) {
 		cqr->status = DASD_CQR_FAILED;
 		dasd_schedule_bh(device);
 	}
@@ -1308,7 +1325,7 @@
 	/* Now call the callback function of requests with final status */
 	list_for_each_safe(l, n, &final_queue) {
 		cqr = list_entry(l, struct dasd_ccw_req, list);
-		list_del(&cqr->list);
+		list_del_init(&cqr->list);
 		if (cqr->callback != NULL)
 			(cqr->callback)(cqr, cqr->callback_data);
 	}
@@ -1393,7 +1410,9 @@
 
 	device = cqr->device;
 	spin_lock_irq(get_ccwdev_lock(device->cdev));
-	rc = cqr->status == DASD_CQR_DONE || cqr->status == DASD_CQR_FAILED;
+	rc = ((cqr->status == DASD_CQR_DONE ||
+	       cqr->status == DASD_CQR_FAILED) &&
+	      list_empty(&cqr->list));
 	spin_unlock_irq(get_ccwdev_lock(device->cdev));
 	return rc;
 }
@@ -1457,15 +1476,37 @@
 	while (!finished) {
 		rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr));
 		if (rc != -ERESTARTSYS) {
-			/* Request status is either done or failed. */
-			rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0;
+			/* Request is final (done or failed) */
+			rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
 			break;
 		}
 		spin_lock_irq(get_ccwdev_lock(device->cdev));
-		if (cqr->status == DASD_CQR_IN_IO &&
-		    device->discipline->term_IO(cqr) == 0) {
-			list_del(&cqr->list);
+		switch (cqr->status) {
+		case DASD_CQR_IN_IO:
+                        /* terminate runnig cqr */
+			if (device->discipline->term_IO) {
+				cqr->retries = -1;
+				device->discipline->term_IO(cqr);
+				/*nished =
+				 * wait (non-interruptible) for final status
+				 * because signal ist still pending
+				 */
+				spin_unlock_irq(get_ccwdev_lock(device->cdev));
+				wait_event(wait_q, _wait_for_wakeup(cqr));
+				spin_lock_irq(get_ccwdev_lock(device->cdev));
+				rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
+				finished = 1;
+			}
+			break;
+		case DASD_CQR_QUEUED:
+			/* request  */
+			list_del_init(&cqr->list);
+			rc = -EIO;
 			finished = 1;
+			break;
+		default:
+			/* cqr with 'non-interruptable' status - just wait */
+			break;
 		}
 		spin_unlock_irq(get_ccwdev_lock(device->cdev));
 	}
@@ -1945,6 +1986,9 @@
 	switch (event) {
 	case CIO_GONE:
 	case CIO_NO_PATH:
+		/* first of all call extended error reporting */
+		dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL);
+
 		if (device->state < DASD_STATE_BASIC)
 			break;
 		/* Device is active. We want to keep it. */
@@ -2002,6 +2046,51 @@
 	put_driver(drv);
 }
 
+/*
+ * notifications for extended error reports
+ */
+static struct notifier_block *dasd_eer_chain;
+
+int
+dasd_register_eer_notifier(struct notifier_block *nb)
+{
+	return notifier_chain_register(&dasd_eer_chain, nb);
+}
+
+int
+dasd_unregister_eer_notifier(struct notifier_block *nb)
+{
+	return notifier_chain_unregister(&dasd_eer_chain, nb);
+}
+
+/*
+ * Notify the registered error reporting module of a problem
+ */
+void
+dasd_write_eer_trigger(unsigned int id, struct dasd_device *device,
+		       struct dasd_ccw_req *cqr)
+{
+	if (device->eer) {
+		struct dasd_eer_trigger temp;
+		temp.id = id;
+		temp.device = device;
+		temp.cqr = cqr;
+		notifier_call_chain(&dasd_eer_chain, DASD_EER_TRIGGER,
+				    (void *)&temp);
+	}
+}
+
+/*
+ * Tell the registered error reporting module to disable error reporting for
+ * a given device and to cleanup any private data structures on that device.
+ */
+static void
+dasd_disable_eer(struct dasd_device *device)
+{
+	notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device);
+}
+
+
 static int __init
 dasd_init(void)
 {
@@ -2083,6 +2172,11 @@
 EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
 EXPORT_SYMBOL_GPL(dasd_generic_auto_online);
 
+EXPORT_SYMBOL(dasd_register_eer_notifier);
+EXPORT_SYMBOL(dasd_unregister_eer_notifier);
+EXPORT_SYMBOL(dasd_write_eer_trigger);
+
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/drivers/s390/block/dasd_3370_erp.c b/drivers/s390/block/dasd_3370_erp.c
index 84565c8..1d11c2a 100644
--- a/drivers/s390/block/dasd_3370_erp.c
+++ b/drivers/s390/block/dasd_3370_erp.c
@@ -4,7 +4,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  *
- * $Revision: 1.9 $
  */
 
 #define PRINTK_HEADER "dasd_erp(3370)"
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index c143ecb..c811380 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -5,7 +5,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
  *
- * $Revision: 1.36 $
  */
 
 #include <linux/timer.h>
@@ -1109,6 +1108,9 @@
 		case 0x0B:
 			DEV_MESSAGE(KERN_WARNING, device, "%s",
 				    "FORMAT F - Volume is suspended duplex");
+			/* call extended error reporting (EER) */
+			dasd_write_eer_trigger(DASD_EER_PPRCSUSPEND, device,
+					       erp->refers);
 			break;
 		case 0x0C:
 			DEV_MESSAGE(KERN_WARNING, device, "%s",
diff --git a/drivers/s390/block/dasd_9336_erp.c b/drivers/s390/block/dasd_9336_erp.c
index 01e8717..dc86144 100644
--- a/drivers/s390/block/dasd_9336_erp.c
+++ b/drivers/s390/block/dasd_9336_erp.c
@@ -4,7 +4,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  *
- * $Revision: 1.8 $
  */
 
 #define PRINTK_HEADER "dasd_erp(9336)"
diff --git a/drivers/s390/block/dasd_9343_erp.c b/drivers/s390/block/dasd_9343_erp.c
index 2a23b74..4a5b795 100644
--- a/drivers/s390/block/dasd_9343_erp.c
+++ b/drivers/s390/block/dasd_9343_erp.c
@@ -4,7 +4,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  *
- * $Revision: 1.13 $
  */
 
 #define PRINTK_HEADER "dasd_erp(9343)"
diff --git a/drivers/s390/block/dasd_cmb.c b/drivers/s390/block/dasd_cmb.c
index 4f365bf..e88f73e 100644
--- a/drivers/s390/block/dasd_cmb.c
+++ b/drivers/s390/block/dasd_cmb.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.9 $)
- *
  * Linux on zSeries Channel Measurement Facility support
  *  (dasd device driver interface)
  *
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index caee16a..1629b27 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -11,7 +11,6 @@
  * functions may not be called from interrupt context. In particular
  * dasd_get_device is a no-no from interrupt context.
  *
- * $Revision: 1.43 $
  */
 
 #include <linux/config.h>
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index ba80fde..3f9d704 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,7 +6,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.53 $
  */
 
 #include <linux/config.h>
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index a4f80bd..38a4e55 100644
--- a/drivers/s390/block/dasd_diag.h
+++ b/drivers/s390/block/dasd_diag.h
@@ -6,7 +6,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.9 $
  */
 
 #define MDSK_WRITE_REQ 0x01
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 96eb482..822e2a2 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -7,7 +7,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.74 $
  */
 
 #include <linux/config.h>
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index b6888c6..e15dd79 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -5,7 +5,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.10 $
  */
 
 #ifndef DASD_ECKD_H
@@ -30,6 +29,7 @@
 #define DASD_ECKD_CCW_PSF		 0x27
 #define DASD_ECKD_CCW_RSSD		 0x3e
 #define DASD_ECKD_CCW_LOCATE_RECORD	 0x47
+#define DASD_ECKD_CCW_SNSS               0x54
 #define DASD_ECKD_CCW_DEFINE_EXTENT	 0x63
 #define DASD_ECKD_CCW_WRITE_MT		 0x85
 #define DASD_ECKD_CCW_READ_MT		 0x86
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
new file mode 100644
index 0000000..f70cd77
--- /dev/null
+++ b/drivers/s390/block/dasd_eer.c
@@ -0,0 +1,1090 @@
+/*
+ *	character device driver for extended error reporting
+ *
+ *
+ *	Copyright (C) 2005 IBM Corporation
+ *	extended error reporting for DASD ECKD devices
+ *	Author(s): Stefan Weinhuber <wein@de.ibm.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
+#include <linux/notifier.h>
+
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <asm/atomic.h>
+#include <asm/ebcdic.h>
+
+#include "dasd_int.h"
+#include "dasd_eckd.h"
+
+
+MODULE_LICENSE("GPL");
+
+MODULE_AUTHOR("Stefan Weinhuber <wein@de.ibm.com>");
+MODULE_DESCRIPTION("DASD extended error reporting module");
+
+
+#ifdef PRINTK_HEADER
+#undef PRINTK_HEADER
+#endif				/* PRINTK_HEADER */
+#define PRINTK_HEADER "dasd(eer):"
+
+
+
+
+
+/*****************************************************************************/
+/*      the internal buffer                                                  */
+/*****************************************************************************/
+
+/*
+ * The internal buffer is meant to store obaque blobs of data, so it doesn't
+ * know of higher level concepts like triggers.
+ * It consists of a number of pages that are used as a ringbuffer. Each data
+ * blob is stored in a simple record that consists of an integer, which
+ * contains the size of the following data, and the data bytes themselfes.
+ *
+ * To allow for multiple independent readers we create one internal buffer
+ * each time the device is opened and destroy the buffer when the file is
+ * closed again.
+ *
+ * One record can be written to a buffer by using the functions
+ * - dasd_eer_start_record (one time per record to write the size to the buffer
+ *                          and reserve the space for the data)
+ * - dasd_eer_write_buffer (one or more times per record to write the data)
+ * The data can be written in several steps but you will have to compute
+ * the total size up front for the invocation of dasd_eer_start_record.
+ * If the ringbuffer is full, dasd_eer_start_record will remove the required
+ * number of old records.
+ *
+ * A record is typically read in two steps, first read the integer that
+ * specifies the size of the following data, then read the data.
+ * Both can be done by
+ * - dasd_eer_read_buffer
+ *
+ * For all mentioned functions you need to get the bufferlock first and keep it
+ * until a complete record is written or read.
+ */
+
+
+/*
+ * Alle information necessary to keep track of an internal buffer is kept in
+ * a struct eerbuffer. The buffer specific to a file pointer is strored in
+ * the private_data field of that file. To be able to write data to all
+ * existing buffers, each buffer is also added to the bufferlist.
+ * If the user doesn't want to read a complete record in one go, we have to
+ * keep track of the rest of the record. residual stores the number of bytes
+ * that are still to deliver. If the rest of the record is invalidated between
+ * two reads then residual will be set to -1 so that the next read will fail.
+ * All entries in the eerbuffer structure are protected with the bufferlock.
+ * To avoid races between writing to a buffer on the one side and creating
+ * and destroying buffers on the other side, the bufferlock must also be used
+ * to protect the bufferlist.
+ */
+
+struct eerbuffer {
+	struct list_head list;
+	char **buffer;
+	int buffersize;
+	int buffer_page_count;
+	int head;
+        int tail;
+	int residual;
+};
+
+LIST_HEAD(bufferlist);
+
+static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED;
+
+DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue);
+
+/*
+ * How many free bytes are available on the buffer.
+ * needs to be called with bufferlock held
+ */
+static int
+dasd_eer_get_free_bytes(struct eerbuffer *eerb)
+{
+	if (eerb->head < eerb->tail) {
+		return eerb->tail - eerb->head - 1;
+	} else
+		return eerb->buffersize - eerb->head + eerb->tail -1;
+}
+
+/*
+ * How many bytes of buffer space are used.
+ * needs to be called with bufferlock held
+ */
+static int
+dasd_eer_get_filled_bytes(struct eerbuffer *eerb)
+{
+
+	if (eerb->head >= eerb->tail) {
+		return eerb->head - eerb->tail;
+	} else
+		return eerb->buffersize - eerb->tail + eerb->head;
+}
+
+/*
+ * The dasd_eer_write_buffer function just copies count bytes of data
+ * to the buffer. Make sure to call dasd_eer_start_record first, to
+ * make sure that enough free space is available.
+ * needs to be called with bufferlock held
+ */
+static void
+dasd_eer_write_buffer(struct eerbuffer *eerb, int count, char *data)
+{
+
+	unsigned long headindex,localhead;
+	unsigned long rest, len;
+	char *nextdata;
+
+	nextdata = data;
+	rest = count;
+	while (rest > 0) {
+ 		headindex = eerb->head / PAGE_SIZE;
+ 		localhead = eerb->head % PAGE_SIZE;
+		len = min(rest, (PAGE_SIZE - localhead));
+		memcpy(eerb->buffer[headindex]+localhead, nextdata, len);
+		nextdata += len;
+		rest -= len;
+		eerb->head += len;
+		if ( eerb->head == eerb->buffersize )
+			eerb->head = 0; /* wrap around */
+		if (eerb->head > eerb->buffersize) {
+			MESSAGE(KERN_ERR, "%s", "runaway buffer head.");
+			BUG();
+		}
+	}
+}
+
+/*
+ * needs to be called with bufferlock held
+ */
+static int
+dasd_eer_read_buffer(struct eerbuffer *eerb, int count, char *data)
+{
+
+	unsigned long tailindex,localtail;
+	unsigned long rest, len, finalcount;
+	char *nextdata;
+
+	finalcount = min(count, dasd_eer_get_filled_bytes(eerb));
+	nextdata = data;
+	rest = finalcount;
+	while (rest > 0) {
+ 		tailindex = eerb->tail / PAGE_SIZE;
+ 		localtail = eerb->tail % PAGE_SIZE;
+		len = min(rest, (PAGE_SIZE - localtail));
+		memcpy(nextdata, eerb->buffer[tailindex]+localtail, len);
+		nextdata += len;
+		rest -= len;
+		eerb->tail += len;
+		if ( eerb->tail == eerb->buffersize )
+			eerb->tail = 0; /* wrap around */
+		if (eerb->tail > eerb->buffersize) {
+			MESSAGE(KERN_ERR, "%s", "runaway buffer tail.");
+			BUG();
+		}
+	}
+	return finalcount;
+}
+
+/*
+ * Whenever you want to write a blob of data to the internal buffer you
+ * have to start by using this function first. It will write the number
+ * of bytes that will be written to the buffer. If necessary it will remove
+ * old records to make room for the new one.
+ * needs to be called with bufferlock held
+ */
+static int
+dasd_eer_start_record(struct eerbuffer *eerb, int count)
+{
+	int tailcount;
+	if (count + sizeof(count) > eerb->buffersize)
+		return -ENOMEM;
+	while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) {
+		if (eerb->residual > 0) {
+			eerb->tail += eerb->residual;
+			if (eerb->tail >= eerb->buffersize)
+				eerb->tail -= eerb->buffersize;
+			eerb->residual = -1;
+		}
+		dasd_eer_read_buffer(eerb, sizeof(tailcount),
+				     (char*)(&tailcount));
+		eerb->tail += tailcount;
+		if (eerb->tail >= eerb->buffersize)
+			eerb->tail -= eerb->buffersize;
+	}
+	dasd_eer_write_buffer(eerb, sizeof(count), (char*)(&count));
+
+	return 0;
+};
+
+/*
+ * release pages that are not used anymore
+ */
+static void
+dasd_eer_free_buffer_pages(char **buf, int no_pages)
+{
+	int i;
+
+	for (i = 0; i < no_pages; ++i) {
+		free_page((unsigned long)buf[i]);
+	}
+}
+
+/*
+ * allocate a new set of memory pages
+ */
+static int
+dasd_eer_allocate_buffer_pages(char **buf, int no_pages)
+{
+	int i;
+
+	for (i = 0; i < no_pages; ++i) {
+		buf[i] = (char *) get_zeroed_page(GFP_KERNEL);
+		if (!buf[i]) {
+			dasd_eer_free_buffer_pages(buf, i);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+/*
+ * empty the buffer by resetting head and tail
+ * In case there is a half read data blob in the buffer, we set residual
+ * to -1 to indicate that the remainder of the blob is lost.
+ */
+static void
+dasd_eer_purge_buffer(struct eerbuffer *eerb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&bufferlock, flags);
+	if (eerb->residual > 0)
+		eerb->residual = -1;
+	eerb->tail=0;
+	eerb->head=0;
+	spin_unlock_irqrestore(&bufferlock, flags);
+}
+
+/*
+ * set the size of the buffer, newsize is the new number of pages to be used
+ * we don't try to copy any data back an forth, so any resize will also purge
+ * the buffer
+ */
+static int
+dasd_eer_resize_buffer(struct eerbuffer *eerb, int newsize)
+{
+	int i, oldcount, reuse;
+	char **new;
+	char **old;
+	unsigned long flags;
+
+	if (newsize < 1)
+		return -EINVAL;
+	if (eerb->buffer_page_count == newsize) {
+		/* documented behaviour is that any successfull invocation
+                 * will purge all records */
+		dasd_eer_purge_buffer(eerb);
+		return 0;
+	}
+	new = kmalloc(newsize*sizeof(char*), GFP_KERNEL);
+	if (!new)
+		return -ENOMEM;
+
+	reuse=min(eerb->buffer_page_count, newsize);
+	for (i = 0; i < reuse; ++i) {
+		new[i] = eerb->buffer[i];
+	}
+	if (eerb->buffer_page_count < newsize) {
+		if (dasd_eer_allocate_buffer_pages(
+			    &new[eerb->buffer_page_count],
+			    newsize - eerb->buffer_page_count)) {
+			kfree(new);
+			return -ENOMEM;
+		}
+	}
+
+	spin_lock_irqsave(&bufferlock, flags);
+	old = eerb->buffer;
+	eerb->buffer = new;
+	if (eerb->residual > 0)
+		eerb->residual = -1;
+	eerb->tail = 0;
+	eerb->head = 0;
+	oldcount = eerb->buffer_page_count;
+	eerb->buffer_page_count = newsize;
+	spin_unlock_irqrestore(&bufferlock, flags);
+
+	if (oldcount > newsize) {
+		for (i = newsize; i < oldcount; ++i) {
+			free_page((unsigned long)old[i]);
+		}
+	}
+	kfree(old);
+
+	return 0;
+}
+
+
+/*****************************************************************************/
+/*      The extended error reporting functionality                           */
+/*****************************************************************************/
+
+/*
+ * When a DASD device driver wants to report an error, it calls the
+ * function dasd_eer_write_trigger (via a notifier mechanism) and gives the
+ * respective trigger ID as parameter.
+ * Currently there are four kinds of triggers:
+ *
+ * DASD_EER_FATALERROR:  all kinds of unrecoverable I/O problems
+ * DASD_EER_PPRCSUSPEND: PPRC was suspended
+ * DASD_EER_NOPATH:      There is no path to the device left.
+ * DASD_EER_STATECHANGE: The state of the device has changed.
+ *
+ * For the first three triggers all required information can be supplied by
+ * the caller. For these triggers a record is written by the function
+ * dasd_eer_write_standard_trigger.
+ *
+ * When dasd_eer_write_trigger is called to write a DASD_EER_STATECHANGE
+ * trigger, we have to gather the necessary sense data first. We cannot queue
+ * the necessary SNSS (sense subsystem status) request immediatly, since we
+ * are likely to run in a deadlock situation. Instead, we schedule a
+ * work_struct that calls the function dasd_eer_sense_subsystem_status to
+ * create and start an SNSS  request asynchronously.
+ *
+ * To avoid memory allocations at runtime, the necessary memory is allocated
+ * when the extended error reporting is enabled for a device (by
+ * dasd_eer_probe). There is one private eer data structure for each eer
+ * enabled DASD device. It contains memory for the work_struct, one SNSS cqr
+ * and a flags field that is used to coordinate the use of the cqr. The call
+ * to write a state change trigger can come in at any time, so we have one flag
+ * CQR_IN_USE that protects the cqr itself. When this flag indicates that the
+ * cqr is currently in use, dasd_eer_sense_subsystem_status cannot start a
+ * second request but sets the SNSS_REQUESTED flag instead.
+ *
+ * When the request is finished, the callback function dasd_eer_SNSS_cb
+ * is called. This function will invoke the function
+ * dasd_eer_write_SNSS_trigger to finally write the trigger. It will also
+ * check the SNSS_REQUESTED flag and if it is set it will call
+ * dasd_eer_sense_subsystem_status again.
+ *
+ * To avoid race conditions during the handling of the lock, the flags must
+ * be protected by the snsslock.
+ */
+
+struct dasd_eer_private {
+	struct dasd_ccw_req *cqr;
+	unsigned long flags;
+	struct work_struct worker;
+};
+
+static void dasd_eer_destroy(struct dasd_device *device,
+			     struct dasd_eer_private *eer);
+static int
+dasd_eer_write_trigger(struct dasd_eer_trigger *trigger);
+static void dasd_eer_sense_subsystem_status(void *data);
+static int dasd_eer_notify(struct notifier_block *self,
+			   unsigned long action, void *data);
+
+struct workqueue_struct *dasd_eer_workqueue;
+
+#define SNSS_DATA_SIZE 44
+static spinlock_t snsslock = SPIN_LOCK_UNLOCKED;
+
+#define DASD_EER_BUSID_SIZE 10
+struct dasd_eer_header {
+	__u32 total_size;
+	__u32 trigger;
+	__u64 tv_sec;
+	__u64 tv_usec;
+	char busid[DASD_EER_BUSID_SIZE];
+} __attribute__ ((packed));
+
+static struct notifier_block dasd_eer_nb = {
+	.notifier_call = dasd_eer_notify,
+};
+
+/*
+ * flags for use with dasd_eer_private
+ */
+#define CQR_IN_USE     0
+#define SNSS_REQUESTED 1
+
+/*
+ * This function checks if extended error reporting is available for a given
+ * dasd_device. If yes, then it creates and returns a struct dasd_eer,
+ * otherwise it returns an -EPERM error pointer.
+ */
+struct dasd_eer_private *
+dasd_eer_probe(struct dasd_device *device)
+{
+	struct dasd_eer_private *private;
+
+	if (!(device && device->discipline
+	      && !strcmp(device->discipline->name, "ECKD"))) {
+		return ERR_PTR(-EPERM);
+	}
+	/* allocate the private data structure */
+	private = (struct dasd_eer_private *)kmalloc(
+		sizeof(struct dasd_eer_private), GFP_KERNEL);
+	if (!private) {
+		return ERR_PTR(-ENOMEM);
+	}
+	INIT_WORK(&private->worker, dasd_eer_sense_subsystem_status,
+		  (void *)device);
+	private->cqr = dasd_kmalloc_request("ECKD",
+					    1 /* SNSS */ ,
+					    SNSS_DATA_SIZE ,
+					    device);
+	if (!private->cqr) {
+		kfree(private);
+		return ERR_PTR(-ENOMEM);
+	}
+	private->flags = 0;
+	return private;
+};
+
+/*
+ * If our private SNSS request is queued, remove it from the
+ * dasd ccw queue so we can free the requests memory.
+ */
+static void
+dasd_eer_dequeue_SNSS_request(struct dasd_device *device,
+			      struct dasd_eer_private *eer)
+{
+	struct list_head *lst, *nxt;
+	struct dasd_ccw_req *cqr, *erpcqr;
+	dasd_erp_fn_t erp_fn;
+
+	spin_lock_irq(get_ccwdev_lock(device->cdev));
+	list_for_each_safe(lst, nxt, &device->ccw_queue) {
+		cqr = list_entry(lst, struct dasd_ccw_req, list);
+		/* we are looking for two kinds or requests */
+		/* first kind: our SNSS request: */
+		if (cqr == eer->cqr) {
+			if (cqr->status == DASD_CQR_IN_IO)
+				device->discipline->term_IO(cqr);
+			list_del(&cqr->list);
+			break;
+		}
+		/* second kind: ERP requests for our SNSS request */
+		if (cqr->refers) {
+			/* If this erp request chain ends in our cqr, then */
+                        /* cal the erp_postaction to clean it up  */
+			erpcqr = cqr;
+			while (erpcqr->refers) {
+				erpcqr = erpcqr->refers;
+			}
+			if (erpcqr == eer->cqr) {
+				erp_fn = device->discipline->erp_postaction(
+					 cqr);
+				erp_fn(cqr);
+			}
+			continue;
+		}
+	}
+	spin_unlock_irq(get_ccwdev_lock(device->cdev));
+}
+
+/*
+ * This function dismantles a struct dasd_eer that was created by
+ * dasd_eer_probe. Since we want to free our private data structure,
+ * we must make sure that the memory is not in use anymore.
+ * We have to flush the work queue and remove a possible SNSS request
+ * from the dasd queue.
+ */
+static void
+dasd_eer_destroy(struct dasd_device *device, struct dasd_eer_private *eer)
+{
+	flush_workqueue(dasd_eer_workqueue);
+	dasd_eer_dequeue_SNSS_request(device, eer);
+	dasd_kfree_request(eer->cqr, device);
+	kfree(eer);
+};
+
+/*
+ * enable the extended error reporting for a particular device
+ */
+static int
+dasd_eer_enable_on_device(struct dasd_device *device)
+{
+	void *eer;
+	if (!device)
+		return -ENODEV;
+	if (device->eer)
+		return 0;
+	if (!try_module_get(THIS_MODULE)) {
+		return -EINVAL;
+	}
+	eer = (void *)dasd_eer_probe(device);
+	if (IS_ERR(eer)) {
+		module_put(THIS_MODULE);
+		return PTR_ERR(eer);
+	}
+	device->eer = eer;
+	return 0;
+}
+
+/*
+ * enable the extended error reporting for a particular device
+ */
+static int
+dasd_eer_disable_on_device(struct dasd_device *device)
+{
+	struct dasd_eer_private *eer = device->eer;
+
+	if (!device)
+		return -ENODEV;
+	if (!device->eer)
+		return 0;
+	device->eer = NULL;
+	dasd_eer_destroy(device,eer);
+	module_put(THIS_MODULE);
+
+	return 0;
+}
+
+/*
+ * Set extended error reporting (eer)
+ * Note: This will be registered as a DASD ioctl, to be called on DASD devices.
+ */
+static int
+dasd_ioctl_set_eer(struct block_device *bdev, int no, long args)
+{
+	struct dasd_device *device;
+	int intval;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	if (bdev != bdev->bd_contains)
+		/* Error-reporting is not allowed for partitions */
+		return -EINVAL;
+	if (get_user(intval, (int __user *) args))
+		return -EFAULT;
+	device =  bdev->bd_disk->private_data;
+	if (device == NULL)
+		return -ENODEV;
+
+	intval = (intval != 0);
+	DEV_MESSAGE (KERN_DEBUG, device,
+		     "set eer on device to %d", intval);
+	if (intval)
+		return dasd_eer_enable_on_device(device);
+	else
+		return dasd_eer_disable_on_device(device);
+}
+
+/*
+ * Get value of extended error reporting.
+ * Note: This will be registered as a DASD ioctl, to be called on DASD devices.
+ */
+static int
+dasd_ioctl_get_eer(struct block_device *bdev, int no, long args)
+{
+	struct dasd_device *device;
+
+	device =  bdev->bd_disk->private_data;
+	if (device == NULL)
+		return -ENODEV;
+	return put_user((device->eer != NULL), (int __user *) args);
+}
+
+/*
+ * The following function can be used for those triggers that have
+ * all necessary data available when the function is called.
+ * If the parameter cqr is not NULL, the chain of requests will be searched
+ * for valid sense data, and all valid sense data sets will be added to
+ * the triggers data.
+ */
+static int
+dasd_eer_write_standard_trigger(int trigger, struct dasd_device *device,
+				struct dasd_ccw_req *cqr)
+{
+	struct dasd_ccw_req *temp_cqr;
+	int data_size;
+	struct timeval tv;
+	struct dasd_eer_header header;
+	unsigned long flags;
+	struct eerbuffer *eerb;
+
+	/* go through cqr chain and count the valid sense data sets */
+	temp_cqr = cqr;
+	data_size = 0;
+	while (temp_cqr) {
+		if (temp_cqr->irb.esw.esw0.erw.cons)
+			data_size += 32;
+		temp_cqr = temp_cqr->refers;
+	}
+
+	header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
+	header.trigger = trigger;
+	do_gettimeofday(&tv);
+	header.tv_sec = tv.tv_sec;
+	header.tv_usec = tv.tv_usec;
+	strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
+
+	spin_lock_irqsave(&bufferlock, flags);
+	list_for_each_entry(eerb, &bufferlist, list) {
+		dasd_eer_start_record(eerb, header.total_size);
+		dasd_eer_write_buffer(eerb, sizeof(header), (char*)(&header));
+		temp_cqr = cqr;
+		while (temp_cqr) {
+			if (temp_cqr->irb.esw.esw0.erw.cons)
+				dasd_eer_write_buffer(eerb, 32, cqr->irb.ecw);
+			temp_cqr = temp_cqr->refers;
+		}
+		dasd_eer_write_buffer(eerb, 4,"EOR");
+	}
+	spin_unlock_irqrestore(&bufferlock, flags);
+
+	wake_up_interruptible(&dasd_eer_read_wait_queue);
+
+	return 0;
+}
+
+/*
+ * This function writes a DASD_EER_STATECHANGE trigger.
+ */
+static void
+dasd_eer_write_SNSS_trigger(struct dasd_device *device,
+			    struct dasd_ccw_req *cqr)
+{
+	int data_size;
+	int snss_rc;
+	struct timeval tv;
+	struct dasd_eer_header header;
+	unsigned long flags;
+	struct eerbuffer *eerb;
+
+	snss_rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0;
+	if (snss_rc)
+		data_size = 0;
+	else
+		data_size = SNSS_DATA_SIZE;
+
+	header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
+	header.trigger = DASD_EER_STATECHANGE;
+	do_gettimeofday(&tv);
+	header.tv_sec = tv.tv_sec;
+	header.tv_usec = tv.tv_usec;
+	strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
+
+	spin_lock_irqsave(&bufferlock, flags);
+	list_for_each_entry(eerb, &bufferlist, list) {
+		dasd_eer_start_record(eerb, header.total_size);
+		dasd_eer_write_buffer(eerb, sizeof(header),(char*)(&header));
+		if (!snss_rc)
+			dasd_eer_write_buffer(eerb, SNSS_DATA_SIZE, cqr->data);
+		dasd_eer_write_buffer(eerb, 4,"EOR");
+	}
+	spin_unlock_irqrestore(&bufferlock, flags);
+
+	wake_up_interruptible(&dasd_eer_read_wait_queue);
+}
+
+/*
+ * callback function for use with SNSS request
+ */
+static void
+dasd_eer_SNSS_cb(struct dasd_ccw_req *cqr, void *data)
+{
+        struct dasd_device *device;
+	struct dasd_eer_private *private;
+	unsigned long irqflags;
+
+        device = (struct dasd_device *)data;
+	private = (struct dasd_eer_private *)device->eer;
+	dasd_eer_write_SNSS_trigger(device, cqr);
+	spin_lock_irqsave(&snsslock, irqflags);
+	if(!test_and_clear_bit(SNSS_REQUESTED, &private->flags)) {
+		clear_bit(CQR_IN_USE, &private->flags);
+		spin_unlock_irqrestore(&snsslock, irqflags);
+		return;
+	};
+	clear_bit(CQR_IN_USE, &private->flags);
+	spin_unlock_irqrestore(&snsslock, irqflags);
+	dasd_eer_sense_subsystem_status(device);
+	return;
+}
+
+/*
+ * clean a used cqr before using it again
+ */
+static void
+dasd_eer_clean_SNSS_request(struct dasd_ccw_req *cqr)
+{
+	struct ccw1 *cpaddr = cqr->cpaddr;
+	void *data = cqr->data;
+
+	memset(cqr, 0, sizeof(struct dasd_ccw_req));
+	memset(cpaddr, 0, sizeof(struct ccw1));
+	memset(data, 0, SNSS_DATA_SIZE);
+	cqr->cpaddr = cpaddr;
+	cqr->data = data;
+	strncpy((char *) &cqr->magic, "ECKD", 4);
+	ASCEBC((char *) &cqr->magic, 4);
+	set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+}
+
+/*
+ * build and start an SNSS request
+ * This function is called from a work queue so we have to
+ * pass the dasd_device pointer as a void pointer.
+ */
+static void
+dasd_eer_sense_subsystem_status(void *data)
+{
+	struct dasd_device *device;
+	struct dasd_eer_private *private;
+	struct dasd_ccw_req *cqr;
+	struct ccw1 *ccw;
+	unsigned long irqflags;
+
+	device = (struct dasd_device *)data;
+	private = (struct dasd_eer_private *)device->eer;
+	if (!private) /* device not eer enabled any more */
+		return;
+	cqr = private->cqr;
+	spin_lock_irqsave(&snsslock, irqflags);
+	if(test_and_set_bit(CQR_IN_USE, &private->flags)) {
+		set_bit(SNSS_REQUESTED, &private->flags);
+		spin_unlock_irqrestore(&snsslock, irqflags);
+		return;
+	};
+	spin_unlock_irqrestore(&snsslock, irqflags);
+	dasd_eer_clean_SNSS_request(cqr);
+	cqr->device = device;
+	cqr->retries = 255;
+	cqr->expires = 10 * HZ;
+
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = DASD_ECKD_CCW_SNSS;
+	ccw->count = SNSS_DATA_SIZE;
+	ccw->flags = 0;
+	ccw->cda = (__u32)(addr_t)cqr->data;
+
+	cqr->buildclk = get_clock();
+	cqr->status = DASD_CQR_FILLED;
+	cqr->callback = dasd_eer_SNSS_cb;
+	cqr->callback_data = (void *)device;
+        dasd_add_request_head(cqr);
+
+	return;
+}
+
+/*
+ * This function is called for all triggers. It calls the appropriate
+ * function that writes the actual trigger records.
+ */
+static int
+dasd_eer_write_trigger(struct dasd_eer_trigger *trigger)
+{
+	int rc;
+	struct dasd_eer_private *private = trigger->device->eer;
+
+	switch (trigger->id) {
+	case DASD_EER_FATALERROR:
+	case DASD_EER_PPRCSUSPEND:
+		rc = dasd_eer_write_standard_trigger(
+			trigger->id, trigger->device, trigger->cqr);
+		break;
+	case DASD_EER_NOPATH:
+		rc = dasd_eer_write_standard_trigger(
+			trigger->id, trigger->device, NULL);
+		break;
+	case DASD_EER_STATECHANGE:
+                if (queue_work(dasd_eer_workqueue, &private->worker)) {
+                        rc=0;
+                } else {
+                        /* If the work_struct was already queued, it can't
+                         * be queued again. But this is OK since we don't
+                         * need to have it queued twice.
+                         */
+                        rc = -EBUSY;
+                }
+		break;
+	default: /* unknown trigger, so we write it without any sense data */
+		rc = dasd_eer_write_standard_trigger(
+			trigger->id, trigger->device, NULL);
+		break;
+	}
+	return rc;
+}
+
+/*
+ * This function is registered with the dasd device driver and gets called
+ * for all dasd eer notifications.
+ */
+static int dasd_eer_notify(struct notifier_block *self,
+			    unsigned long action, void *data)
+{
+	switch (action) {
+	case DASD_EER_DISABLE:
+		dasd_eer_disable_on_device((struct dasd_device *)data);
+		break;
+	case DASD_EER_TRIGGER:
+		dasd_eer_write_trigger((struct dasd_eer_trigger *)data);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+
+/*****************************************************************************/
+/*      the device operations                                                */
+/*****************************************************************************/
+
+/*
+ * On the one side we need a lock to access our internal buffer, on the
+ * other side a copy_to_user can sleep. So we need to copy the data we have
+ * to transfer in a readbuffer, which is protected by the readbuffer_mutex.
+ */
+static char readbuffer[PAGE_SIZE];
+DECLARE_MUTEX(readbuffer_mutex);
+
+
+static int
+dasd_eer_open(struct inode *inp, struct file *filp)
+{
+	struct eerbuffer *eerb;
+	unsigned long flags;
+
+	eerb = kmalloc(sizeof(struct eerbuffer), GFP_KERNEL);
+	eerb->head = 0;
+	eerb->tail = 0;
+	eerb->residual = 0;
+	eerb->buffer_page_count = 1;
+	eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE;
+        eerb->buffer = kmalloc(eerb->buffer_page_count*sizeof(char*),
+			       GFP_KERNEL);
+        if (!eerb->buffer)
+                return -ENOMEM;
+	if (dasd_eer_allocate_buffer_pages(eerb->buffer,
+					   eerb->buffer_page_count)) {
+		kfree(eerb->buffer);
+		return -ENOMEM;
+	}
+	filp->private_data = eerb;
+	spin_lock_irqsave(&bufferlock, flags);
+	list_add(&eerb->list, &bufferlist);
+	spin_unlock_irqrestore(&bufferlock, flags);
+
+	return nonseekable_open(inp,filp);
+}
+
+static int
+dasd_eer_close(struct inode *inp, struct file *filp)
+{
+	struct eerbuffer *eerb;
+	unsigned long flags;
+
+	eerb = (struct eerbuffer *)filp->private_data;
+	spin_lock_irqsave(&bufferlock, flags);
+	list_del(&eerb->list);
+	spin_unlock_irqrestore(&bufferlock, flags);
+	dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count);
+	kfree(eerb->buffer);
+	kfree(eerb);
+
+	return 0;
+}
+
+static long
+dasd_eer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	int intval;
+	struct eerbuffer *eerb;
+
+	eerb = (struct eerbuffer *)filp->private_data;
+	switch (cmd) {
+	case DASD_EER_PURGE:
+		dasd_eer_purge_buffer(eerb);
+		return 0;
+	case DASD_EER_SETBUFSIZE:
+		if (get_user(intval, (int __user *)arg))
+			return -EFAULT;
+		return dasd_eer_resize_buffer(eerb, intval);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static ssize_t
+dasd_eer_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
+{
+	int tc,rc;
+	int tailcount,effective_count;
+        unsigned long flags;
+	struct eerbuffer *eerb;
+
+	eerb = (struct eerbuffer *)filp->private_data;
+	if(down_interruptible(&readbuffer_mutex))
+		return -ERESTARTSYS;
+
+	spin_lock_irqsave(&bufferlock, flags);
+
+	if (eerb->residual < 0) { /* the remainder of this record */
+		                  /* has been deleted             */
+		eerb->residual = 0;
+		spin_unlock_irqrestore(&bufferlock, flags);
+		up(&readbuffer_mutex);
+		return -EIO;
+	} else if (eerb->residual > 0) {
+		/* OK we still have a second half of a record to deliver */
+		effective_count = min(eerb->residual, (int)count);
+		eerb->residual -= effective_count;
+	} else {
+		tc = 0;
+		while (!tc) {
+			tc = dasd_eer_read_buffer(eerb,
+				sizeof(tailcount), (char*)(&tailcount));
+			if (!tc) {
+				/* no data available */
+				spin_unlock_irqrestore(&bufferlock, flags);
+				up(&readbuffer_mutex);
+				if (filp->f_flags & O_NONBLOCK)
+					return -EAGAIN;
+				rc = wait_event_interruptible(
+					dasd_eer_read_wait_queue,
+					eerb->head != eerb->tail);
+				if (rc) {
+					return rc;
+				}
+				if(down_interruptible(&readbuffer_mutex))
+					return -ERESTARTSYS;
+				spin_lock_irqsave(&bufferlock, flags);
+			}
+		}
+		WARN_ON(tc != sizeof(tailcount));
+		effective_count = min(tailcount,(int)count);
+		eerb->residual = tailcount - effective_count;
+	}
+
+	tc = dasd_eer_read_buffer(eerb, effective_count, readbuffer);
+	WARN_ON(tc != effective_count);
+
+	spin_unlock_irqrestore(&bufferlock, flags);
+
+	if (copy_to_user(buf, readbuffer, effective_count)) {
+		up(&readbuffer_mutex);
+		return -EFAULT;
+	}
+
+	up(&readbuffer_mutex);
+	return effective_count;
+}
+
+static unsigned int
+dasd_eer_poll (struct file *filp, poll_table *ptable)
+{
+	unsigned int mask;
+	unsigned long flags;
+	struct eerbuffer *eerb;
+
+	eerb = (struct eerbuffer *)filp->private_data;
+	poll_wait(filp, &dasd_eer_read_wait_queue, ptable);
+	spin_lock_irqsave(&bufferlock, flags);
+	if (eerb->head != eerb->tail)
+		mask = POLLIN | POLLRDNORM ;
+	else
+		mask = 0;
+	spin_unlock_irqrestore(&bufferlock, flags);
+	return mask;
+}
+
+static struct file_operations dasd_eer_fops = {
+	.open		= &dasd_eer_open,
+	.release	= &dasd_eer_close,
+	.unlocked_ioctl = &dasd_eer_ioctl,
+	.compat_ioctl	= &dasd_eer_ioctl,
+	.read		= &dasd_eer_read,
+	.poll		= &dasd_eer_poll,
+	.owner		= THIS_MODULE,
+};
+
+static struct miscdevice dasd_eer_dev = {
+	.minor	    = MISC_DYNAMIC_MINOR,
+	.name	    = "dasd_eer",
+	.fops	    = &dasd_eer_fops,
+};
+
+
+/*****************************************************************************/
+/*	Init and exit							     */
+/*****************************************************************************/
+
+static int
+__init dasd_eer_init(void)
+{
+	int rc;
+
+	dasd_eer_workqueue = create_singlethread_workqueue("dasd_eer");
+	if (!dasd_eer_workqueue) {
+		MESSAGE(KERN_ERR , "%s", "dasd_eer_init could not "
+		       "create workqueue \n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = dasd_register_eer_notifier(&dasd_eer_nb);
+	if (rc) {
+		MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
+		       "register error reporting");
+		goto queue;
+	}
+
+	dasd_ioctl_no_register(THIS_MODULE, BIODASDEERSET, dasd_ioctl_set_eer);
+	dasd_ioctl_no_register(THIS_MODULE, BIODASDEERGET, dasd_ioctl_get_eer);
+
+	/* we don't need our own character device,
+	 * so we just register as misc device */
+	rc = misc_register(&dasd_eer_dev);
+	if (rc) {
+		MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
+		       "register misc device");
+		goto unregister;
+	}
+
+	return 0;
+
+unregister:
+	dasd_unregister_eer_notifier(&dasd_eer_nb);
+	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET,
+				 dasd_ioctl_set_eer);
+	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET,
+				 dasd_ioctl_get_eer);
+queue:
+	destroy_workqueue(dasd_eer_workqueue);
+out:
+	return rc;
+
+}
+module_init(dasd_eer_init);
+
+static void
+__exit dasd_eer_exit(void)
+{
+	dasd_unregister_eer_notifier(&dasd_eer_nb);
+	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET,
+				 dasd_ioctl_set_eer);
+	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET,
+				 dasd_ioctl_get_eer);
+	destroy_workqueue(dasd_eer_workqueue);
+
+	WARN_ON(misc_deregister(&dasd_eer_dev) != 0);
+}
+module_exit(dasd_eer_exit);
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 7cb98d2..8fd71ab 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -7,7 +7,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.14 $
  */
 
 #include <linux/config.h>
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 8ec75dc..9114569 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -4,7 +4,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.41 $
  */
 
 #include <linux/config.h>
diff --git a/drivers/s390/block/dasd_fba.h b/drivers/s390/block/dasd_fba.h
index 624f040..da1fa91 100644
--- a/drivers/s390/block/dasd_fba.h
+++ b/drivers/s390/block/dasd_fba.h
@@ -4,7 +4,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.6 $
  */
 
 #ifndef DASD_FBA_H
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index a601c9a..65dc844 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -9,7 +9,6 @@
  *
  * gendisk related functions for the dasd driver.
  *
- * $Revision: 1.51 $
  */
 
 #include <linux/config.h>
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index e4b4015..d1b08fa 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.68 $
  */
 
 #ifndef DASD_INT_H
@@ -276,6 +275,34 @@
 
 extern struct dasd_discipline *dasd_diag_discipline_pointer;
 
+
+/*
+ * Notification numbers for extended error reporting notifications:
+ * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's
+ * eer pointer) is freed. The error reporting module needs to do all necessary
+ * cleanup steps.
+ * The DASD_EER_TRIGGER notification sends the actual error reports (triggers).
+ */
+#define DASD_EER_DISABLE 0
+#define DASD_EER_TRIGGER 1
+
+/* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */
+#define DASD_EER_FATALERROR  1
+#define DASD_EER_NOPATH      2
+#define DASD_EER_STATECHANGE 3
+#define DASD_EER_PPRCSUSPEND 4
+
+/*
+ * The dasd_eer_trigger structure contains all data that we need to send
+ * along with an DASD_EER_TRIGGER notification.
+ */
+struct dasd_eer_trigger {
+	unsigned int id;
+	struct dasd_device *device;
+	struct dasd_ccw_req *cqr;
+};
+
+
 struct dasd_device {
 	/* Block device stuff. */
 	struct gendisk *gdp;
@@ -289,6 +316,9 @@
 	unsigned long flags;		/* per device flags */
 	unsigned short features;        /* copy of devmap-features (read-only!) */
 
+	/* extended error reporting stuff (eer) */
+	void *eer;
+
 	/* Device discipline stuff. */
 	struct dasd_discipline *discipline;
 	char *private;
@@ -489,6 +519,12 @@
 int dasd_generic_set_offline (struct ccw_device *cdev);
 int dasd_generic_notify(struct ccw_device *, int);
 void dasd_generic_auto_online (struct ccw_driver *);
+int dasd_register_eer_notifier(struct notifier_block *);
+int dasd_unregister_eer_notifier(struct notifier_block *);
+void dasd_write_eer_trigger(unsigned int , struct dasd_device *,
+			struct dasd_ccw_req *);
+
+
 
 /* externals in dasd_devmap.c */
 extern int dasd_max_devindex;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 9396fca..fafeeae 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,8 +7,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.50 $
- *
  * i/o controls for the dasd driver.
  */
 #include <linux/config.h>
@@ -423,8 +421,15 @@
 	dasd_info->cu_model = cdev->id.cu_model;
 	dasd_info->dev_type = cdev->id.dev_type;
 	dasd_info->dev_model = cdev->id.dev_model;
-	dasd_info->open_count = atomic_read(&device->open_count);
 	dasd_info->status = device->state;
+	/*
+	 * The open_count is increased for every opener, that includes
+	 * the blkdev_get in dasd_scan_partitions.
+	 * This must be hidden from user-space.
+	 */
+	dasd_info->open_count = atomic_read(&device->open_count);
+	if (!device->bdev)
+		dasd_info->open_count++;
 	
 	/*
 	 * check if device is really formatted
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index fff9020..2d5da3c 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,7 +9,6 @@
  *
  * /proc interface for the dasd driver.
  *
- * $Revision: 1.33 $
  */
 
 #include <linux/config.h>
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 1f06091..606f6ad 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/interrupt.h>
+#include <linux/err.h>
 
 #include <linux/slab.h>
 #include <linux/bootmem.h>
@@ -864,7 +865,7 @@
 	}
 
 	cdev = ccw_device_probe_console();
-	if (!cdev)
+	if (IS_ERR(cdev))
 		return -ENODEV;
 
 	raw3215[0] = raw = (struct raw3215_info *)
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index c570a9f..ef607a1d 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/types.h>
+#include <linux/err.h>
 
 #include <asm/ccwdev.h>
 #include <asm/cio.h>
@@ -597,7 +598,7 @@
 	}
 
 	cdev = ccw_device_probe_console();
-	if (!cdev)
+	if (IS_ERR(cdev))
 		return -ENODEV;
 	rp = raw3270_setup_console(cdev);
 	if (IS_ERR(rp))
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 5bda234..a317a12 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -440,7 +440,11 @@
 			return -EPERM;
 		len = strnlen_user(u_kbs->kb_string,
 				   sizeof(u_kbs->kb_string) - 1);
-		p = kmalloc(len, GFP_KERNEL);
+		if (!len)
+			return -EFAULT;
+		if (len > sizeof(u_kbs->kb_string) - 1)
+			return -EINVAL;
+		p = kmalloc(len + 1, GFP_KERNEL);
 		if (!p)
 			return -ENOMEM;
 		if (copy_from_user(p, u_kbs->kb_string, len)) {
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index ceb0e47..4138564 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -85,11 +85,10 @@
 /* Maximum retry counts */
 #define SCLP_INIT_RETRY		3
 #define SCLP_MASK_RETRY		3
-#define SCLP_REQUEST_RETRY	3
 
 /* Timeout intervals in seconds.*/
-#define SCLP_BUSY_INTERVAL	2
-#define SCLP_RETRY_INTERVAL	5
+#define SCLP_BUSY_INTERVAL	10
+#define SCLP_RETRY_INTERVAL	15
 
 static void sclp_process_queue(void);
 static int sclp_init_mask(int calculate);
@@ -153,11 +152,9 @@
 	if (sclp_running_state != sclp_running_state_idle)
 		return 0;
 	del_timer(&sclp_request_timer);
-	if (req->start_count <= SCLP_REQUEST_RETRY) {
-		rc = service_call(req->command, req->sccb);
-		req->start_count++;
-	} else
-		rc = -EIO;
+	rc = service_call(req->command, req->sccb);
+	req->start_count++;
+
 	if (rc == 0) {
 		/* Sucessfully started request */
 		req->status = SCLP_REQ_RUNNING;
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 20be88e..682039c 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1357,7 +1357,7 @@
 	debug_set_level(TAPE_DBF_AREA, 6);
 #endif
 
-	DBF_EVENT(3, "34xx init: $Revision: 1.23 $\n");
+	DBF_EVENT(3, "34xx init\n");
 	/* Register driver for 3480/3490 tapes. */
 	rc = ccw_driver_register(&tape_34xx_driver);
 	if (rc)
@@ -1377,8 +1377,7 @@
 
 MODULE_DEVICE_TABLE(ccw, tape_34xx_ids);
 MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH");
-MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape "
-		   "device driver ($Revision: 1.23 $)");
+MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape device driver");
 MODULE_LICENSE("GPL");
 
 module_init(tape_34xx_init);
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index fcaee44..b3569c8 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -1,6 +1,6 @@
 /*
  * (C) Copyright IBM Corp. 2004
- * tape_class.c ($Revision: 1.8 $)
+ * tape_class.c
  *
  * Tape class device support
  *
@@ -12,7 +12,7 @@
 MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
 MODULE_DESCRIPTION(
 	"(C) Copyright IBM Corp. 2004   All Rights Reserved.\n"
-	"tape_class.c ($Revision: 1.8 $)"
+	"tape_class.c"
 );
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
index 33133ad..3d0ca05 100644
--- a/drivers/s390/char/tape_class.h
+++ b/drivers/s390/char/tape_class.h
@@ -1,6 +1,6 @@
 /*
  * (C) Copyright IBM Corp. 2004   All Rights Reserved.
- * tape_class.h ($Revision: 1.4 $)
+ * tape_class.h
  *
  * Tape class device support
  *
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 8f486e1..4ea438c 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -1239,7 +1239,7 @@
 #ifdef DBF_LIKE_HELL
 	debug_set_level(TAPE_DBF_AREA, 6);
 #endif
-	DBF_EVENT(3, "tape init: ($Revision: 1.54 $)\n");
+	DBF_EVENT(3, "tape init\n");
 	tape_proc_init();
 	tapechar_init ();
 	tapeblock_init ();
@@ -1263,8 +1263,7 @@
 
 MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and "
 	      "Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)");
-MODULE_DESCRIPTION("Linux on zSeries channel attached "
-		   "tape device driver ($Revision: 1.54 $)");
+MODULE_DESCRIPTION("Linux on zSeries channel attached tape device driver");
 MODULE_LICENSE("GPL");
 
 module_init(tape_init);
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index cd2cc28..5287631 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -2,8 +2,6 @@
  *  drivers/s390/cio/airq.c
  *   S/390 common I/O routines -- support for adapter interruptions
  *
- *   $Revision: 1.15 $
- *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 72f27c1..cb8e2e6 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,6 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.42 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 6c077ad..8013c8e 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,7 +1,6 @@
 /*
  *  drivers/s390/cio/ccwgroup.c
  *  bus driver for ccwgroup
- *   $Revision: 1.35 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                       IBM Corporation
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 2cbb724..8cf9905 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,7 +1,6 @@
 /*
  *  drivers/s390/cio/chsc.c
  *   S/390 common I/O routines -- channel subsystem call
- *   $Revision: 1.128 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -233,7 +232,7 @@
 		return 0;
 
 	mask = 0x80 >> j;
-	spin_lock(&sch->lock);
+	spin_lock_irq(&sch->lock);
 
 	stsch(sch->schid, &schib);
 	if (!schib.pmcw.dnv)
@@ -282,10 +281,10 @@
 	if (sch->driver && sch->driver->verify)
 		sch->driver->verify(&sch->dev);
 out_unlock:
-	spin_unlock(&sch->lock);
+	spin_unlock_irq(&sch->lock);
 	return 0;
 out_unreg:
-	spin_unlock(&sch->lock);
+	spin_unlock_irq(&sch->lock);
 	sch->lpm = 0;
 	if (css_enqueue_subchannel_slow(sch->schid)) {
 		css_clear_subchannel_slow_list();
@@ -653,7 +652,7 @@
 	if (!sch)
 		/* Check if the subchannel is now available. */
 		return __chp_add_new_sch(schid);
-	spin_lock(&sch->lock);
+	spin_lock_irq(&sch->lock);
 	for (i=0; i<8; i++)
 		if (sch->schib.pmcw.chpid[i] == chp->id) {
 			if (stsch(sch->schid, &sch->schib) != 0) {
@@ -675,7 +674,7 @@
 	if (sch->driver && sch->driver->verify)
 		sch->driver->verify(&sch->dev);
 
-	spin_unlock(&sch->lock);
+	spin_unlock_irq(&sch->lock);
 	put_device(&sch->dev);
 	return 0;
 }
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 44e4b4b..3e75095 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -68,6 +68,6 @@
 
 extern int chsc_enable_facility(int);
 
-#define to_channelpath(dev) container_of(dev, struct channel_path, dev)
+#define to_channelpath(device) container_of(device, struct channel_path, dev)
 
 #endif
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 6223b06..cbb86fa 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,6 @@
 /*
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
- *   $Revision: 1.140 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 0b03714..07ef3f6 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/s390/cio/cmf.c ($Revision: 1.19 $)
+ * linux/drivers/s390/cio/cmf.c
  *
  * Linux on zSeries Channel Measurement Facility support
  *
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 5161087..1bbf231 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,7 +1,6 @@
 /*
  *  drivers/s390/cio/css.c
  *  driver for channel subsystem
- *   $Revision: 1.96 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index a67e7e6..062fb10 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1,7 +1,6 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.140 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -255,7 +254,7 @@
 	struct ccw_device_id *id = &(cdev->id);
 	int ret;
 
-	ret = sprintf(buf, "ccw:t%04Xm%02x",
+	ret = sprintf(buf, "ccw:t%04Xm%02X",
 			id->cu_type, id->cu_model);
 	if (id->dev_type != 0)
 		ret += sprintf(buf + ret, "dt%04Xdm%02X\n",
@@ -1013,7 +1012,7 @@
 	int ret;
 
 	if (xchg(&console_cdev_in_use, 1) != 0)
-		return NULL;
+		return ERR_PTR(-EBUSY);
 	sch = cio_probe_console();
 	if (IS_ERR(sch)) {
 		console_cdev_in_use = 0;
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 8b02189..3a50b19 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,8 +1,6 @@
 /*
  *  drivers/s390/cio/device_ops.c
  *
- *   $Revision: 1.61 $
- *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 77be2c3..45ce032 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,8 +56,6 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.117 $"
-
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
 MODULE_DESCRIPTION("QDIO base support version 2, " \
@@ -66,8 +64,7 @@
 
 /******************** HERE WE GO ***********************************/
 
-static const char version[] = "QDIO base support version 2 ("
-	VERSION_QDIO_C "/" VERSION_QDIO_H  "/" VERSION_CIO_QDIO_H ")";
+static const char version[] = "QDIO base support version 2";
 
 #ifdef QDIO_PERFORMANCE_STATS
 static int proc_perf_file_registration;
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index fa385e7..ceb3ab3 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -5,8 +5,6 @@
 
 #include "schid.h"
 
-#define VERSION_CIO_QDIO_H "$Revision: 1.40 $"
-
 #ifdef CONFIG_QDIO_DEBUG
 #define QDIO_VERBOSE_LEVEL 9
 #else /* CONFIG_QDIO_DEBUG */
diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h
index f87c785..dbbcda3 100644
--- a/drivers/s390/crypto/z90common.h
+++ b/drivers/s390/crypto/z90common.h
@@ -27,8 +27,6 @@
 #ifndef _Z90COMMON_H_
 #define _Z90COMMON_H_
 
-#define VERSION_Z90COMMON_H "$Revision: 1.17 $"
-
 
 #define RESPBUFFSIZE 256
 #define PCI_FUNC_KEY_DECRYPT 0x5044
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h
index 3a18443..5e6b1f5 100644
--- a/drivers/s390/crypto/z90crypt.h
+++ b/drivers/s390/crypto/z90crypt.h
@@ -29,8 +29,6 @@
 
 #include <linux/ioctl.h>
 
-#define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $"
-
 #define z90crypt_VERSION 1
 #define z90crypt_RELEASE 3	// 2 = PCIXCC, 3 = rewrite for coding standards
 #define z90crypt_VARIANT 3	// 3 = CEX2A support
diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c
index d7f7494..4141919 100644
--- a/drivers/s390/crypto/z90hardware.c
+++ b/drivers/s390/crypto/z90hardware.c
@@ -32,12 +32,6 @@
 #include "z90crypt.h"
 #include "z90common.h"
 
-#define VERSION_Z90HARDWARE_C "$Revision: 1.34 $"
-
-char z90hardware_version[] __initdata =
-	"z90hardware.o (" VERSION_Z90HARDWARE_C "/"
-	                  VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")";
-
 struct cca_token_hdr {
 	unsigned char  token_identifier;
 	unsigned char  version;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 2f54d03..7d6f190 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -38,14 +38,6 @@
 #include "z90crypt.h"
 #include "z90common.h"
 
-#define VERSION_Z90MAIN_C "$Revision: 1.62 $"
-
-static char z90main_version[] __initdata =
-	"z90main.o (" VERSION_Z90MAIN_C "/"
-                      VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")";
-
-extern char z90hardware_version[];
-
 /**
  * Defaults that may be modified.
  */
@@ -594,8 +586,6 @@
 		PRINTKN("Version %d.%d.%d loaded, built on %s %s\n",
 			z90crypt_VERSION, z90crypt_RELEASE, z90crypt_VARIANT,
 			__DATE__, __TIME__);
-		PRINTKN("%s\n", z90main_version);
-		PRINTKN("%s\n", z90hardware_version);
 		PDEBUG("create_z90crypt (domain index %d) successful.\n",
 		       domain);
 	} else
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index e70af7f..a86436a 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -2,8 +2,6 @@
  *  drivers/s390/net/claw.c
  *    ESCON CLAW network driver
  *
- *    $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $
- *
  *  Linux for zSeries version
  *    Copyright (C) 2002,2005 IBM Corporation
  *  Author(s) Original code written by:
@@ -4391,14 +4389,7 @@
 claw_init(void)
 {
 	int ret = 0;
-       printk(KERN_INFO "claw: starting driver "
-#ifdef MODULE
-                "module "
-#else
-                "compiled into kernel "
-#endif
-                " $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ \n");
-
+	printk(KERN_INFO "claw: starting driver\n");
 
 #ifdef FUNCTRACE
         printk(KERN_INFO "claw: %s() enter \n",__FUNCTION__);
diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h
index 3df7197..969be46 100644
--- a/drivers/s390/net/claw.h
+++ b/drivers/s390/net/claw.h
@@ -2,7 +2,7 @@
 *  Define constants                                    *
 *                                                      *
 ********************************************************/
-#define VERSION_CLAW_H "$Revision: 1.6 $"
+
 /*-----------------------------------------------------*
 *     CCW command codes for CLAW protocol              *
 *------------------------------------------------------*/
diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c
index 0e2a8bb..e6e72de 100644
--- a/drivers/s390/net/ctcdbug.c
+++ b/drivers/s390/net/ctcdbug.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.6 $)
+ * linux/drivers/s390/net/ctcdbug.c
  *
  * CTC / ESCON network driver - s390 dbf exploit.
  *
@@ -9,8 +9,6 @@
  *    Author(s): Original Code written by
  *			  Peter Tiedemann (ptiedem@de.ibm.com)
  *
- *    $Revision: 1.6 $	 $Date: 2005/05/11 08:10:17 $
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -80,4 +78,3 @@
 	return 0;
 }
 
-
diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
index 7d6afa1..413925e 100644
--- a/drivers/s390/net/ctcdbug.h
+++ b/drivers/s390/net/ctcdbug.h
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.6 $)
+ * linux/drivers/s390/net/ctcdbug.h
  *
  * CTC / ESCON network driver - s390 dbf exploit.
  *
@@ -9,8 +9,6 @@
  *    Author(s): Original Code written by
  *			  Peter Tiedemann (ptiedem@de.ibm.com)
  *
- *    $Revision: 1.6 $	 $Date: 2005/05/11 08:10:17 $
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 1901fee..af9f212 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,6 +1,4 @@
 /*
- * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $
- *
  * CTC / ESCON network driver
  *
  * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -37,8 +35,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $
- *
  */
 #undef DEBUG
 #include <linux/module.h>
@@ -248,22 +244,11 @@
 print_banner(void)
 {
 	static int printed = 0;
-	char vbuf[] = "$Revision: 1.79 $";
-	char *version = vbuf;
 
 	if (printed)
 		return;
-	if ((version = strchr(version, ':'))) {
-		char *p = strchr(version + 1, '$');
-		if (p)
-			*p = '\0';
-	} else
-		version = " ??? ";
-	printk(KERN_INFO "CTC driver Version%s"
-#ifdef DEBUG
-		    " (DEBUG-VERSION, " __DATE__ __TIME__ ")"
-#endif
-		    " initialized\n", version);
+
+	printk(KERN_INFO "CTC driver initialized\n");
 	printed = 1;
 }
 
diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h
index ba3605f..d2e835c 100644
--- a/drivers/s390/net/ctcmain.h
+++ b/drivers/s390/net/ctcmain.h
@@ -1,6 +1,4 @@
 /*
- * $Id: ctcmain.h,v 1.4 2005/03/24 09:04:17 mschwide Exp $
- *
  * CTC / ESCON network driver
  *
  * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -29,8 +27,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.4 $
- *
  */
 
 #ifndef _CTCMAIN_H_
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 93d1725..5cdcdbf 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -1,6 +1,4 @@
 /*
- * $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $
- *
  * CTC / ESCON network driver, tty interface.
  *
  * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
diff --git a/drivers/s390/net/ctctty.h b/drivers/s390/net/ctctty.h
index 84b2f8f..7254dc0 100644
--- a/drivers/s390/net/ctctty.h
+++ b/drivers/s390/net/ctctty.h
@@ -1,6 +1,4 @@
 /*
- * $Id: ctctty.h,v 1.4 2003/09/18 08:01:10 mschwide Exp $
- *
  * CTC / ESCON network driver, tty interface.
  *
  * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index 2014fb7..b125331 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -1,6 +1,4 @@
 /*
- * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $
- *
  * CTC / LCS ccw_device driver
  *
  * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
index 24029bd..6caf5fa 100644
--- a/drivers/s390/net/fsm.c
+++ b/drivers/s390/net/fsm.c
@@ -1,6 +1,4 @@
 /**
- * $Id: fsm.c,v 1.6 2003/10/15 11:37:29 mschwide Exp $
- *
  * A generic FSM based on fsm used in isdn4linux
  *
  */
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h
index 5b98253..af679c1 100644
--- a/drivers/s390/net/fsm.h
+++ b/drivers/s390/net/fsm.h
@@ -1,5 +1,3 @@
-/* $Id: fsm.h,v 1.1.1.1 2002/03/13 19:33:09 mschwide Exp $
- */
 #ifndef _FSM_H_
 #define _FSM_H_
 
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index ea81773..760e77e 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,6 +1,4 @@
 /* 
- * $Id: iucv.c,v 1.47 2005/11/21 11:35:22 mschwide Exp $
- *
  * IUCV network driver
  *
  * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -29,8 +27,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.47 $
- *
  */
 
 /* #define DEBUG */
@@ -355,17 +351,7 @@
 static void
 iucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.47 $";
-	char *version = vbuf;
-
-	if ((version = strchr(version, ':'))) {
-		char *p = strchr(version + 1, '$');
-		if (p)
-			*p = '\0';
-	} else
-		version = " ??? ";
-	printk(KERN_INFO
-	       "IUCV lowlevel driver Version%s initialized\n", version);
+	printk(KERN_INFO "IUCV lowlevel driver initialized\n");
 }
 
 /**
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index da8c515..6229ba4 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -11,8 +11,6 @@
  *			  Frank Pavlic (fpavlic@de.ibm.com) and
  *		 	  Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
- *    $Revision: 1.99 $	 $Date: 2005/05/11 08:10:17 $
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -59,9 +57,8 @@
 /**
  * initialization string for output
  */
-#define VERSION_LCS_C  "$Revision: 1.99 $"
 
-static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
+static char version[] __initdata = "LCS driver";
 static char debug_buffer[255];
 
 /**
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index a7f348e..08e60ad 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -6,8 +6,6 @@
 #include <linux/workqueue.h>
 #include <asm/ccwdev.h>
 
-#define VERSION_LCS_H "$Revision: 1.19 $"
-
 #define LCS_DBF_TEXT(level, name, text) \
 	do { \
 		debug_text_event(lcs_dbf_##name, level, text); \
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index ac4c4b8..71d3853 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,6 +1,4 @@
 /*
- * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $
- *
  * IUCV network driver
  *
  * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -31,8 +29,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV network driver $Revision: 1.69 $
- *
  */
 
 #undef DEBUG
@@ -2077,16 +2073,7 @@
 static void
 netiucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.69 $";
-	char *version = vbuf;
-
-	if ((version = strchr(version, ':'))) {
-		char *p = strchr(version + 1, '$');
-		if (p)
-			*p = '\0';
-	} else
-		version = " ??? ";
-	PRINT_INFO("NETIUCV driver Version%s initialized\n", version);
+	PRINT_INFO("NETIUCV driver initialized\n");
 }
 
 static void __exit
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index d238c7e..9a064d4 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -25,8 +25,6 @@
 
 #include "qeth_mpc.h"
 
-#define VERSION_QETH_H 		"$Revision: 1.152 $"
-
 #ifdef CONFIG_QETH_IPV6
 #define QETH_VERSION_IPV6 	":IPv6"
 #else
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index f94f1f25..b023131 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -1,6 +1,5 @@
 /*
- *
- * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $)
+ * linux/drivers/s390/net/qeth_eddp.c
  *
  * Enhanced Device Driver Packing (EDDP) support for the qeth driver.
  *
@@ -8,8 +7,6 @@
  *
  *    Author(s): Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.13 $	 $Date: 2005/05/04 20:19:18 $
- *
  */
 #include <linux/config.h>
 #include <linux/errno.h>
diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h
index e1b5186..cae9ba2 100644
--- a/drivers/s390/net/qeth_eddp.h
+++ b/drivers/s390/net/qeth_eddp.h
@@ -1,14 +1,12 @@
 /*
- * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.5 $)
+ * linux/drivers/s390/net/qeth_eddp.h
  *
- * Header file for qeth enhanced device driver pakcing.
+ * Header file for qeth enhanced device driver packing.
  *
  * Copyright 2004 IBM Corporation
  *
  *    Author(s): Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.5 $	 $Date: 2005/03/24 09:04:18 $
- *
  */
 #ifndef __QETH_EDDP_H__
 #define __QETH_EDDP_H__
diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
index c0b4c8d..e422b41 100644
--- a/drivers/s390/net/qeth_fs.h
+++ b/drivers/s390/net/qeth_fs.h
@@ -12,11 +12,6 @@
 #ifndef __QETH_FS_H__
 #define __QETH_FS_H__
 
-#define VERSION_QETH_FS_H "$Revision: 1.10 $"
-
-extern const char *VERSION_QETH_PROC_C;
-extern const char *VERSION_QETH_SYS_C;
-
 #ifdef CONFIG_PROC_FS
 extern int
 qeth_create_procfs_entries(void);
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 97f927c..410abea 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,5 @@
 /*
- *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.251 $)
+ * linux/drivers/s390/net/qeth_main.c
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,8 +11,6 @@
  *			  Frank Pavlic (fpavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.251 $	 $Date: 2005/05/04 20:19:18 $
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -73,7 +70,6 @@
 #include "qeth_eddp.h"
 #include "qeth_tso.h"
 
-#define VERSION_QETH_C "$Revision: 1.251 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -8626,12 +8622,7 @@
 {
 	int rc=0;
 
-	PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n",
-		   version, VERSION_QETH_C, VERSION_QETH_H,
-		   VERSION_QETH_MPC_H, VERSION_QETH_MPC_C,
-		   VERSION_QETH_FS_H, VERSION_QETH_PROC_C,
-		   VERSION_QETH_SYS_C, QETH_VERSION_IPV6,
-		   QETH_VERSION_VLAN);
+	PRINT_INFO("loading %s\n", version);
 
 	INIT_LIST_HEAD(&qeth_card_list.list);
 	INIT_LIST_HEAD(&qeth_notify_list);
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
index 5f8754a..77c8320 100644
--- a/drivers/s390/net/qeth_mpc.c
+++ b/drivers/s390/net/qeth_mpc.c
@@ -11,8 +11,6 @@
 #include <asm/cio.h>
 #include "qeth_mpc.h"
 
-const char *VERSION_QETH_MPC_C = "$Revision: 1.13 $";
-
 unsigned char IDX_ACTIVATE_READ[]={
 	0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
 	0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 864cec5..011c410 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -14,10 +14,6 @@
 
 #include <asm/qeth.h>
 
-#define VERSION_QETH_MPC_H "$Revision: 1.46 $"
-
-extern const char *VERSION_QETH_MPC_C;
-
 #define IPA_PDU_HEADER_SIZE	0x40
 #define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e)
 #define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26)
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 7bf3509..3c6339d 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.16 $)
+ * linux/drivers/s390/net/qeth_fs.c
  *
  * Linux on zSeries OSA Express and HiperSockets support
  * This file contains code related to procfs.
@@ -21,8 +21,6 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-const char *VERSION_QETH_PROC_C = "$Revision: 1.16 $";
-
 /***** /proc/qeth *****/
 #define QETH_PROCFILE_NAME "qeth"
 static struct proc_dir_entry *qeth_procfile;
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 0ea185f..c1831f5 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.60 $)
+ * linux/drivers/s390/net/qeth_sys.c
  *
  * Linux on zSeries OSA Express and HiperSockets support
  * This file contains code related to sysfs.
@@ -20,8 +20,6 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-const char *VERSION_QETH_SYS_C = "$Revision: 1.60 $";
-
 /*****************************************************************************/
 /*                                                                           */
 /*          /sys-fs stuff UNDER DEVELOPMENT !!!                              */
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
index 3c50b6f..1286dde 100644
--- a/drivers/s390/net/qeth_tso.h
+++ b/drivers/s390/net/qeth_tso.h
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.8 $)
+ * linux/drivers/s390/net/qeth_tso.h
  *
  * Header file for qeth TCP Segmentation Offload support.
  *
@@ -7,8 +7,6 @@
  *
  *    Author(s): Frank Pavlic <fpavlic@de.ibm.com>
  *
- *    $Revision: 1.8 $	 $Date: 2005/05/04 20:19:18 $
- *
  */
 #ifndef __QETH_TSO_H__
 #define __QETH_TSO_H__
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c
index 206518c..e3f6471 100644
--- a/drivers/s390/s390_rdev.c
+++ b/drivers/s390/s390_rdev.c
@@ -1,7 +1,6 @@
 /*
  *  drivers/s390/s390_rdev.c
  *  s390 root device
- *   $Revision: 1.4 $
  *
  *    Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
index d9ea7ed..7abb42a 100644
--- a/drivers/s390/s390mach.h
+++ b/drivers/s390/s390mach.h
@@ -90,15 +90,16 @@
 
 static inline int stcrw(struct crw *pcrw )
 {
-        int ccode;
+	int ccode;
 
-        __asm__ __volatile__(
-                "STCRW 0(%1)\n\t"
-                "IPM %0\n\t"
-                "SRL %0,28\n\t"
-                : "=d" (ccode) : "a" (pcrw)
-                : "cc", "1" );
-        return ccode;
+	__asm__ __volatile__(
+		"stcrw 0(%2)\n\t"
+		"ipm %0\n\t"
+		"srl %0,28\n\t"
+		: "=d" (ccode), "=m" (*pcrw)
+		: "a" (pcrw)
+		: "cc" );
+	return ccode;
 }
 
 #endif /* __s390mach */
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 167fef3..95b92f3 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -29,8 +29,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_AUX_REVISION "$Revision: 1.145 $"
-
 #include "zfcp_ext.h"
 
 /* accumulated log level (module parameter) */
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 0fc4638..241136d 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -27,8 +27,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_CCW_C_REVISION "$Revision: 1.58 $"
-
 #include "zfcp_ext.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 9559971..4d7d47c 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -23,8 +23,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_DBF_REVISION "$Revision$"
-
 #include <asm/debug.h>
 #include <linux/ctype.h>
 #include "zfcp_ext.h"
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 9bb5110..e260d19 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -34,8 +34,6 @@
 #ifndef ZFCP_DEF_H
 #define ZFCP_DEF_H
 
-#define ZFCP_DEF_REVISION "$Revision: 1.111 $"
-
 /*************************** INCLUDES *****************************************/
 
 #include <linux/init.h>
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index c065cb8..da947e6 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -31,8 +31,6 @@
 
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_ERP
 
-#define ZFCP_ERP_REVISION "$Revision: 1.86 $"
-
 #include "zfcp_ext.h"
 
 static int zfcp_erp_adisc(struct zfcp_port *);
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index c378226..c1ba7cf 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -32,8 +32,6 @@
 #ifndef ZFCP_EXT_H
 #define ZFCP_EXT_H
 
-#define ZFCP_EXT_REVISION "$Revision: 1.62 $"
-
 #include "zfcp_def.h"
 
 extern struct zfcp_data zfcp_data;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index cbfab09..9f0cb3d 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -30,8 +30,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_FSF_C_REVISION "$Revision: 1.92 $"
-
 #include "zfcp_ext.h"
 
 static int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *);
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index d719f66..1c32751 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -29,8 +29,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_QDIO_C_REVISION "$Revision: 1.20 $"
-
 #include "zfcp_ext.h"
 
 static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int);
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 3c2cbcc..e080375 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -31,8 +31,6 @@
 
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_SCSI
 
-#define ZFCP_SCSI_REVISION "$Revision: 1.74 $"
-
 #include "zfcp_ext.h"
 
 static void zfcp_scsi_slave_destroy(struct scsi_device *sdp);
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index 9f26225..dfc0737 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -27,8 +27,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.38 $"
-
 #include "zfcp_ext.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c
index 77a5e2d..6622d55 100644
--- a/drivers/s390/scsi/zfcp_sysfs_driver.c
+++ b/drivers/s390/scsi/zfcp_sysfs_driver.c
@@ -27,8 +27,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.17 $"
-
 #include "zfcp_ext.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index 3924eb3..f401d42 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -28,8 +28,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.47 $"
-
 #include "zfcp_ext.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index 2f50815..ad5dfb8 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -28,8 +28,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.30 $"
-
 #include "zfcp_ext.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 38d6d00..014cc8d 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -38,10 +38,10 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/blkdev.h>
+#include <linux/delay.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
 #include <asm/semaphore.h>
-#include <asm/delay.h>
 
 #include "aacraid.h"
 
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 19bd346..a800fb5 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -286,6 +286,10 @@
 	  board_ahci }, /* ICH8M */
 	{ PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ICH8M */
+	{ 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* JMicron JMB360 */
+	{ 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* JMicron JMB363 */
 	{ }	/* terminate list */
 };
 
@@ -802,7 +806,6 @@
 	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
 	void __iomem *mmio = probe_ent->mmio_base;
 	u32 tmp, cap_save;
-	u16 tmp16;
 	unsigned int i, j, using_dac;
 	int rc;
 	void __iomem *port_mmio;
@@ -836,9 +839,13 @@
 	writel(0xf, mmio + HOST_PORTS_IMPL);
 	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */
 
-	pci_read_config_word(pdev, 0x92, &tmp16);
-	tmp16 |= 0xf;
-	pci_write_config_word(pdev, 0x92, tmp16);
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+		u16 tmp16;
+
+		pci_read_config_word(pdev, 0x92, &tmp16);
+		tmp16 |= 0xf;
+		pci_write_config_word(pdev, 0x92, tmp16);
+	}
 
 	hpriv->cap = readl(mmio + HOST_CAP);
 	hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
@@ -1082,6 +1089,10 @@
 	if (have_msi)
 		hpriv->flags |= AHCI_FLAG_MSI;
 
+	/* JMicron-specific fixup: make sure we're in AHCI mode */
+	if (pdev->vendor == 0x197b)
+		pci_write_config_byte(pdev, 0x41, 0xa1);
+
 	/* initialize adapter */
 	rc = ahci_host_init(probe_ent);
 	if (rc)
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index 69ed77f..7955ebe 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -37,13 +37,13 @@
 config AIC79XX_RESET_DELAY_MS
 	int "Initial bus reset delay in milli-seconds"
 	depends on SCSI_AIC79XX
-	default "15000"
+	default "5000"
 	---help---
 	The number of milliseconds to delay after an initial bus reset.
 	The bus settle delay following all error recovery actions is
 	dictated by the SCSI layer and is not affected by this value.
 
-	Default: 15000 (15 seconds)
+	Default: 5000 (5 seconds)
 
 config AIC79XX_BUILD_FIRMWARE
 	bool "Build Adapter Firmware with Kernel Build"
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 2cfdbef..1d11f7e 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#109 $
  *
  * $FreeBSD$
  */
@@ -222,6 +222,7 @@
 typedef enum {
 	AHD_FENONE		= 0x00000,
 	AHD_WIDE  		= 0x00001,/* Wide Channel */
+	AHD_AIC79XXB_SLOWCRC    = 0x00002,/* SLOWCRC bit should be set */
 	AHD_MULTI_FUNC		= 0x00100,/* Multi-Function/Channel Device */
 	AHD_TARGETMODE		= 0x01000,/* Has tested target mode support */
 	AHD_MULTIROLE		= 0x02000,/* Space for two roles at a time */
diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg
index 3a32047..be14e2e 100644
--- a/drivers/scsi/aic7xxx/aic79xx.reg
+++ b/drivers/scsi/aic7xxx/aic79xx.reg
@@ -1,7 +1,7 @@
 /*
  * Aic79xx register and scratch ram definitions.
  *
- * Copyright (c) 1994-2001 Justin T. Gibbs.
+ * Copyright (c) 1994-2001, 2004 Justin T. Gibbs.
  * Copyright (c) 2000-2002 Adaptec Inc.
  * All rights reserved.
  *
@@ -39,7 +39,7 @@
  *
  * $FreeBSD$
  */
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $"
 
 /*
  * This file is processed by the aic7xxx_asm utility for use in assembling
@@ -3715,8 +3715,9 @@
 
 	SEQ_FLAGS2 {
 		size		1
-		field	TARGET_MSG_PENDING	  0x02
-		field	SELECTOUT_QFROZEN	  0x04
+		field	PENDING_MK_MESSAGE	0x01
+		field	TARGET_MSG_PENDING	0x02
+		field	SELECTOUT_QFROZEN	0x04
 	}
 
 	ALLOCFIFO_SCBPTR {
@@ -3777,6 +3778,26 @@
 	CMDSIZE_TABLE {
 		size		8
 	}
+	/*
+	 * When an SCB with the MK_MESSAGE flag is
+	 * queued to the controller, it cannot enter
+	 * the waiting for selection list until the
+	 * selections for any previously queued
+	 * commands to that target complete.  During
+	 * the wait, the MK_MESSAGE SCB is queued
+	 * here.
+	 */
+	MK_MESSAGE_SCB {
+		size		2
+	}
+	/*
+	 * Saved SCSIID of MK_MESSAGE_SCB to avoid
+	 * an extra SCBPTR operation when deciding
+	 * if the MK_MESSAGE_SCB can be run.
+	 */
+	MK_MESSAGE_SCSIID {
+		size		1
+	}
 }
 
 /************************* Hardware SCB Definition ****************************/
diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq
index bef1f9d..58bc175 100644
--- a/drivers/scsi/aic7xxx/aic79xx.seq
+++ b/drivers/scsi/aic7xxx/aic79xx.seq
@@ -1,7 +1,7 @@
 /*
  * Adaptec U320 device driver firmware for Linux and FreeBSD.
  *
- * Copyright (c) 1994-2001 Justin T. Gibbs.
+ * Copyright (c) 1994-2001, 2004 Justin T. Gibbs.
  * Copyright (c) 2000-2002 Adaptec Inc.
  * All rights reserved.
  *
@@ -40,7 +40,7 @@
  * $FreeBSD$
  */
 
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $"
 PATCH_ARG_LIST = "struct ahd_softc *ahd"
 PREFIX = "ahd_"
 
@@ -110,10 +110,8 @@
 	 * one last time.
 	 */
 	test	SSTAT0, SELDO jnz select_out;
-END_CRITICAL;
 	call	start_selection;
 idle_loop_checkbus:
-BEGIN_CRITICAL;
 	test	SSTAT0, SELDO jnz select_out;
 END_CRITICAL;
 	test	SSTAT0, SELDI jnz select_in;
@@ -294,7 +292,6 @@
 	test	CCSCBCTL, ARRDONE jz return;
 fetch_new_scb_done:
 	and	CCSCBCTL, ~(CCARREN|CCSCBEN);
-	bmov	REG0, SCBPTR, 2;
 	clr	A;
 	add	CMDS_PENDING, 1;
 	adc	CMDS_PENDING[1], A;
@@ -316,43 +313,117 @@
 	clr	SCB_FIFO_USE_COUNT;
 	/* Update the next SCB address to download. */
 	bmov	NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4;
+	/*
+	 * NULL out the SCB links since these fields
+	 * occupy the same location as SCB_NEXT_SCB_BUSADDR.
+	 */
 	mvi	SCB_NEXT[1], SCB_LIST_NULL;
 	mvi	SCB_NEXT2[1], SCB_LIST_NULL;
 	/* Increment our position in the QINFIFO. */
 	mov	NONE, SNSCB_QOFF;
+
 	/*
-	 * SCBs that want to send messages are always
-	 * queued independently.  This ensures that they
-	 * are at the head of the SCB list to select out
-	 * to a target and we will see the MK_MESSAGE flag.
+	 * Save SCBID of this SCB in REG0 since
+	 * SCBPTR will be clobbered during target
+	 * list updates.  We also record the SCB's
+	 * flags so that we can refer to them even
+	 * after SCBPTR has been changed.
 	 */
-	test	SCB_CONTROL, MK_MESSAGE jnz first_new_target_scb;
+	bmov	REG0, SCBPTR, 2;
+	mov	A, SCB_CONTROL;
+
+	/*
+	 * Find the tail SCB of the execution queue
+	 * for this target.
+	 */
 	shr	SINDEX, 3, SCB_SCSIID;
 	and	SINDEX, ~0x1;
 	mvi	SINDEX[1], (WAITING_SCB_TAILS >> 8);
 	bmov	DINDEX, SINDEX, 2;
 	bmov	SCBPTR, SINDIR, 2;
+
+	/*
+	 * Update the tail to point to the new SCB.
+	 */
 	bmov	DINDIR, REG0, 2;
+
+	/*
+	 * If the queue was empty, queue this SCB as
+	 * the first for this target.
+	 */
 	cmp	SCBPTR[1], SCB_LIST_NULL je first_new_target_scb;
+
+	/*
+	 * SCBs that want to send messages must always be
+	 * at the head of their per-target queue so that
+	 * ATN can be asserted even if the current
+	 * negotiation agreement is packetized.  If the
+	 * target queue is empty, the SCB can be queued
+	 * immediately.  If the queue is not empty, we must
+	 * wait for it to empty before entering this SCB
+	 * into the waiting for selection queue.  Otherwise
+	 * our batching and round-robin selection scheme 
+	 * could allow commands to be queued out of order.
+	 * To simplify the implementation, we stop pulling
+	 * new commands from the host until the MK_MESSAGE
+	 * SCB can be queued to the waiting for selection
+	 * list.
+	 */
+	test	A, MK_MESSAGE jz batch_scb; 
+
+	/*
+	 * If the last SCB is also a MK_MESSAGE SCB, then
+	 * order is preserved even if we batch.
+	 */
+	test	SCB_CONTROL, MK_MESSAGE jz batch_scb; 
+
+	/*
+	 * Defer this SCB and stop fetching new SCBs until
+	 * it can be queued.  Since the SCB_SCSIID of the
+	 * tail SCB must be the same as that of the newly
+	 * queued SCB, there is no need to restore the SCBID
+	 * here.
+	 */
+	or	SEQ_FLAGS2, PENDING_MK_MESSAGE;
+	bmov	MK_MESSAGE_SCB, REG0, 2;
+	mov	MK_MESSAGE_SCSIID, SCB_SCSIID ret;
+
+batch_scb:
+	/*
+	 * Otherwise just update the previous tail SCB to
+	 * point to the new tail.
+	 */
 	bmov	SCB_NEXT, REG0, 2 ret;
+
 first_new_target_scb:
+	/*
+	 * Append SCB to the tail of the waiting for
+	 * selection list.
+	 */
 	cmp	WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb;
 	bmov	SCBPTR, WAITING_TID_TAIL, 2;
 	bmov	SCB_NEXT2, REG0, 2;
 	bmov	WAITING_TID_TAIL, REG0, 2 ret;
 first_new_scb:
+	/*
+	 * Whole list is empty, so the head of
+	 * the list must be initialized too.
+	 */
 	bmov	WAITING_TID_HEAD, REG0, 2;
 	bmov	WAITING_TID_TAIL, REG0, 2 ret;
 END_CRITICAL;
 
 scbdma_idle:
 	/*
-	 * Give precedence to downloading new SCBs to execute
-	 * unless select-outs are currently frozen.
+	 * Don't bother downloading new SCBs to execute
+	 * if select-outs are currently frozen or we have
+	 * a MK_MESSAGE SCB waiting to enter the queue.
 	 */
-	test	SEQ_FLAGS2, SELECTOUT_QFROZEN jnz . + 2;
+	test	SEQ_FLAGS2, SELECTOUT_QFROZEN|PENDING_MK_MESSAGE
+		jnz scbdma_no_new_scbs;
 BEGIN_CRITICAL;
 	test	QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb;
+scbdma_no_new_scbs:
 	cmp	COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb;
 	cmp	COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return;
 	/* FALLTHROUGH */
@@ -671,27 +742,41 @@
 	}
 
 	/*
-	 * Requeue any SCBs not sent, to the tail of the waiting Q.
+	 * The whole list made it.  Clear our tail pointer to indicate
+	 * that the per-target selection queue is now empty.
 	 */
-	cmp	SCB_NEXT[1], SCB_LIST_NULL je select_out_list_done;
+	cmp	SCB_NEXT[1], SCB_LIST_NULL je select_out_clear_tail;
 
 	/*
+	 * Requeue any SCBs not sent, to the tail of the waiting Q.
 	 * We know that neither the per-TID list nor the list of
-	 * TIDs is empty.  Use this knowledge to our advantage.
+	 * TIDs is empty.  Use this knowledge to our advantage and
+	 * queue the remainder to the tail of the global execution
+	 * queue.
 	 */
 	bmov	REG0, SCB_NEXT, 2;
+select_out_queue_remainder:
 	bmov	SCBPTR, WAITING_TID_TAIL, 2;
 	bmov	SCB_NEXT2, REG0, 2;
 	bmov	WAITING_TID_TAIL, REG0, 2;
 	jmp	select_out_inc_tid_q;
 
-select_out_list_done:
+select_out_clear_tail:
 	/*
-	 * The whole list made it.  Just clear our TID's tail pointer
-	 * unless we were queued independently due to our need to
-	 * send a message.
+	 * Queue any pending MK_MESSAGE SCB for this target now
+	 * that the queue is empty.
 	 */
-	test	SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q;
+	test	SEQ_FLAGS2, PENDING_MK_MESSAGE jz select_out_no_mk_message_scb;
+	mov	A, MK_MESSAGE_SCSIID;
+	cmp	SCB_SCSIID, A jne select_out_no_mk_message_scb;
+	and	SEQ_FLAGS2, ~PENDING_MK_MESSAGE;
+	bmov	REG0, MK_MESSAGE_SCB, 2;
+	jmp select_out_queue_remainder;
+
+select_out_no_mk_message_scb:
+	/*
+	 * Clear this target's execution tail and increment the queue.
+	 */
 	shr	DINDEX, 3, SCB_SCSIID;
 	or	DINDEX, 1;	/* Want only the second byte */
 	mvi	DINDEX[1], ((WAITING_SCB_TAILS) >> 8);
@@ -703,8 +788,8 @@
 	mvi	WAITING_TID_TAIL[1], SCB_LIST_NULL;
 	bmov	SCBPTR, CURRSCB, 2;
 	mvi	CLRSINT0, CLRSELDO;
-	test	LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_phase;
-	test	LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_phase;
+	test	LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_mode_cleared;
+	test	LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_mode_cleared;
 
 	/*
 	 * If this is a packetized connection, return to our
@@ -2127,6 +2212,18 @@
 	mvi	DFFSXFRCTL, CLRCHN;
 unexpected_nonpkt_mode_cleared:
 	mvi	CLRSINT2, CLRNONPACKREQ;
+	if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
+		/*
+		 * Test to ensure that the bus has not
+		 * already gone free prior to clearing
+		 * any stale busfree status.  This avoids
+		 * a window whereby a busfree just after
+		 * a selection could be missed.
+		 */
+		test	SCSISIGI, BSYI jz . + 2;
+		mvi	CLRSINT1,CLRBUSFREE;
+		or	SIMODE1, ENBUSFREE;
+	}
 	test	SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase;
 	SET_SEQINTCODE(ENTERING_NONPACK)
 	jmp	ITloop;
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index db8f5ce..342f779 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#250 $
  */
 
 #ifdef __linux__
@@ -197,7 +197,8 @@
 					    char channel, int lun, u_int tag,
 					    role_t role, uint32_t status,
 					    ahd_search_action action,
-					    u_int *list_head, u_int tid);
+					    u_int *list_head, u_int *list_tail,
+					    u_int tid);
 static void		ahd_stitch_tid_list(struct ahd_softc *ahd,
 					    u_int tid_prev, u_int tid_cur,
 					    u_int tid_next);
@@ -1660,7 +1661,8 @@
 		 * so just clear the error.
 		 */
 		ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ);
-	} else if ((status & BUSFREE) != 0) {
+	} else if ((status & BUSFREE) != 0
+		|| (lqistat1 & LQOBUSFREE) != 0) {
 		u_int lqostat1;
 		int   restart;
 		int   clear_fifo;
@@ -2025,10 +2027,6 @@
 		u_int waiting_t;
 		u_int next;
 
-		if ((busfreetime & BUSFREE_LQO) == 0)
-			printf("%s: Warning, BUSFREE time is 0x%x.  "
-			       "Expected BUSFREE_LQO.\n",
-			       ahd_name(ahd), busfreetime);
 		/*
 		 * The LQO manager detected an unexpected busfree
 		 * either:
@@ -2251,8 +2249,14 @@
 			struct ahd_tmode_tstate *tstate;
 
 			/*
-			 * PPR Rejected.  Try non-ppr negotiation
-			 * and retry command.
+			 * PPR Rejected.
+			 *
+			 * If the previous negotiation was packetized,
+			 * this could be because the device has been
+			 * reset without our knowledge.  Force our
+			 * current negotiation to async and retry the
+			 * negotiation.  Otherwise retry the command
+			 * with non-ppr negotiation.
 			 */
 #ifdef AHD_DEBUG
 			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
@@ -2261,11 +2265,34 @@
 			tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
 						    devinfo.our_scsiid,
 						    devinfo.target, &tstate);
-			tinfo->curr.transport_version = 2;
-			tinfo->goal.transport_version = 2;
-			tinfo->goal.ppr_options = 0;
-			ahd_qinfifo_requeue_tail(ahd, scb);
-			printerror = 0;
+			if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)!=0) {
+				ahd_set_width(ahd, &devinfo,
+					      MSG_EXT_WDTR_BUS_8_BIT,
+					      AHD_TRANS_CUR,
+					      /*paused*/TRUE);
+				ahd_set_syncrate(ahd, &devinfo,
+						/*period*/0, /*offset*/0,
+						/*ppr_options*/0,
+						AHD_TRANS_CUR,
+						/*paused*/TRUE);
+				/*
+				 * The expect PPR busfree handler below
+				 * will effect the retry and necessary
+				 * abort.
+				 */
+			} else {
+				tinfo->curr.transport_version = 2;
+				tinfo->goal.transport_version = 2;
+				tinfo->goal.ppr_options = 0;
+				/*
+				 * Remove any SCBs in the waiting for selection
+				 * queue that may also be for this target so
+				 * that command ordering is preserved.
+				 */
+				ahd_freeze_devq(ahd, scb);
+				ahd_qinfifo_requeue_tail(ahd, scb);
+				printerror = 0;
+			}
 		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
 			&& ppr_busfree == 0) {
 			/*
@@ -2280,6 +2307,12 @@
 				      MSG_EXT_WDTR_BUS_8_BIT,
 				      AHD_TRANS_CUR|AHD_TRANS_GOAL,
 				      /*paused*/TRUE);
+			/*
+			 * Remove any SCBs in the waiting for selection
+			 * queue that may also be for this target so that
+			 * command ordering is preserved.
+			 */
+			ahd_freeze_devq(ahd, scb);
 			ahd_qinfifo_requeue_tail(ahd, scb);
 			printerror = 0;
 		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)
@@ -2297,6 +2330,12 @@
 					/*ppr_options*/0,
 					AHD_TRANS_CUR|AHD_TRANS_GOAL,
 					/*paused*/TRUE);
+			/*
+			 * Remove any SCBs in the waiting for selection
+			 * queue that may also be for this target so that
+			 * command ordering is preserved.
+			 */
+			ahd_freeze_devq(ahd, scb);
 			ahd_qinfifo_requeue_tail(ahd, scb);
 			printerror = 0;
 		} else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0
@@ -2369,14 +2408,14 @@
 			 */
 			printf("%s: ", ahd_name(ahd));
 		}
-		if (lastphase != P_BUSFREE)
-			ahd_force_renegotiation(ahd, &devinfo);
 		printf("Unexpected busfree %s, %d SCBs aborted, "
 		       "PRGMCNT == 0x%x\n",
 		       ahd_lookup_phase_entry(lastphase)->phasemsg,
 		       aborted,
 		       ahd_inw(ahd, PRGMCNT));
 		ahd_dump_card_state(ahd);
+		if (lastphase != P_BUSFREE)
+			ahd_force_renegotiation(ahd, &devinfo);
 	}
 	/* Always restart the sequencer. */
 	return (1);
@@ -3293,6 +3332,15 @@
 		con_opts |= WIDEXFER;
 
 	/*
+	 * Slow down our CRC interval to be
+	 * compatible with packetized U320 devices
+	 * that can't handle a CRC at full speed
+	 */
+	if (ahd->features & AHD_AIC79XXB_SLOWCRC) {
+		con_opts |= ENSLOWCRC;
+	}
+
+	/*
 	 * During packetized transfers, the target will
 	 * give us the oportunity to send command packets
 	 * without us asserting attention.
@@ -3315,7 +3363,6 @@
 {
 	struct		scb *pending_scb;
 	int		pending_scb_count;
-	u_int		scb_tag;
 	int		paused;
 	u_int		saved_scbptr;
 	ahd_mode_state	saved_modes;
@@ -3333,7 +3380,6 @@
 	pending_scb_count = 0;
 	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
 		struct ahd_devinfo devinfo;
-		struct hardware_scb *pending_hscb;
 		struct ahd_initiator_tinfo *tinfo;
 		struct ahd_tmode_tstate *tstate;
 
@@ -3341,11 +3387,10 @@
 		tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
 					    devinfo.our_scsiid,
 					    devinfo.target, &tstate);
-		pending_hscb = pending_scb->hscb;
 		if ((tstate->auto_negotiate & devinfo.target_mask) == 0
 		 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
 			pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
-			pending_hscb->control &= ~MK_MESSAGE;
+			pending_scb->hscb->control &= ~MK_MESSAGE;
 		}
 		ahd_sync_scb(ahd, pending_scb,
 			     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
@@ -3377,18 +3422,15 @@
 		ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
 	saved_scbptr = ahd_get_scbptr(ahd);
 	/* Ensure that the hscbs down on the card match the new information */
-	for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {
-		struct	hardware_scb *pending_hscb;
+	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
+		u_int	scb_tag;
 		u_int	control;
 
-		pending_scb = ahd_lookup_scb(ahd, scb_tag);
-		if (pending_scb == NULL)
-			continue;
+		scb_tag = SCB_GET_TAG(pending_scb);
 		ahd_set_scbptr(ahd, scb_tag);
-		pending_hscb = pending_scb->hscb;
 		control = ahd_inb_scbram(ahd, SCB_CONTROL);
 		control &= ~MK_MESSAGE;
-		control |= pending_hscb->control & MK_MESSAGE;
+		control |= pending_scb->hscb->control & MK_MESSAGE;
 		ahd_outb(ahd, SCB_CONTROL, control);
 	}
 	ahd_set_scbptr(ahd, saved_scbptr);
@@ -6500,13 +6542,14 @@
 			      | ENLQIOVERI_LQ|ENLQIOVERI_NLQ);
 	ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC);
 	/*
-	 * An interrupt from LQOBUSFREE is made redundant by the
-	 * BUSFREE interrupt.  We choose to have the sequencer catch
-	 * LQOPHCHGINPKT errors manually for the command phase at the
-	 * start of a packetized selection case.
-	ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE|ENLQOPHACHGINPKT);
+	 * We choose to have the sequencer catch LQOPHCHGINPKT errors
+	 * manually for the command phase at the start of a packetized
+	 * selection case.  ENLQOBUSFREE should be made redundant by
+	 * the BUSFREE interrupt, but it seems that some LQOBUSFREE
+	 * events fail to assert the BUSFREE interrupt so we must
+	 * also enable LQOBUSFREE interrupts.
 	 */
-	ahd_outb(ahd, LQOMODE1, 0);
+	ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE);
 
 	/*
 	 * Setup sequencer interrupt handlers.
@@ -6617,6 +6660,8 @@
 	/* We don't have any waiting selections */
 	ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL);
 	ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL);
+	ahd_outw(ahd, MK_MESSAGE_SCB, SCB_LIST_NULL);
+	ahd_outw(ahd, MK_MESSAGE_SCSIID, 0xFF);
 	for (i = 0; i < AHD_NUM_TARGETS; i++)
 		ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL);
 
@@ -6704,6 +6749,18 @@
 
 	ahd_loadseq(ahd);
 	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+
+	if (ahd->features & AHD_AIC79XXB_SLOWCRC) {
+		u_int negodat3 = ahd_inb(ahd, NEGCONOPTS);
+
+		negodat3 |= ENSLOWCRC;
+		ahd_outb(ahd, NEGCONOPTS, negodat3);
+		negodat3 = ahd_inb(ahd, NEGCONOPTS);
+		if (!(negodat3 & ENSLOWCRC))
+			printf("aic79xx: failed to set the SLOWCRC bit\n");
+		else
+			printf("aic79xx: SLOWCRC bit set\n");
+	}
 }
 
 /*
@@ -7260,12 +7317,28 @@
 	ahd->flags &= ~AHD_UPDATE_PEND_CMDS;
 }
 
+void
+ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)
+{
+	cam_status ostat;
+	cam_status cstat;
+
+	ostat = ahd_get_transaction_status(scb);
+	if (ostat == CAM_REQ_INPROG)
+		ahd_set_transaction_status(scb, status);
+	cstat = ahd_get_transaction_status(scb);
+	if (cstat != CAM_REQ_CMP)
+		ahd_freeze_scb(scb);
+	ahd_done(ahd, scb);
+}
+
 int
 ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
 		   int lun, u_int tag, role_t role, uint32_t status,
 		   ahd_search_action action)
 {
 	struct scb	*scb;
+	struct scb	*mk_msg_scb;
 	struct scb	*prev_scb;
 	ahd_mode_state	 saved_modes;
 	u_int		 qinstart;
@@ -7274,6 +7347,7 @@
 	u_int		 tid_next;
 	u_int		 tid_prev;
 	u_int		 scbid;
+	u_int		 seq_flags2;
 	u_int		 savedscbptr;
 	uint32_t	 busaddr;
 	int		 found;
@@ -7329,23 +7403,10 @@
 			found++;
 			switch (action) {
 			case SEARCH_COMPLETE:
-			{
-				cam_status ostat;
-				cam_status cstat;
-
-				ostat = ahd_get_transaction_status(scb);
-				if (ostat == CAM_REQ_INPROG)
-					ahd_set_transaction_status(scb,
-								   status);
-				cstat = ahd_get_transaction_status(scb);
-				if (cstat != CAM_REQ_CMP)
-					ahd_freeze_scb(scb);
 				if ((scb->flags & SCB_ACTIVE) == 0)
 					printf("Inactive SCB in qinfifo\n");
-				ahd_done(ahd, scb);
-
+				ahd_done_with_status(ahd, scb, status);
 				/* FALLTHROUGH */
-			}
 			case SEARCH_REMOVE:
 				break;
 			case SEARCH_PRINT:
@@ -7375,21 +7436,24 @@
 	 * looking for matches.
 	 */
 	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+	seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2);
+	if ((seq_flags2 & PENDING_MK_MESSAGE) != 0) {
+		scbid = ahd_inw(ahd, MK_MESSAGE_SCB);
+		mk_msg_scb = ahd_lookup_scb(ahd, scbid);
+	} else
+		mk_msg_scb = NULL;
 	savedscbptr = ahd_get_scbptr(ahd);
 	tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
 	tid_prev = SCB_LIST_NULL;
 	targets = 0;
 	for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) {
 		u_int tid_head;
+		u_int tid_tail;
 
-		/*
-		 * We limit based on the number of SCBs since
-		 * MK_MESSAGE SCBs are not in the per-tid lists.
-		 */
 		targets++;
-		if (targets > AHD_SCB_MAX) {
+		if (targets > AHD_NUM_TARGETS)
 			panic("TID LIST LOOP");
-		}
+
 		if (scbid >= ahd->scb_data.numscbs) {
 			printf("%s: Waiting TID List inconsistency. "
 			       "SCB index == 0x%x, yet numscbs == 0x%x.",
@@ -7419,8 +7483,71 @@
 		tid_head = scbid;
 		found += ahd_search_scb_list(ahd, target, channel,
 					     lun, tag, role, status,
-					     action, &tid_head,
+					     action, &tid_head, &tid_tail,
 					     SCB_GET_TARGET(ahd, scb));
+		/*
+		 * Check any MK_MESSAGE SCB that is still waiting to
+		 * enter this target's waiting for selection queue.
+		 */
+		if (mk_msg_scb != NULL
+		 && ahd_match_scb(ahd, mk_msg_scb, target, channel,
+				  lun, tag, role)) {
+
+			/*
+			 * We found an scb that needs to be acted on.
+			 */
+			found++;
+			switch (action) {
+			case SEARCH_COMPLETE:
+				if ((mk_msg_scb->flags & SCB_ACTIVE) == 0)
+					printf("Inactive SCB pending MK_MSG\n");
+				ahd_done_with_status(ahd, mk_msg_scb, status);
+				/* FALLTHROUGH */
+			case SEARCH_REMOVE:
+			{
+				u_int tail_offset;
+
+				printf("Removing MK_MSG scb\n");
+
+				/*
+				 * Reset our tail to the tail of the
+				 * main per-target list.
+				 */
+				tail_offset = WAITING_SCB_TAILS
+				    + (2 * SCB_GET_TARGET(ahd, mk_msg_scb));
+				ahd_outw(ahd, tail_offset, tid_tail);
+
+				seq_flags2 &= ~PENDING_MK_MESSAGE;
+				ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
+				ahd_outw(ahd, CMDS_PENDING,
+					 ahd_inw(ahd, CMDS_PENDING)-1);
+				mk_msg_scb = NULL;
+				break;
+			}
+			case SEARCH_PRINT:
+				printf(" 0x%x", SCB_GET_TAG(scb));
+				/* FALLTHROUGH */
+			case SEARCH_COUNT:
+				break;
+			}
+		}
+
+		if (mk_msg_scb != NULL
+		 && SCBID_IS_NULL(tid_head)
+		 && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
+				  SCB_LIST_NULL, ROLE_UNKNOWN)) {
+
+			/*
+			 * When removing the last SCB for a target
+			 * queue with a pending MK_MESSAGE scb, we
+			 * must queue the MK_MESSAGE scb.
+			 */
+			printf("Queueing mk_msg_scb\n");
+			tid_head = ahd_inw(ahd, MK_MESSAGE_SCB);
+			seq_flags2 &= ~PENDING_MK_MESSAGE;
+			ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
+			mk_msg_scb = NULL;
+		}
 		if (tid_head != scbid)
 			ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next);
 		if (!SCBID_IS_NULL(tid_head))
@@ -7428,6 +7555,8 @@
 		if (action == SEARCH_PRINT)
 			printf(")\n");
 	}
+
+	/* Restore saved state. */
 	ahd_set_scbptr(ahd, savedscbptr);
 	ahd_restore_modes(ahd, saved_modes);
 	return (found);
@@ -7436,7 +7565,8 @@
 static int
 ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
 		    int lun, u_int tag, role_t role, uint32_t status,
-		    ahd_search_action action, u_int *list_head, u_int tid)
+		    ahd_search_action action, u_int *list_head, 
+		    u_int *list_tail, u_int tid)
 {
 	struct	scb *scb;
 	u_int	scbid;
@@ -7448,6 +7578,7 @@
 	found = 0;
 	prev = SCB_LIST_NULL;
 	next = *list_head;
+	*list_tail = SCB_LIST_NULL;
 	for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) {
 		if (scbid >= ahd->scb_data.numscbs) {
 			printf("%s:SCB List inconsistency. "
@@ -7463,6 +7594,7 @@
 			panic("Waiting List traversal\n");
 		}
 		ahd_set_scbptr(ahd, scbid);
+		*list_tail = scbid;
 		next = ahd_inw_scbram(ahd, SCB_NEXT);
 		if (ahd_match_scb(ahd, scb, target, channel,
 				  lun, SCB_LIST_NULL, role) == 0) {
@@ -7472,24 +7604,14 @@
 		found++;
 		switch (action) {
 		case SEARCH_COMPLETE:
-		{
-			cam_status ostat;
-			cam_status cstat;
-
-			ostat = ahd_get_transaction_status(scb);
-			if (ostat == CAM_REQ_INPROG)
-				ahd_set_transaction_status(scb, status);
-			cstat = ahd_get_transaction_status(scb);
-			if (cstat != CAM_REQ_CMP)
-				ahd_freeze_scb(scb);
 			if ((scb->flags & SCB_ACTIVE) == 0)
 				printf("Inactive SCB in Waiting List\n");
-			ahd_done(ahd, scb);
+			ahd_done_with_status(ahd, scb, status);
 			/* FALLTHROUGH */
-		}
 		case SEARCH_REMOVE:
 			ahd_rem_wscb(ahd, scbid, prev, next, tid);
-			if (prev == SCB_LIST_NULL)
+			*list_tail = prev;
+			if (SCBID_IS_NULL(prev))
 				*list_head = next;
 			break;
 		case SEARCH_PRINT:
@@ -7558,14 +7680,17 @@
 	}
 
 	/*
-	 * SCBs that had MK_MESSAGE set in them will not
-	 * be queued to the per-target lists, so don't
-	 * blindly clear the tail pointer.
+	 * SCBs that have MK_MESSAGE set in them may
+	 * cause the tail pointer to be updated without
+	 * setting the next pointer of the previous tail.
+	 * Only clear the tail if the removed SCB was
+	 * the tail.
 	 */
 	tail_offset = WAITING_SCB_TAILS + (2 * tid);
 	if (SCBID_IS_NULL(next)
 	 && ahd_inw(ahd, tail_offset) == scbid)
 		ahd_outw(ahd, tail_offset, prev);
+
 	ahd_add_scb_to_free_list(ahd, scbid);
 	return (next);
 }
@@ -8148,11 +8273,6 @@
 		ahd_setup_data_scb(ahd, scb);
 		scb->flags |= SCB_SENSE;
 		ahd_queue_scb(ahd, scb);
-		/*
-		 * Ensure we have enough time to actually
-		 * retrieve the sense.
-		 */
-		ahd_scb_timer_reset(scb, 5 * 1000000);
 		break;
 	}
 	case SCSI_STATUS_OK:
@@ -8793,6 +8913,9 @@
 	 * Mode independent registers.
 	 */
 	cur_col = 0;
+	ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50);
+	ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50);
+	ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50);
 	ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50);
 	ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50);
 	ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50);
@@ -8808,6 +8931,12 @@
 	ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50);
 	ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50);
 	ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50);
+	ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50);
+	ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT),
+				       &cur_col, 50);
+	ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50);
+	ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID),
+				    &cur_col, 50);
 	ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50);
 	ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50);
 	ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50);
@@ -8915,7 +9044,7 @@
 
 		ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
 		fifo_scbptr = ahd_get_scbptr(ahd);
-		printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
+		printf("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
 		       ahd_name(ahd), i,
 		       (dffstat & (FIFO0FREE << i)) ? "Free" : "Active",
 		       ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr);
@@ -8970,6 +9099,9 @@
 	printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n",
 	       ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT),
 	       ahd_inb(ahd, MAXCMDCNT));
+	printf("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n",
+	       ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID),
+	       ahd_inb(ahd, SAVED_LUN));
 	ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50);
 	printf("\n");
 	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
index 91c4f7f..8ad3ce9 100644
--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
+++ b/drivers/scsi/aic7xxx/aic79xx_inline.h
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#59 $
  *
  * $FreeBSD$
  */
@@ -804,9 +804,10 @@
 		uint64_t host_dataptr;
 
 		host_dataptr = ahd_le64toh(scb->hscb->dataptr);
-		printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
+		printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
 		       ahd_name(ahd),
-		       SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr),
+		       SCB_GET_TAG(scb), scb->hscb->scsiid,
+		       ahd_le32toh(scb->hscb->hscb_busaddr),
 		       (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
 		       (u_int)(host_dataptr & 0xFFFFFFFF),
 		       ahd_le32toh(scb->hscb->datacnt));
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 2567e29..7254ea5 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -314,6 +314,21 @@
  */
 uint32_t aic79xx_periodic_otag;
 
+/* Some storage boxes are using an LSI chip which has a bug making it
+ * impossible to use aic79xx Rev B chip in 320 speeds.  The following
+ * storage boxes have been reported to be buggy:
+ * EonStor 3U 16-Bay: U16U-G3A3
+ * EonStor 2U 12-Bay: U12U-G3A3
+ * SentinelRAID: 2500F R5 / R6
+ * SentinelRAID: 2500F R1
+ * SentinelRAID: 2500F/1500F
+ * SentinelRAID: 150F
+ * 
+ * To get around this LSI bug, you can set your board to 160 mode
+ * or you can enable the SLOWCRC bit.
+ */
+uint32_t aic79xx_slowcrc;
+
 /*
  * Module information and settable options.
  */
@@ -343,6 +358,7 @@
 "	amplitude:<int>		Set the signal amplitude (0-7).\n"
 "	seltime:<int>		Selection Timeout:\n"
 "				(0/256ms,1/128ms,2/64ms,3/32ms)\n"
+"	slowcrc			Turn on the SLOWCRC bit (Rev B only)\n"		 
 "\n"
 "	Sample /etc/modprobe.conf line:\n"
 "		Enable verbose logging\n"
@@ -1003,6 +1019,7 @@
 		{ "slewrate", NULL },
 		{ "precomp", NULL },
 		{ "amplitude", NULL },
+		{ "slowcrc", &aic79xx_slowcrc },
 	};
 
 	end = strchr(s, '\0');
@@ -1072,7 +1089,6 @@
 		return (ENOMEM);
 
 	*((struct ahd_softc **)host->hostdata) = ahd;
-	ahd_lock(ahd, &s);
 	ahd->platform_data->host = host;
 	host->can_queue = AHD_MAX_QUEUE;
 	host->cmd_per_lun = 2;
@@ -1083,7 +1099,9 @@
 	host->max_lun = AHD_NUM_LUNS;
 	host->max_channel = 0;
 	host->sg_tablesize = AHD_NSEG;
+	ahd_lock(ahd, &s);
 	ahd_set_unit(ahd, ahd_linux_unit++);
+	ahd_unlock(ahd, &s);
 	sprintf(buf, "scsi%d", host->host_no);
 	new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
 	if (new_name != NULL) {
@@ -1093,7 +1111,6 @@
 	host->unique_id = ahd->unit;
 	ahd_linux_initialize_scsi_bus(ahd);
 	ahd_intr_enable(ahd, TRUE);
-	ahd_unlock(ahd, &s);
 
 	host->transportt = ahd_linux_transport_template;
 
@@ -1127,6 +1144,7 @@
 {
 	u_int target_id;
 	u_int numtarg;
+	unsigned long s;
 
 	target_id = 0;
 	numtarg = 0;
@@ -1139,6 +1157,8 @@
 	else
 		numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
 
+	ahd_lock(ahd, &s);
+
 	/*
 	 * Force negotiation to async for all targets that
 	 * will not see an initial bus reset.
@@ -1155,16 +1175,12 @@
 		ahd_update_neg_request(ahd, &devinfo, tstate,
 				       tinfo, AHD_NEG_ALWAYS);
 	}
+	ahd_unlock(ahd, &s);
 	/* Give the bus some time to recover */
 	if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
 		ahd_freeze_simq(ahd);
-		init_timer(&ahd->platform_data->reset_timer);
-		ahd->platform_data->reset_timer.data = (u_long)ahd;
-		ahd->platform_data->reset_timer.expires =
-		    jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;
-		ahd->platform_data->reset_timer.function =
-		    (ahd_linux_callback_t *)ahd_release_simq;
-		add_timer(&ahd->platform_data->reset_timer);
+		msleep(AIC79XX_RESET_DELAY);
+		ahd_release_simq(ahd);
 	}
 }
 
@@ -2033,6 +2049,9 @@
 void
 ahd_freeze_simq(struct ahd_softc *ahd)
 {
+	unsigned long s;
+
+	ahd_lock(ahd, &s);
 	ahd->platform_data->qfrozen++;
 	if (ahd->platform_data->qfrozen == 1) {
 		scsi_block_requests(ahd->platform_data->host);
@@ -2040,6 +2059,7 @@
 					CAM_LUN_WILDCARD, SCB_LIST_NULL,
 					ROLE_INITIATOR, CAM_REQUEUE_REQ);
 	}
+	ahd_unlock(ahd, &s);
 }
 
 void
@@ -2344,8 +2364,9 @@
 			       ahd_name(ahd), dev->active);
 			retval = FAILED;
 		}
-	}
-	ahd_unlock(ahd, &flags);
+	} else
+		ahd_unlock(ahd, &flags);
+
 	return (retval);
 }
 
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index cb74fcc..9cb1013 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -36,7 +36,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#137 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#166 $
  *
  */
 #ifndef _AIC79XX_LINUX_H_
@@ -228,7 +228,6 @@
 typedef void ahd_linux_callback_t (u_long);  
 static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
 				     ahd_callback_t *func, void *arg);
-static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
 
 static __inline void
 ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
@@ -243,12 +242,6 @@
 	add_timer(timer);
 }
 
-static __inline void
-ahd_scb_timer_reset(struct scb *scb, u_int usec)
-{
-	mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
-}
-
 /***************************** SMP support ************************************/
 #include <linux/spinlock.h>
 
@@ -389,7 +382,6 @@
 
 	spinlock_t		 spin_lock;
 	u_int			 qfrozen;
-	struct timer_list	 reset_timer;
 	struct semaphore	 eh_sem;
 	struct Scsi_Host        *host;		/* pointer to scsi host */
 #define AHD_LINUX_NOIRQ	((uint32_t)~0)
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index bf360ae..ebbf7e4 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -220,10 +220,10 @@
 	*base2 = pci_resource_start(ahd->dev_softc, 3);
 	if (*base == 0 || *base2 == 0)
 		return (ENOMEM);
-	if (request_region(*base, 256, "aic79xx") == 0)
+	if (!request_region(*base, 256, "aic79xx"))
 		return (ENOMEM);
-	if (request_region(*base2, 256, "aic79xx") == 0) {
-		release_region(*base2, 256);
+	if (!request_region(*base2, 256, "aic79xx")) {
+		release_region(*base, 256);
 		return (ENOMEM);
 	}
 	return (0);
@@ -237,7 +237,7 @@
 	u_long	start;
 	u_long	base_page;
 	u_long	base_offset;
-	int	error;
+	int	error = 0;
 
 	if (aic79xx_allow_memio == 0)
 		return (ENOMEM);
@@ -245,16 +245,15 @@
 	if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) != 0)
 		return (ENOMEM);
 
-	error = 0;
 	start = pci_resource_start(ahd->dev_softc, 1);
 	base_page = start & PAGE_MASK;
 	base_offset = start - base_page;
 	if (start != 0) {
 		*bus_addr = start;
-		if (request_mem_region(start, 0x1000, "aic79xx") == 0)
+		if (!request_mem_region(start, 0x1000, "aic79xx"))
 			error = ENOMEM;
-		if (error == 0) {
-			*maddr = ioremap_nocache(base_page, base_offset + 256);
+		if (!error) {
+			*maddr = ioremap_nocache(base_page, base_offset + 512);
 			if (*maddr == NULL) {
 				error = ENOMEM;
 				release_mem_region(start, 0x1000);
@@ -344,7 +343,7 @@
 
 	error = request_irq(ahd->dev_softc->irq, ahd_linux_isr,
 			    SA_SHIRQ, "aic79xx", ahd);
-	if (error == 0)
+	if (!error)
 		ahd->platform_data->irq = ahd->dev_softc->irq;
 	
 	return (-error);
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 196a634..757242e 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -38,7 +38,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#92 $
  */
 
 #ifdef __linux__
@@ -950,12 +950,19 @@
 		if ((ahd->flags & AHD_HP_BOARD) == 0)
 			AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);
 	} else {
+		/* This is revision B and newer. */
+		extern uint32_t aic79xx_slowcrc;
 		u_int devconfig1;
 
 		ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
-			      |  AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY;
+			      |  AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY
+			      |  AHD_BUSFREEREV_BUG;
 		ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;
 
+		/* If the user requested the the SLOWCRC bit to be set. */
+		if (aic79xx_slowcrc)
+			ahd->features |= AHD_AIC79XXB_SLOWCRC;
+
 		/*
 		 * Some issues have been resolved in the 7901B.
 		 */
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
index 8763b15..2068e00 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
  */
 typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
 typedef struct ahd_reg_parse_entry {
@@ -2204,6 +2204,20 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_mk_message_scb_print;
+#else
+#define ahd_mk_message_scb_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "MK_MESSAGE_SCB", 0x160, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_mk_message_scsiid_print;
+#else
+#define ahd_mk_message_scsiid_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "MK_MESSAGE_SCSIID", 0x162, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_scb_base_print;
 #else
 #define ahd_scb_base_print(regvalue, cur_col, wrap) \
@@ -3638,6 +3652,7 @@
 #define	SEQ_FLAGS2      		0x14d
 #define		SELECTOUT_QFROZEN	0x04
 #define		TARGET_MSG_PENDING	0x02
+#define		PENDING_MK_MESSAGE	0x01
 
 #define	ALLOCFIFO_SCBPTR		0x14e
 
@@ -3655,6 +3670,10 @@
 
 #define	CMDSIZE_TABLE   		0x158
 
+#define	MK_MESSAGE_SCB  		0x160
+
+#define	MK_MESSAGE_SCSIID		0x162
+
 #define	SCB_BASE        		0x180
 
 #define	SCB_RESIDUAL_DATACNT		0x180
@@ -3800,5 +3819,5 @@
 
 
 /* Exported Labels */
-#define	LABEL_seq_isr 	0x285
-#define	LABEL_timer_isr	0x281
+#define	LABEL_seq_isr 	0x28f
+#define	LABEL_timer_isr	0x28b
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
index a4137c9..db38a61 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
  */
 
 #include "aic79xx_osm.h"
@@ -3382,6 +3382,7 @@
 }
 
 static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
+	{ "PENDING_MK_MESSAGE",	0x01, 0x01 },
 	{ "TARGET_MSG_PENDING",	0x02, 0x02 },
 	{ "SELECTOUT_QFROZEN",	0x04, 0x04 }
 };
@@ -3389,7 +3390,7 @@
 int
 ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2",
+	return (ahd_print_register(SEQ_FLAGS2_parse_table, 3, "SEQ_FLAGS2",
 	    0x14d, regvalue, cur_col, wrap));
 }
 
@@ -3450,6 +3451,20 @@
 }
 
 int
+ahd_mk_message_scb_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "MK_MESSAGE_SCB",
+	    0x160, regvalue, cur_col, wrap));
+}
+
+int
+ahd_mk_message_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "MK_MESSAGE_SCSIID",
+	    0x162, regvalue, cur_col, wrap));
+}
+
+int
 ahd_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "SCB_BASE",
diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
index b1e5365..11bed07 100644
--- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
@@ -2,17 +2,17 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
  */
 static uint8_t seqprog[] = {
 	0xff, 0x02, 0x06, 0x78,
-	0x00, 0xea, 0x64, 0x59,
+	0x00, 0xea, 0x6e, 0x59,
 	0x01, 0xea, 0x04, 0x30,
 	0xff, 0x04, 0x0c, 0x78,
-	0x19, 0xea, 0x64, 0x59,
+	0x19, 0xea, 0x6e, 0x59,
 	0x19, 0xea, 0x04, 0x00,
-	0x33, 0xea, 0x5e, 0x59,
+	0x33, 0xea, 0x68, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x60, 0x3a, 0x3a, 0x68,
 	0x04, 0x4d, 0x35, 0x78,
@@ -33,15 +33,15 @@
 	0xff, 0xea, 0x62, 0x02,
 	0x00, 0xe2, 0x3a, 0x40,
 	0xff, 0x21, 0x3b, 0x70,
-	0x40, 0x4b, 0xaa, 0x69,
-	0x00, 0xe2, 0x68, 0x59,
-	0x40, 0x4b, 0xaa, 0x69,
-	0x20, 0x4b, 0x96, 0x69,
+	0x40, 0x4b, 0xb4, 0x69,
+	0x00, 0xe2, 0x72, 0x59,
+	0x40, 0x4b, 0xb4, 0x69,
+	0x20, 0x4b, 0xa0, 0x69,
 	0xfc, 0x42, 0x44, 0x78,
 	0x10, 0x40, 0x44, 0x78,
-	0x00, 0xe2, 0xfc, 0x5d,
+	0x00, 0xe2, 0x10, 0x5e,
 	0x20, 0x4d, 0x48, 0x78,
-	0x00, 0xe2, 0xfc, 0x5d,
+	0x00, 0xe2, 0x10, 0x5e,
 	0x30, 0x3f, 0xc0, 0x09,
 	0x30, 0xe0, 0x50, 0x60,
 	0x7f, 0x4a, 0x94, 0x08,
@@ -51,7 +51,7 @@
 	0x00, 0xe2, 0x76, 0x58,
 	0x00, 0xe2, 0x86, 0x58,
 	0x00, 0xe2, 0x06, 0x40,
-	0x33, 0xea, 0x5e, 0x59,
+	0x33, 0xea, 0x68, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x01, 0x52, 0x84, 0x78,
 	0x02, 0x58, 0x50, 0x31,
@@ -59,26 +59,26 @@
 	0xff, 0x97, 0x6f, 0x78,
 	0x50, 0x4b, 0x6a, 0x68,
 	0xbf, 0x3a, 0x74, 0x08,
-	0x14, 0xea, 0x64, 0x59,
+	0x14, 0xea, 0x6e, 0x59,
 	0x14, 0xea, 0x04, 0x00,
 	0x08, 0x92, 0x25, 0x03,
 	0xff, 0x90, 0x5f, 0x68,
-	0x00, 0xe2, 0x76, 0x5b,
+	0x00, 0xe2, 0x8a, 0x5b,
 	0x00, 0xe2, 0x5e, 0x40,
-	0x00, 0xea, 0x5e, 0x59,
+	0x00, 0xea, 0x68, 0x59,
 	0x01, 0xea, 0x00, 0x30,
 	0x80, 0xf9, 0x7e, 0x68,
-	0x00, 0xe2, 0x5c, 0x59,
-	0x11, 0xea, 0x5e, 0x59,
+	0x00, 0xe2, 0x66, 0x59,
+	0x11, 0xea, 0x68, 0x59,
 	0x11, 0xea, 0x00, 0x00,
-	0x80, 0xf9, 0x5c, 0x79,
+	0x80, 0xf9, 0x66, 0x79,
 	0xff, 0xea, 0xd4, 0x0d,
-	0x22, 0xea, 0x5e, 0x59,
+	0x22, 0xea, 0x68, 0x59,
 	0x22, 0xea, 0x00, 0x00,
 	0x10, 0x16, 0x90, 0x78,
 	0x10, 0x16, 0x2c, 0x00,
 	0x01, 0x0b, 0xae, 0x32,
-	0x18, 0xad, 0x12, 0x79,
+	0x18, 0xad, 0x1c, 0x79,
 	0x04, 0xad, 0xdc, 0x68,
 	0x80, 0xad, 0x84, 0x78,
 	0x10, 0xad, 0xaa, 0x78,
@@ -118,7 +118,6 @@
 	0x80, 0x18, 0x30, 0x04,
 	0x40, 0xad, 0x84, 0x78,
 	0xe7, 0xad, 0x5a, 0x09,
-	0x02, 0xa8, 0x40, 0x31,
 	0xff, 0xea, 0xc0, 0x09,
 	0x01, 0x54, 0xa9, 0x1a,
 	0x00, 0x55, 0xab, 0x22,
@@ -128,24 +127,30 @@
 	0xff, 0xea, 0x5a, 0x03,
 	0xff, 0xea, 0x5e, 0x03,
 	0x01, 0x10, 0xd4, 0x31,
-	0x10, 0x92, 0x07, 0x69,
+	0x02, 0xa8, 0x40, 0x31,
+	0x01, 0x92, 0xc1, 0x31,
 	0x3d, 0x93, 0xc5, 0x29,
 	0xfe, 0xe2, 0xc4, 0x09,
 	0x01, 0xea, 0xc6, 0x01,
 	0x02, 0xe2, 0xc8, 0x31,
 	0x02, 0xec, 0x50, 0x31,
 	0x02, 0xa0, 0xda, 0x31,
-	0xff, 0xa9, 0x06, 0x71,
+	0xff, 0xa9, 0x10, 0x71,
+	0x10, 0xe0, 0x0e, 0x79,
+	0x10, 0x92, 0x0f, 0x79,
+	0x01, 0x4d, 0x9b, 0x02,
+	0x02, 0xa0, 0xc0, 0x32,
+	0x01, 0x93, 0xc5, 0x36,
 	0x02, 0xa0, 0x58, 0x37,
-	0xff, 0x21, 0x0f, 0x71,
+	0xff, 0x21, 0x19, 0x71,
 	0x02, 0x22, 0x51, 0x31,
 	0x02, 0xa0, 0x5c, 0x33,
 	0x02, 0xa0, 0x44, 0x36,
 	0x02, 0xa0, 0x40, 0x32,
 	0x02, 0xa0, 0x44, 0x36,
-	0x04, 0x4d, 0x17, 0x69,
-	0x40, 0x16, 0x48, 0x69,
-	0xff, 0x2d, 0x4d, 0x61,
+	0x05, 0x4d, 0x21, 0x69,
+	0x40, 0x16, 0x52, 0x69,
+	0xff, 0x2d, 0x57, 0x61,
 	0xff, 0x29, 0x85, 0x70,
 	0x02, 0x28, 0x55, 0x32,
 	0x01, 0xea, 0x5a, 0x01,
@@ -159,22 +164,22 @@
 	0x01, 0x56, 0xad, 0x1a,
 	0xff, 0x54, 0xa9, 0x1a,
 	0xff, 0x55, 0xab, 0x22,
-	0xff, 0x8d, 0x41, 0x71,
-	0x80, 0xac, 0x40, 0x71,
-	0x20, 0x16, 0x40, 0x69,
+	0xff, 0x8d, 0x4b, 0x71,
+	0x80, 0xac, 0x4a, 0x71,
+	0x20, 0x16, 0x4a, 0x69,
 	0x00, 0xac, 0xc4, 0x19,
-	0x07, 0xe2, 0x40, 0xf9,
+	0x07, 0xe2, 0x4a, 0xf9,
 	0x02, 0x8c, 0x51, 0x31,
-	0x00, 0xe2, 0x24, 0x41,
+	0x00, 0xe2, 0x2e, 0x41,
 	0x01, 0xac, 0x08, 0x31,
 	0x09, 0xea, 0x5a, 0x01,
 	0x02, 0x8c, 0x51, 0x32,
 	0xff, 0xea, 0x1a, 0x07,
 	0x04, 0x24, 0xf9, 0x30,
-	0x1d, 0xea, 0x52, 0x41,
+	0x1d, 0xea, 0x5c, 0x41,
 	0x02, 0x2c, 0x51, 0x31,
 	0x04, 0xa8, 0xf9, 0x30,
-	0x19, 0xea, 0x52, 0x41,
+	0x19, 0xea, 0x5c, 0x41,
 	0x06, 0xea, 0x08, 0x81,
 	0x01, 0xe2, 0x5a, 0x35,
 	0x02, 0xf2, 0xf0, 0x31,
@@ -190,27 +195,27 @@
 	0x02, 0x20, 0xb9, 0x30,
 	0x02, 0x20, 0x51, 0x31,
 	0x4c, 0x93, 0xd7, 0x28,
-	0x10, 0x92, 0x77, 0x79,
+	0x10, 0x92, 0x81, 0x79,
 	0x01, 0x6b, 0xc0, 0x30,
 	0x02, 0x64, 0xc8, 0x00,
 	0x40, 0x3a, 0x74, 0x04,
 	0x00, 0xe2, 0x76, 0x58,
-	0x33, 0xea, 0x5e, 0x59,
+	0x33, 0xea, 0x68, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x30, 0x3f, 0xc0, 0x09,
-	0x30, 0xe0, 0x78, 0x61,
-	0x20, 0x3f, 0x8e, 0x69,
-	0x10, 0x3f, 0x78, 0x79,
+	0x30, 0xe0, 0x82, 0x61,
+	0x20, 0x3f, 0x98, 0x69,
+	0x10, 0x3f, 0x82, 0x79,
 	0x02, 0xea, 0x7e, 0x00,
-	0x00, 0xea, 0x5e, 0x59,
+	0x00, 0xea, 0x68, 0x59,
 	0x01, 0xea, 0x00, 0x30,
 	0x02, 0x4e, 0x51, 0x35,
 	0x01, 0xea, 0x7e, 0x00,
-	0x11, 0xea, 0x5e, 0x59,
+	0x11, 0xea, 0x68, 0x59,
 	0x11, 0xea, 0x00, 0x00,
 	0x02, 0x4e, 0x51, 0x35,
 	0xc0, 0x4a, 0x94, 0x00,
-	0x04, 0x41, 0x9c, 0x79,
+	0x04, 0x41, 0xa6, 0x79,
 	0x08, 0xea, 0x98, 0x00,
 	0x08, 0x57, 0xae, 0x00,
 	0x08, 0x3c, 0x78, 0x00,
@@ -218,12 +223,12 @@
 	0x0f, 0x67, 0xc0, 0x09,
 	0x00, 0x3a, 0x75, 0x02,
 	0x20, 0xea, 0x96, 0x00,
-	0x00, 0xe2, 0x14, 0x42,
+	0x00, 0xe2, 0x28, 0x42,
 	0xc0, 0x4a, 0x94, 0x00,
-	0x40, 0x3a, 0xc8, 0x69,
+	0x40, 0x3a, 0xd2, 0x69,
 	0x02, 0x55, 0x06, 0x68,
-	0x02, 0x56, 0xc8, 0x69,
-	0xff, 0x5b, 0xc8, 0x61,
+	0x02, 0x56, 0xd2, 0x69,
+	0xff, 0x5b, 0xd2, 0x61,
 	0x02, 0x20, 0x51, 0x31,
 	0x80, 0xea, 0xb2, 0x01,
 	0x44, 0xea, 0x00, 0x00,
@@ -231,40 +236,45 @@
 	0x33, 0xea, 0x00, 0x00,
 	0xff, 0xea, 0xb2, 0x09,
 	0xff, 0xe0, 0xc0, 0x19,
-	0xff, 0xe0, 0xca, 0x79,
+	0xff, 0xe0, 0xd4, 0x79,
 	0x02, 0xac, 0x51, 0x31,
-	0x00, 0xe2, 0xc0, 0x41,
+	0x00, 0xe2, 0xca, 0x41,
 	0x02, 0x5e, 0x50, 0x31,
 	0x02, 0xa8, 0xb8, 0x30,
 	0x02, 0x5c, 0x50, 0x31,
-	0xff, 0xad, 0xdb, 0x71,
+	0xff, 0xad, 0xe5, 0x71,
 	0x02, 0xac, 0x41, 0x31,
 	0x02, 0x22, 0x51, 0x31,
 	0x02, 0xa0, 0x5c, 0x33,
 	0x02, 0xa0, 0x44, 0x32,
-	0x00, 0xe2, 0xe4, 0x41,
-	0x10, 0x92, 0xe5, 0x69,
+	0x00, 0xe2, 0xf8, 0x41,
+	0x01, 0x4d, 0xf1, 0x79,
+	0x01, 0x62, 0xc1, 0x31,
+	0x00, 0x93, 0xf1, 0x61,
+	0xfe, 0x4d, 0x9b, 0x0a,
+	0x02, 0x60, 0x41, 0x31,
+	0x00, 0xe2, 0xdc, 0x41,
 	0x3d, 0x93, 0xc9, 0x29,
 	0x01, 0xe4, 0xc8, 0x01,
 	0x01, 0xea, 0xca, 0x01,
 	0xff, 0xea, 0xda, 0x01,
 	0x02, 0x20, 0x51, 0x31,
 	0x02, 0xae, 0x41, 0x32,
-	0xff, 0x21, 0xed, 0x61,
+	0xff, 0x21, 0x01, 0x62,
 	0xff, 0xea, 0x46, 0x02,
 	0x02, 0x5c, 0x50, 0x31,
 	0x40, 0xea, 0x96, 0x00,
-	0x02, 0x56, 0x04, 0x6e,
-	0x01, 0x55, 0x04, 0x6e,
-	0x10, 0x92, 0xf9, 0x79,
-	0x10, 0x40, 0x02, 0x6a,
-	0x01, 0x56, 0x02, 0x7a,
+	0x02, 0x56, 0x20, 0x6e,
+	0x01, 0x55, 0x20, 0x6e,
+	0x10, 0x92, 0x0d, 0x7a,
+	0x10, 0x40, 0x16, 0x6a,
+	0x01, 0x56, 0x16, 0x7a,
 	0xff, 0x97, 0x07, 0x78,
-	0x13, 0xea, 0x64, 0x59,
+	0x13, 0xea, 0x6e, 0x59,
 	0x13, 0xea, 0x04, 0x00,
 	0x00, 0xe2, 0x06, 0x40,
 	0xbf, 0x3a, 0x74, 0x08,
-	0x04, 0x41, 0x08, 0x7a,
+	0x04, 0x41, 0x1c, 0x7a,
 	0x08, 0xea, 0x98, 0x00,
 	0x08, 0x57, 0xae, 0x00,
 	0x01, 0x93, 0x75, 0x32,
@@ -272,108 +282,108 @@
 	0x40, 0xea, 0x72, 0x02,
 	0x08, 0x3c, 0x78, 0x00,
 	0x80, 0xea, 0x6e, 0x02,
-	0x00, 0xe2, 0xe2, 0x5b,
+	0x00, 0xe2, 0xf6, 0x5b,
 	0x01, 0x3c, 0xc1, 0x31,
-	0x9f, 0xe0, 0x84, 0x7c,
-	0x80, 0xe0, 0x28, 0x72,
-	0xa0, 0xe0, 0x64, 0x72,
-	0xc0, 0xe0, 0x5a, 0x72,
-	0xe0, 0xe0, 0x94, 0x72,
-	0x01, 0xea, 0x64, 0x59,
+	0x9f, 0xe0, 0x98, 0x7c,
+	0x80, 0xe0, 0x3c, 0x72,
+	0xa0, 0xe0, 0x78, 0x72,
+	0xc0, 0xe0, 0x6e, 0x72,
+	0xe0, 0xe0, 0xa8, 0x72,
+	0x01, 0xea, 0x6e, 0x59,
 	0x01, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x14, 0x42,
-	0x80, 0x39, 0x2f, 0x7a,
-	0x03, 0xea, 0x64, 0x59,
+	0x00, 0xe2, 0x28, 0x42,
+	0x80, 0x39, 0x43, 0x7a,
+	0x03, 0xea, 0x6e, 0x59,
 	0x03, 0xea, 0x04, 0x00,
-	0xee, 0x00, 0x36, 0x6a,
+	0xee, 0x00, 0x4a, 0x6a,
 	0x05, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x5e, 0x59,
+	0x33, 0xea, 0x68, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x02, 0xa8, 0x9c, 0x32,
-	0x00, 0xe2, 0x7e, 0x59,
+	0x00, 0xe2, 0x88, 0x59,
 	0xef, 0x96, 0xd5, 0x19,
-	0x00, 0xe2, 0x46, 0x52,
+	0x00, 0xe2, 0x5a, 0x52,
 	0x09, 0x80, 0xe1, 0x30,
 	0x02, 0xea, 0x36, 0x00,
 	0xa8, 0xea, 0x32, 0x00,
-	0x00, 0xe2, 0x4c, 0x42,
+	0x00, 0xe2, 0x60, 0x42,
 	0x01, 0x96, 0xd1, 0x30,
 	0x10, 0x80, 0x89, 0x31,
 	0x20, 0xea, 0x32, 0x00,
 	0xbf, 0x39, 0x73, 0x0a,
-	0x10, 0x4c, 0x56, 0x6a,
-	0x20, 0x19, 0x4e, 0x6a,
-	0x20, 0x19, 0x52, 0x6a,
-	0x02, 0x4d, 0x14, 0x6a,
+	0x10, 0x4c, 0x6a, 0x6a,
+	0x20, 0x19, 0x62, 0x6a,
+	0x20, 0x19, 0x66, 0x6a,
+	0x02, 0x4d, 0x28, 0x6a,
 	0x40, 0x39, 0x73, 0x02,
-	0x00, 0xe2, 0x14, 0x42,
-	0x80, 0x39, 0xd5, 0x6a,
+	0x00, 0xe2, 0x28, 0x42,
+	0x80, 0x39, 0xe9, 0x6a,
 	0x01, 0x44, 0x10, 0x33,
 	0x08, 0x92, 0x25, 0x03,
-	0x00, 0xe2, 0x14, 0x42,
+	0x00, 0xe2, 0x28, 0x42,
 	0x10, 0xea, 0x80, 0x00,
 	0x01, 0x37, 0xc5, 0x31,
-	0x80, 0xe2, 0x80, 0x62,
-	0x10, 0x92, 0xa5, 0x6a,
+	0x80, 0xe2, 0x94, 0x62,
+	0x10, 0x92, 0xb9, 0x6a,
 	0xc0, 0x94, 0xc5, 0x01,
-	0x40, 0x92, 0x71, 0x6a,
+	0x40, 0x92, 0x85, 0x6a,
 	0xbf, 0xe2, 0xc4, 0x09,
-	0x20, 0x92, 0x85, 0x7a,
+	0x20, 0x92, 0x99, 0x7a,
 	0x01, 0xe2, 0x88, 0x30,
-	0x00, 0xe2, 0xe2, 0x5b,
-	0xa0, 0x3c, 0x8d, 0x62,
+	0x00, 0xe2, 0xf6, 0x5b,
+	0xa0, 0x3c, 0xa1, 0x62,
 	0x23, 0x92, 0x89, 0x08,
-	0x00, 0xe2, 0xe2, 0x5b,
-	0xa0, 0x3c, 0x8d, 0x62,
-	0x00, 0xa8, 0x84, 0x42,
-	0xff, 0xe2, 0x84, 0x62,
-	0x00, 0xe2, 0xa4, 0x42,
+	0x00, 0xe2, 0xf6, 0x5b,
+	0xa0, 0x3c, 0xa1, 0x62,
+	0x00, 0xa8, 0x98, 0x42,
+	0xff, 0xe2, 0x98, 0x62,
+	0x00, 0xe2, 0xb8, 0x42,
 	0x40, 0xea, 0x98, 0x00,
 	0x01, 0xe2, 0x88, 0x30,
-	0x00, 0xe2, 0xe2, 0x5b,
-	0xa0, 0x3c, 0x63, 0x72,
+	0x00, 0xe2, 0xf6, 0x5b,
+	0xa0, 0x3c, 0x77, 0x72,
 	0x40, 0xea, 0x98, 0x00,
 	0x01, 0x37, 0x95, 0x32,
 	0x08, 0xea, 0x6e, 0x02,
-	0x00, 0xe2, 0x14, 0x42,
-	0xe0, 0xea, 0xfe, 0x5b,
-	0x80, 0xe0, 0xe0, 0x6a,
-	0x04, 0xe0, 0x92, 0x73,
-	0x02, 0xe0, 0xc4, 0x73,
-	0x00, 0xea, 0x3e, 0x73,
-	0x03, 0xe0, 0xd4, 0x73,
-	0x23, 0xe0, 0xb6, 0x72,
-	0x08, 0xe0, 0xdc, 0x72,
-	0x00, 0xe2, 0xe2, 0x5b,
-	0x07, 0xea, 0x64, 0x59,
+	0x00, 0xe2, 0x28, 0x42,
+	0xe0, 0xea, 0x12, 0x5c,
+	0x80, 0xe0, 0xf4, 0x6a,
+	0x04, 0xe0, 0xa6, 0x73,
+	0x02, 0xe0, 0xd8, 0x73,
+	0x00, 0xea, 0x52, 0x73,
+	0x03, 0xe0, 0xe8, 0x73,
+	0x23, 0xe0, 0xca, 0x72,
+	0x08, 0xe0, 0xf0, 0x72,
+	0x00, 0xe2, 0xf6, 0x5b,
+	0x07, 0xea, 0x6e, 0x59,
 	0x07, 0xea, 0x04, 0x00,
-	0x08, 0x48, 0x15, 0x72,
-	0x04, 0x48, 0xb3, 0x62,
+	0x08, 0x48, 0x29, 0x72,
+	0x04, 0x48, 0xc7, 0x62,
 	0x01, 0x49, 0x89, 0x30,
-	0x00, 0xe2, 0xa4, 0x42,
+	0x00, 0xe2, 0xb8, 0x42,
 	0x01, 0x44, 0xd4, 0x31,
-	0x00, 0xe2, 0xa4, 0x42,
+	0x00, 0xe2, 0xb8, 0x42,
 	0x01, 0x00, 0x6c, 0x32,
-	0x33, 0xea, 0x5e, 0x59,
+	0x33, 0xea, 0x68, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x4c, 0x3a, 0xc1, 0x28,
 	0x01, 0x64, 0xc0, 0x31,
-	0x00, 0x36, 0x5f, 0x59,
+	0x00, 0x36, 0x69, 0x59,
 	0x01, 0x36, 0x01, 0x30,
-	0x01, 0xe0, 0xda, 0x7a,
-	0xa0, 0xea, 0xf4, 0x5b,
-	0x01, 0xa0, 0xda, 0x62,
-	0x01, 0x84, 0xcf, 0x7a,
-	0x01, 0x95, 0xdd, 0x6a,
-	0x05, 0xea, 0x64, 0x59,
+	0x01, 0xe0, 0xee, 0x7a,
+	0xa0, 0xea, 0x08, 0x5c,
+	0x01, 0xa0, 0xee, 0x62,
+	0x01, 0x84, 0xe3, 0x7a,
+	0x01, 0x95, 0xf1, 0x6a,
+	0x05, 0xea, 0x6e, 0x59,
 	0x05, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xdc, 0x42,
-	0x03, 0xea, 0x64, 0x59,
+	0x00, 0xe2, 0xf0, 0x42,
+	0x03, 0xea, 0x6e, 0x59,
 	0x03, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xdc, 0x42,
-	0x07, 0xea, 0x06, 0x5c,
+	0x00, 0xe2, 0xf0, 0x42,
+	0x07, 0xea, 0x1a, 0x5c,
 	0x01, 0x44, 0xd4, 0x31,
-	0x00, 0xe2, 0x14, 0x42,
+	0x00, 0xe2, 0x28, 0x42,
 	0x3f, 0xe0, 0x76, 0x0a,
 	0xc0, 0x3a, 0xc1, 0x09,
 	0x00, 0x3b, 0x51, 0x01,
@@ -384,54 +394,54 @@
 	0x01, 0xea, 0xc6, 0x01,
 	0x02, 0xe2, 0xc8, 0x31,
 	0x02, 0xec, 0x40, 0x31,
-	0xff, 0xa1, 0xfc, 0x72,
+	0xff, 0xa1, 0x10, 0x73,
 	0x02, 0xe8, 0xda, 0x31,
 	0x02, 0xa0, 0x50, 0x31,
-	0x00, 0xe2, 0x1e, 0x43,
+	0x00, 0xe2, 0x32, 0x43,
 	0x80, 0x39, 0x73, 0x02,
 	0x01, 0x44, 0xd4, 0x31,
-	0x00, 0xe2, 0xe2, 0x5b,
+	0x00, 0xe2, 0xf6, 0x5b,
 	0x01, 0x39, 0x73, 0x02,
-	0xe0, 0x3c, 0x39, 0x63,
+	0xe0, 0x3c, 0x4d, 0x63,
 	0x02, 0x39, 0x73, 0x02,
-	0x20, 0x46, 0x32, 0x63,
+	0x20, 0x46, 0x46, 0x63,
 	0xff, 0xea, 0x52, 0x09,
-	0xa8, 0xea, 0xf4, 0x5b,
-	0x04, 0x92, 0x19, 0x7b,
+	0xa8, 0xea, 0x08, 0x5c,
+	0x04, 0x92, 0x2d, 0x7b,
 	0x01, 0x3a, 0xc1, 0x31,
-	0x00, 0x93, 0x19, 0x63,
+	0x00, 0x93, 0x2d, 0x63,
 	0x01, 0x3b, 0xc1, 0x31,
-	0x00, 0x94, 0x23, 0x73,
+	0x00, 0x94, 0x37, 0x73,
 	0x01, 0xa9, 0x52, 0x11,
-	0xff, 0xa9, 0x0e, 0x6b,
-	0x00, 0xe2, 0x32, 0x43,
+	0xff, 0xa9, 0x22, 0x6b,
+	0x00, 0xe2, 0x46, 0x43,
 	0x10, 0x39, 0x73, 0x02,
-	0x04, 0x92, 0x33, 0x7b,
+	0x04, 0x92, 0x47, 0x7b,
 	0xfb, 0x92, 0x25, 0x0b,
 	0xff, 0xea, 0x72, 0x0a,
-	0x01, 0xa4, 0x2d, 0x6b,
+	0x01, 0xa4, 0x41, 0x6b,
 	0x02, 0xa8, 0x9c, 0x32,
-	0x00, 0xe2, 0x7e, 0x59,
-	0x10, 0x92, 0xdd, 0x7a,
-	0xff, 0xea, 0x06, 0x5c,
-	0x00, 0xe2, 0xdc, 0x42,
-	0x04, 0xea, 0x64, 0x59,
+	0x00, 0xe2, 0x88, 0x59,
+	0x10, 0x92, 0xf1, 0x7a,
+	0xff, 0xea, 0x1a, 0x5c,
+	0x00, 0xe2, 0xf0, 0x42,
+	0x04, 0xea, 0x6e, 0x59,
 	0x04, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xdc, 0x42,
-	0x04, 0xea, 0x64, 0x59,
+	0x00, 0xe2, 0xf0, 0x42,
+	0x04, 0xea, 0x6e, 0x59,
 	0x04, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x14, 0x42,
-	0x08, 0x92, 0xd5, 0x7a,
-	0xc0, 0x39, 0x49, 0x7b,
-	0x80, 0x39, 0xd5, 0x6a,
-	0xff, 0x88, 0x49, 0x6b,
-	0x40, 0x39, 0xd5, 0x6a,
-	0x10, 0x92, 0x4f, 0x7b,
-	0x0a, 0xea, 0x64, 0x59,
+	0x00, 0xe2, 0x28, 0x42,
+	0x08, 0x92, 0xe9, 0x7a,
+	0xc0, 0x39, 0x5d, 0x7b,
+	0x80, 0x39, 0xe9, 0x6a,
+	0xff, 0x88, 0x5d, 0x6b,
+	0x40, 0x39, 0xe9, 0x6a,
+	0x10, 0x92, 0x63, 0x7b,
+	0x0a, 0xea, 0x6e, 0x59,
 	0x0a, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x6e, 0x5b,
-	0x00, 0xe2, 0xae, 0x43,
-	0x50, 0x4b, 0x56, 0x6b,
+	0x00, 0xe2, 0x82, 0x5b,
+	0x00, 0xe2, 0xc2, 0x43,
+	0x50, 0x4b, 0x6a, 0x6b,
 	0xbf, 0x3a, 0x74, 0x08,
 	0x01, 0xe0, 0xf4, 0x31,
 	0xff, 0xea, 0xc0, 0x09,
@@ -441,31 +451,31 @@
 	0x01, 0xfa, 0xc0, 0x35,
 	0x02, 0xa8, 0x90, 0x32,
 	0x02, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x5e, 0x59,
+	0x33, 0xea, 0x68, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x02, 0x48, 0x51, 0x31,
 	0xff, 0x90, 0x85, 0x68,
-	0xff, 0x88, 0x7b, 0x6b,
-	0x01, 0xa4, 0x77, 0x6b,
-	0x02, 0xa4, 0x7f, 0x6b,
-	0x01, 0x84, 0x7f, 0x7b,
+	0xff, 0x88, 0x8f, 0x6b,
+	0x01, 0xa4, 0x8b, 0x6b,
+	0x02, 0xa4, 0x93, 0x6b,
+	0x01, 0x84, 0x93, 0x7b,
 	0x02, 0x28, 0x19, 0x33,
 	0x02, 0xa8, 0x50, 0x36,
-	0xff, 0x88, 0x7f, 0x73,
-	0x00, 0xe2, 0x52, 0x5b,
+	0xff, 0x88, 0x93, 0x73,
+	0x00, 0xe2, 0x66, 0x5b,
 	0x02, 0xa8, 0x20, 0x33,
 	0x04, 0xa4, 0x49, 0x03,
 	0xff, 0xea, 0x1a, 0x03,
-	0xff, 0x2d, 0x8b, 0x63,
+	0xff, 0x2d, 0x9f, 0x63,
 	0x02, 0xa8, 0x58, 0x32,
 	0x02, 0xa8, 0x5c, 0x36,
 	0x02, 0xa8, 0x40, 0x31,
 	0x02, 0x2e, 0x51, 0x31,
 	0x02, 0xa0, 0x18, 0x33,
 	0x02, 0xa0, 0x5c, 0x36,
-	0xc0, 0x39, 0xd5, 0x6a,
+	0xc0, 0x39, 0xe9, 0x6a,
 	0x04, 0x92, 0x25, 0x03,
-	0x20, 0x92, 0xaf, 0x6b,
+	0x20, 0x92, 0xc3, 0x6b,
 	0x02, 0xa8, 0x40, 0x31,
 	0xc0, 0x3a, 0xc1, 0x09,
 	0x00, 0x3b, 0x51, 0x01,
@@ -480,60 +490,60 @@
 	0xf7, 0x57, 0xae, 0x08,
 	0x08, 0xea, 0x98, 0x00,
 	0x01, 0x44, 0xd4, 0x31,
-	0xee, 0x00, 0xb8, 0x6b,
+	0xee, 0x00, 0xcc, 0x6b,
 	0x02, 0xea, 0xb4, 0x00,
 	0xc0, 0xea, 0x72, 0x02,
-	0x09, 0x4c, 0xba, 0x7b,
+	0x09, 0x4c, 0xce, 0x7b,
 	0x01, 0xea, 0x78, 0x02,
 	0x08, 0x4c, 0x06, 0x68,
-	0x0b, 0xea, 0x64, 0x59,
+	0x0b, 0xea, 0x6e, 0x59,
 	0x0b, 0xea, 0x04, 0x00,
 	0x01, 0x44, 0xd4, 0x31,
-	0x20, 0x39, 0x15, 0x7a,
-	0x00, 0xe2, 0xcc, 0x5b,
-	0x00, 0xe2, 0x14, 0x42,
-	0x01, 0x84, 0xd1, 0x7b,
+	0x20, 0x39, 0x29, 0x7a,
+	0x00, 0xe2, 0xe0, 0x5b,
+	0x00, 0xe2, 0x28, 0x42,
+	0x01, 0x84, 0xe5, 0x7b,
 	0x01, 0xa4, 0x49, 0x07,
 	0x08, 0x60, 0x30, 0x33,
 	0x08, 0x80, 0x41, 0x37,
 	0xdf, 0x39, 0x73, 0x0a,
-	0xee, 0x00, 0xde, 0x6b,
+	0xee, 0x00, 0xf2, 0x6b,
 	0x05, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x5e, 0x59,
+	0x33, 0xea, 0x68, 0x59,
 	0x33, 0xea, 0x00, 0x00,
-	0x00, 0xe2, 0x7e, 0x59,
-	0x00, 0xe2, 0xdc, 0x42,
-	0xff, 0x42, 0xee, 0x6b,
-	0x01, 0x41, 0xe2, 0x6b,
-	0x02, 0x41, 0xe2, 0x7b,
-	0xff, 0x42, 0xee, 0x6b,
-	0x01, 0x41, 0xe2, 0x6b,
-	0x02, 0x41, 0xe2, 0x7b,
-	0xff, 0x42, 0xee, 0x7b,
-	0x04, 0x4c, 0xe2, 0x6b,
+	0x00, 0xe2, 0x88, 0x59,
+	0x00, 0xe2, 0xf0, 0x42,
+	0xff, 0x42, 0x02, 0x6c,
+	0x01, 0x41, 0xf6, 0x6b,
+	0x02, 0x41, 0xf6, 0x7b,
+	0xff, 0x42, 0x02, 0x6c,
+	0x01, 0x41, 0xf6, 0x6b,
+	0x02, 0x41, 0xf6, 0x7b,
+	0xff, 0x42, 0x02, 0x7c,
+	0x04, 0x4c, 0xf6, 0x6b,
 	0xe0, 0x41, 0x78, 0x0e,
 	0x01, 0x44, 0xd4, 0x31,
-	0xff, 0x42, 0xf6, 0x7b,
-	0x04, 0x4c, 0xf6, 0x6b,
+	0xff, 0x42, 0x0a, 0x7c,
+	0x04, 0x4c, 0x0a, 0x6c,
 	0xe0, 0x41, 0x78, 0x0a,
-	0xe0, 0x3c, 0x15, 0x62,
+	0xe0, 0x3c, 0x29, 0x62,
 	0xff, 0xea, 0xca, 0x09,
 	0x01, 0xe2, 0xc8, 0x31,
 	0x01, 0x46, 0xda, 0x35,
 	0x01, 0x44, 0xd4, 0x35,
 	0x10, 0xea, 0x80, 0x00,
 	0x01, 0xe2, 0x6e, 0x36,
-	0x04, 0xa6, 0x0e, 0x7c,
+	0x04, 0xa6, 0x22, 0x7c,
 	0xff, 0xea, 0x5a, 0x09,
 	0xff, 0xea, 0x4c, 0x0d,
-	0x01, 0xa6, 0x3a, 0x6c,
+	0x01, 0xa6, 0x4e, 0x6c,
 	0x10, 0xad, 0x84, 0x78,
-	0x80, 0xad, 0x32, 0x6c,
+	0x80, 0xad, 0x46, 0x6c,
 	0x08, 0xad, 0x84, 0x68,
-	0x20, 0x19, 0x26, 0x7c,
+	0x20, 0x19, 0x3a, 0x7c,
 	0x80, 0xea, 0xb2, 0x01,
 	0x11, 0x00, 0x00, 0x10,
-	0x02, 0xa6, 0x22, 0x7c,
+	0x02, 0xa6, 0x36, 0x7c,
 	0xff, 0xea, 0xb2, 0x0d,
 	0x11, 0x00, 0x00, 0x10,
 	0xff, 0xea, 0xb2, 0x09,
@@ -561,7 +571,7 @@
 	0x00, 0x86, 0x0d, 0x23,
 	0x00, 0x87, 0x0f, 0x23,
 	0x01, 0x84, 0xc5, 0x31,
-	0x80, 0x83, 0x5d, 0x7c,
+	0x80, 0x83, 0x71, 0x7c,
 	0x02, 0xe2, 0xc4, 0x01,
 	0xff, 0xea, 0x4c, 0x09,
 	0x01, 0xe2, 0x36, 0x30,
@@ -572,75 +582,75 @@
 	0xfe, 0xa6, 0x4c, 0x0d,
 	0x0b, 0x98, 0xe1, 0x30,
 	0xfd, 0xa4, 0x49, 0x09,
-	0x80, 0xa3, 0x71, 0x7c,
+	0x80, 0xa3, 0x85, 0x7c,
 	0x02, 0xa4, 0x48, 0x01,
 	0x01, 0xa4, 0x36, 0x30,
 	0xa8, 0xea, 0x32, 0x00,
 	0xfd, 0xa4, 0x49, 0x0b,
 	0x05, 0xa3, 0x07, 0x33,
-	0x80, 0x83, 0x7d, 0x6c,
+	0x80, 0x83, 0x91, 0x6c,
 	0x02, 0xea, 0x4c, 0x05,
 	0xff, 0xea, 0x4c, 0x0d,
-	0x00, 0xe2, 0x56, 0x59,
-	0x02, 0xa6, 0x10, 0x6c,
+	0x00, 0xe2, 0x60, 0x59,
+	0x02, 0xa6, 0x24, 0x6c,
 	0x80, 0xf9, 0xf2, 0x05,
-	0xc0, 0x39, 0x8b, 0x7c,
-	0x03, 0xea, 0x64, 0x59,
+	0xc0, 0x39, 0x9f, 0x7c,
+	0x03, 0xea, 0x6e, 0x59,
 	0x03, 0xea, 0x04, 0x00,
-	0x20, 0x39, 0xaf, 0x7c,
-	0x01, 0x84, 0x95, 0x6c,
-	0x06, 0xea, 0x64, 0x59,
+	0x20, 0x39, 0xc3, 0x7c,
+	0x01, 0x84, 0xa9, 0x6c,
+	0x06, 0xea, 0x6e, 0x59,
 	0x06, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xb2, 0x44,
+	0x00, 0xe2, 0xc6, 0x44,
 	0x01, 0x00, 0x6c, 0x32,
-	0xee, 0x00, 0x9e, 0x6c,
+	0xee, 0x00, 0xb2, 0x6c,
 	0x05, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x5e, 0x59,
+	0x33, 0xea, 0x68, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x80, 0x3d, 0x7a, 0x00,
-	0xfc, 0x42, 0xa0, 0x7c,
+	0xfc, 0x42, 0xb4, 0x7c,
 	0x7f, 0x3d, 0x7a, 0x08,
-	0x00, 0x36, 0x5f, 0x59,
+	0x00, 0x36, 0x69, 0x59,
 	0x01, 0x36, 0x01, 0x30,
-	0x09, 0xea, 0x64, 0x59,
+	0x09, 0xea, 0x6e, 0x59,
 	0x09, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x14, 0x42,
-	0x01, 0xa4, 0x95, 0x6c,
-	0x00, 0xe2, 0x68, 0x5c,
+	0x00, 0xe2, 0x28, 0x42,
+	0x01, 0xa4, 0xa9, 0x6c,
+	0x00, 0xe2, 0x7c, 0x5c,
 	0x20, 0x39, 0x73, 0x02,
 	0x01, 0x00, 0x6c, 0x32,
-	0x02, 0xa6, 0xba, 0x7c,
-	0x00, 0xe2, 0x7e, 0x5c,
+	0x02, 0xa6, 0xce, 0x7c,
+	0x00, 0xe2, 0x92, 0x5c,
 	0x00, 0xe2, 0x76, 0x58,
 	0x00, 0xe2, 0x86, 0x58,
 	0x00, 0xe2, 0x5a, 0x58,
-	0x00, 0x36, 0x5f, 0x59,
+	0x00, 0x36, 0x69, 0x59,
 	0x01, 0x36, 0x01, 0x30,
-	0x20, 0x19, 0xba, 0x6c,
-	0x00, 0xe2, 0xea, 0x5c,
-	0x04, 0x19, 0xd4, 0x6c,
+	0x20, 0x19, 0xce, 0x6c,
+	0x00, 0xe2, 0xfe, 0x5c,
+	0x04, 0x19, 0xe8, 0x6c,
 	0x02, 0x19, 0x32, 0x00,
-	0x01, 0x84, 0xd5, 0x7c,
-	0x01, 0x1b, 0xce, 0x7c,
-	0x01, 0x1a, 0xd4, 0x6c,
-	0x00, 0xe2, 0x84, 0x44,
-	0x80, 0x4b, 0xda, 0x6c,
-	0x01, 0x4c, 0xd6, 0x7c,
-	0x03, 0x42, 0x84, 0x6c,
-	0x00, 0xe2, 0x0a, 0x5c,
+	0x01, 0x84, 0xe9, 0x7c,
+	0x01, 0x1b, 0xe2, 0x7c,
+	0x01, 0x1a, 0xe8, 0x6c,
+	0x00, 0xe2, 0x98, 0x44,
+	0x80, 0x4b, 0xee, 0x6c,
+	0x01, 0x4c, 0xea, 0x7c,
+	0x03, 0x42, 0x98, 0x6c,
+	0x00, 0xe2, 0x1e, 0x5c,
 	0x80, 0xf9, 0xf2, 0x01,
-	0x04, 0x39, 0x15, 0x7a,
-	0x00, 0xe2, 0x14, 0x42,
-	0x08, 0x5d, 0xf2, 0x6c,
+	0x04, 0x39, 0x29, 0x7a,
+	0x00, 0xe2, 0x28, 0x42,
+	0x08, 0x5d, 0x06, 0x6d,
 	0x00, 0xe2, 0x76, 0x58,
-	0x00, 0x36, 0x5f, 0x59,
+	0x00, 0x36, 0x69, 0x59,
 	0x01, 0x36, 0x01, 0x30,
-	0x02, 0x1b, 0xe2, 0x7c,
-	0x08, 0x5d, 0xf0, 0x7c,
+	0x02, 0x1b, 0xf6, 0x7c,
+	0x08, 0x5d, 0x04, 0x7d,
 	0x03, 0x68, 0x00, 0x37,
 	0x01, 0x84, 0x09, 0x07,
-	0x80, 0x1b, 0xfc, 0x7c,
-	0x80, 0x84, 0xfd, 0x6c,
+	0x80, 0x1b, 0x10, 0x7d,
+	0x80, 0x84, 0x11, 0x6d,
 	0xff, 0x85, 0x0b, 0x1b,
 	0xff, 0x86, 0x0d, 0x23,
 	0xff, 0x87, 0x0f, 0x23,
@@ -652,161 +662,164 @@
 	0xf9, 0xd9, 0xb2, 0x0d,
 	0x01, 0xd9, 0xb2, 0x05,
 	0x01, 0x52, 0x48, 0x31,
-	0x20, 0xa4, 0x26, 0x7d,
-	0x20, 0x5b, 0x26, 0x7d,
-	0x80, 0xf9, 0x34, 0x7d,
+	0x20, 0xa4, 0x3a, 0x7d,
+	0x20, 0x5b, 0x3a, 0x7d,
+	0x80, 0xf9, 0x48, 0x7d,
 	0x02, 0xea, 0xb4, 0x00,
 	0x11, 0x00, 0x00, 0x10,
-	0x04, 0x19, 0x40, 0x7d,
+	0x04, 0x19, 0x54, 0x7d,
 	0xdf, 0x19, 0x32, 0x08,
-	0x60, 0x5b, 0x40, 0x6d,
-	0x01, 0x4c, 0x1a, 0x7d,
+	0x60, 0x5b, 0x54, 0x6d,
+	0x01, 0x4c, 0x2e, 0x7d,
 	0x20, 0x19, 0x32, 0x00,
 	0x01, 0xd9, 0xb2, 0x05,
 	0x02, 0xea, 0xb4, 0x00,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x10, 0x5b, 0x38, 0x6d,
-	0x08, 0x5b, 0x42, 0x6d,
-	0x20, 0x5b, 0x32, 0x6d,
-	0x02, 0x5b, 0x62, 0x6d,
-	0x0e, 0xea, 0x64, 0x59,
+	0x10, 0x5b, 0x4c, 0x6d,
+	0x08, 0x5b, 0x56, 0x6d,
+	0x20, 0x5b, 0x46, 0x6d,
+	0x02, 0x5b, 0x76, 0x6d,
+	0x0e, 0xea, 0x6e, 0x59,
 	0x0e, 0xea, 0x04, 0x00,
-	0x80, 0xf9, 0x22, 0x6d,
+	0x80, 0xf9, 0x36, 0x6d,
 	0xdf, 0x5c, 0xb8, 0x08,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x01, 0xa4, 0x1d, 0x6e,
-	0x00, 0xe2, 0x68, 0x5c,
-	0x00, 0xe2, 0x6c, 0x5d,
+	0x01, 0xa4, 0x37, 0x6e,
+	0x00, 0xe2, 0x7c, 0x5c,
+	0x00, 0xe2, 0x80, 0x5d,
 	0x01, 0x90, 0x21, 0x1b,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x00, 0xe2, 0x52, 0x5b,
+	0x00, 0xe2, 0x66, 0x5b,
 	0xf3, 0x96, 0xd5, 0x19,
-	0x00, 0xe2, 0x50, 0x55,
-	0x80, 0x96, 0x51, 0x6d,
-	0x0f, 0xea, 0x64, 0x59,
+	0x00, 0xe2, 0x64, 0x55,
+	0x80, 0x96, 0x65, 0x6d,
+	0x0f, 0xea, 0x6e, 0x59,
 	0x0f, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x58, 0x45,
+	0x00, 0xe2, 0x6c, 0x45,
 	0x04, 0x8c, 0xe1, 0x30,
 	0x01, 0xea, 0xf2, 0x00,
 	0x02, 0xea, 0x36, 0x00,
 	0xa8, 0xea, 0x32, 0x00,
-	0xff, 0x97, 0x5f, 0x7d,
-	0x14, 0xea, 0x64, 0x59,
+	0xff, 0x97, 0x73, 0x7d,
+	0x14, 0xea, 0x6e, 0x59,
 	0x14, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xce, 0x5d,
+	0x00, 0xe2, 0xe2, 0x5d,
 	0x01, 0xd9, 0xb2, 0x05,
 	0x09, 0x80, 0xe1, 0x30,
 	0x02, 0xea, 0x36, 0x00,
 	0xa8, 0xea, 0x32, 0x00,
-	0x00, 0xe2, 0xc6, 0x5d,
+	0x00, 0xe2, 0xda, 0x5d,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x02, 0xa6, 0x7c, 0x7d,
-	0x00, 0xe2, 0x56, 0x59,
-	0x20, 0x5b, 0x8a, 0x6d,
-	0xfc, 0x42, 0x76, 0x7d,
-	0x10, 0x40, 0x78, 0x6d,
-	0x20, 0x4d, 0x7a, 0x7d,
-	0x08, 0x5d, 0x8a, 0x6d,
-	0x02, 0xa6, 0x10, 0x6c,
-	0x00, 0xe2, 0x56, 0x59,
-	0x20, 0x5b, 0x8a, 0x6d,
-	0x01, 0x1b, 0xaa, 0x6d,
-	0xfc, 0x42, 0x86, 0x7d,
-	0x10, 0x40, 0x88, 0x6d,
+	0x02, 0xa6, 0x90, 0x7d,
+	0x00, 0xe2, 0x60, 0x59,
+	0x20, 0x5b, 0x9e, 0x6d,
+	0xfc, 0x42, 0x8a, 0x7d,
+	0x10, 0x40, 0x8c, 0x6d,
+	0x20, 0x4d, 0x8e, 0x7d,
+	0x08, 0x5d, 0x9e, 0x6d,
+	0x02, 0xa6, 0x24, 0x6c,
+	0x00, 0xe2, 0x60, 0x59,
+	0x20, 0x5b, 0x9e, 0x6d,
+	0x01, 0x1b, 0xbe, 0x6d,
+	0xfc, 0x42, 0x9a, 0x7d,
+	0x10, 0x40, 0x9c, 0x6d,
 	0x20, 0x4d, 0x84, 0x78,
 	0x08, 0x5d, 0x84, 0x78,
 	0x02, 0x19, 0x32, 0x00,
 	0x01, 0x5b, 0x40, 0x31,
-	0x00, 0xe2, 0xea, 0x5c,
-	0x00, 0xe2, 0xcc, 0x5b,
+	0x00, 0xe2, 0xfe, 0x5c,
+	0x00, 0xe2, 0xe0, 0x5b,
 	0x20, 0xea, 0xb6, 0x00,
-	0x00, 0xe2, 0x0a, 0x5c,
+	0x00, 0xe2, 0x1e, 0x5c,
 	0x20, 0x5c, 0xb8, 0x00,
-	0x04, 0x19, 0xa0, 0x6d,
-	0x01, 0x1a, 0xa0, 0x6d,
-	0x00, 0xe2, 0x56, 0x59,
+	0x04, 0x19, 0xb4, 0x6d,
+	0x01, 0x1a, 0xb4, 0x6d,
+	0x00, 0xe2, 0x60, 0x59,
 	0x01, 0x1a, 0x84, 0x78,
 	0x80, 0xf9, 0xf2, 0x01,
-	0x20, 0xa0, 0x04, 0x7e,
+	0x20, 0xa0, 0x18, 0x7e,
 	0xff, 0x90, 0x21, 0x1b,
-	0x08, 0x92, 0x63, 0x6b,
+	0x08, 0x92, 0x77, 0x6b,
 	0x02, 0xea, 0xb4, 0x04,
 	0x01, 0xa4, 0x49, 0x03,
-	0x40, 0x5b, 0xba, 0x6d,
-	0x00, 0xe2, 0x56, 0x59,
-	0x40, 0x5b, 0xba, 0x6d,
-	0x04, 0x5d, 0x1e, 0x7e,
-	0x01, 0x1a, 0x1e, 0x7e,
+	0x40, 0x5b, 0xce, 0x6d,
+	0x00, 0xe2, 0x60, 0x59,
+	0x40, 0x5b, 0xce, 0x6d,
+	0x04, 0x5d, 0x38, 0x7e,
+	0x01, 0x1a, 0x38, 0x7e,
 	0x20, 0x4d, 0x84, 0x78,
-	0x40, 0x5b, 0x04, 0x7e,
-	0x04, 0x5d, 0x1e, 0x7e,
-	0x01, 0x1a, 0x1e, 0x7e,
+	0x40, 0x5b, 0x18, 0x7e,
+	0x04, 0x5d, 0x38, 0x7e,
+	0x01, 0x1a, 0x38, 0x7e,
 	0x80, 0xf9, 0xf2, 0x01,
 	0xff, 0x90, 0x21, 0x1b,
-	0x08, 0x92, 0x63, 0x6b,
+	0x08, 0x92, 0x77, 0x6b,
 	0x02, 0xea, 0xb4, 0x04,
-	0x00, 0xe2, 0x56, 0x59,
+	0x00, 0xe2, 0x60, 0x59,
 	0x01, 0x1b, 0x84, 0x78,
 	0x80, 0xf9, 0xf2, 0x01,
 	0x02, 0xea, 0xb4, 0x04,
-	0x00, 0xe2, 0x56, 0x59,
-	0x01, 0x1b, 0xe2, 0x6d,
-	0x40, 0x5b, 0xf0, 0x7d,
-	0x01, 0x1b, 0xe2, 0x6d,
+	0x00, 0xe2, 0x60, 0x59,
+	0x01, 0x1b, 0xf6, 0x6d,
+	0x40, 0x5b, 0x04, 0x7e,
+	0x01, 0x1b, 0xf6, 0x6d,
 	0x02, 0x19, 0x32, 0x00,
 	0x01, 0x1a, 0x84, 0x78,
 	0x80, 0xf9, 0xf2, 0x01,
 	0xff, 0xea, 0x10, 0x03,
 	0x08, 0x92, 0x25, 0x03,
-	0x00, 0xe2, 0x62, 0x43,
-	0x01, 0x1a, 0xec, 0x7d,
-	0x40, 0x5b, 0xe8, 0x7d,
-	0x01, 0x1a, 0xd6, 0x6d,
+	0x00, 0xe2, 0x76, 0x43,
+	0x01, 0x1a, 0x00, 0x7e,
+	0x40, 0x5b, 0xfc, 0x7d,
+	0x01, 0x1a, 0xea, 0x6d,
 	0xfc, 0x42, 0x84, 0x78,
-	0x01, 0x1a, 0xf0, 0x6d,
-	0x10, 0xea, 0x64, 0x59,
+	0x01, 0x1a, 0x04, 0x6e,
+	0x10, 0xea, 0x6e, 0x59,
 	0x10, 0xea, 0x04, 0x00,
 	0xfc, 0x42, 0x84, 0x78,
-	0x10, 0x40, 0xf6, 0x6d,
+	0x10, 0x40, 0x0a, 0x6e,
 	0x20, 0x4d, 0x84, 0x78,
-	0x40, 0x5b, 0xd6, 0x6d,
+	0x40, 0x5b, 0xea, 0x6d,
 	0x01, 0x1a, 0x84, 0x78,
 	0x01, 0x90, 0x21, 0x1b,
 	0x30, 0x3f, 0xc0, 0x09,
 	0x30, 0xe0, 0x84, 0x60,
 	0x40, 0x4b, 0x84, 0x68,
 	0xff, 0xea, 0x52, 0x01,
-	0xee, 0x00, 0x0c, 0x6e,
+	0xee, 0x00, 0x20, 0x6e,
 	0x80, 0xf9, 0xf2, 0x01,
 	0xff, 0x90, 0x21, 0x1b,
 	0x02, 0xea, 0xb4, 0x00,
 	0x20, 0xea, 0x9a, 0x00,
-	0xf3, 0x42, 0x16, 0x6e,
-	0x12, 0xea, 0x64, 0x59,
+	0x04, 0x41, 0x26, 0x7e,
+	0x08, 0xea, 0x98, 0x00,
+	0x08, 0x57, 0xae, 0x00,
+	0xf3, 0x42, 0x30, 0x6e,
+	0x12, 0xea, 0x6e, 0x59,
 	0x12, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x14, 0x42,
-	0x0d, 0xea, 0x64, 0x59,
+	0x00, 0xe2, 0x28, 0x42,
+	0x0d, 0xea, 0x6e, 0x59,
 	0x0d, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x14, 0x42,
+	0x00, 0xe2, 0x28, 0x42,
 	0x01, 0x90, 0x21, 0x1b,
-	0x11, 0xea, 0x64, 0x59,
+	0x11, 0xea, 0x6e, 0x59,
 	0x11, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x52, 0x5b,
+	0x00, 0xe2, 0x66, 0x5b,
 	0x08, 0x5a, 0xb4, 0x00,
-	0x00, 0xe2, 0x44, 0x5e,
+	0x00, 0xe2, 0x5e, 0x5e,
 	0xa8, 0xea, 0x32, 0x00,
-	0x00, 0xe2, 0x56, 0x59,
-	0x80, 0x1a, 0x32, 0x7e,
-	0x00, 0xe2, 0x44, 0x5e,
+	0x00, 0xe2, 0x60, 0x59,
+	0x80, 0x1a, 0x4c, 0x7e,
+	0x00, 0xe2, 0x5e, 0x5e,
 	0x80, 0x19, 0x32, 0x00,
-	0x40, 0x5b, 0x38, 0x6e,
-	0x08, 0x5a, 0x38, 0x7e,
+	0x40, 0x5b, 0x52, 0x6e,
+	0x08, 0x5a, 0x52, 0x7e,
 	0x20, 0x4d, 0x84, 0x78,
 	0x02, 0x84, 0x09, 0x03,
-	0x40, 0x5b, 0x04, 0x7e,
+	0x40, 0x5b, 0x18, 0x7e,
 	0xff, 0x90, 0x21, 0x1b,
 	0x80, 0xf9, 0xf2, 0x01,
-	0x08, 0x92, 0x63, 0x6b,
+	0x08, 0x92, 0x77, 0x6b,
 	0x02, 0xea, 0xb4, 0x04,
 	0x01, 0x40, 0xe1, 0x30,
 	0x05, 0x41, 0xe3, 0x98,
@@ -1039,138 +1052,138 @@
 	{ ahd_patch0_func, 64, 1, 1 },
 	{ ahd_patch2_func, 67, 1, 2 },
 	{ ahd_patch0_func, 68, 1, 1 },
-	{ ahd_patch4_func, 116, 1, 1 },
-	{ ahd_patch2_func, 175, 3, 1 },
-	{ ahd_patch1_func, 178, 2, 1 },
-	{ ahd_patch5_func, 180, 1, 1 },
-	{ ahd_patch2_func, 189, 1, 2 },
-	{ ahd_patch0_func, 190, 1, 1 },
-	{ ahd_patch6_func, 191, 2, 2 },
-	{ ahd_patch0_func, 193, 6, 3 },
-	{ ahd_patch2_func, 196, 1, 2 },
-	{ ahd_patch0_func, 197, 1, 1 },
-	{ ahd_patch2_func, 200, 1, 2 },
-	{ ahd_patch0_func, 201, 1, 1 },
-	{ ahd_patch3_func, 203, 1, 1 },
-	{ ahd_patch7_func, 204, 3, 1 },
-	{ ahd_patch3_func, 213, 1, 1 },
-	{ ahd_patch5_func, 214, 16, 2 },
-	{ ahd_patch0_func, 230, 1, 1 },
-	{ ahd_patch8_func, 250, 2, 1 },
-	{ ahd_patch1_func, 254, 1, 2 },
-	{ ahd_patch0_func, 255, 1, 1 },
-	{ ahd_patch7_func, 258, 3, 1 },
-	{ ahd_patch1_func, 273, 1, 2 },
-	{ ahd_patch0_func, 274, 1, 1 },
-	{ ahd_patch1_func, 277, 1, 2 },
-	{ ahd_patch0_func, 278, 1, 1 },
-	{ ahd_patch2_func, 281, 1, 2 },
-	{ ahd_patch0_func, 282, 1, 1 },
-	{ ahd_patch9_func, 295, 2, 2 },
-	{ ahd_patch0_func, 297, 1, 1 },
-	{ ahd_patch1_func, 339, 1, 2 },
-	{ ahd_patch0_func, 340, 1, 1 },
-	{ ahd_patch2_func, 348, 1, 2 },
-	{ ahd_patch0_func, 349, 1, 1 },
-	{ ahd_patch2_func, 352, 1, 2 },
-	{ ahd_patch0_func, 353, 1, 1 },
-	{ ahd_patch1_func, 359, 1, 2 },
-	{ ahd_patch0_func, 360, 1, 1 },
-	{ ahd_patch1_func, 362, 1, 2 },
+	{ ahd_patch4_func, 115, 1, 1 },
+	{ ahd_patch2_func, 180, 3, 1 },
+	{ ahd_patch1_func, 183, 2, 1 },
+	{ ahd_patch5_func, 185, 1, 1 },
+	{ ahd_patch2_func, 194, 1, 2 },
+	{ ahd_patch0_func, 195, 1, 1 },
+	{ ahd_patch6_func, 196, 2, 2 },
+	{ ahd_patch0_func, 198, 6, 3 },
+	{ ahd_patch2_func, 201, 1, 2 },
+	{ ahd_patch0_func, 202, 1, 1 },
+	{ ahd_patch2_func, 205, 1, 2 },
+	{ ahd_patch0_func, 206, 1, 1 },
+	{ ahd_patch3_func, 208, 1, 1 },
+	{ ahd_patch7_func, 209, 3, 1 },
+	{ ahd_patch3_func, 218, 1, 1 },
+	{ ahd_patch5_func, 219, 16, 2 },
+	{ ahd_patch0_func, 235, 1, 1 },
+	{ ahd_patch8_func, 260, 2, 1 },
+	{ ahd_patch1_func, 264, 1, 2 },
+	{ ahd_patch0_func, 265, 1, 1 },
+	{ ahd_patch7_func, 268, 3, 1 },
+	{ ahd_patch1_func, 283, 1, 2 },
+	{ ahd_patch0_func, 284, 1, 1 },
+	{ ahd_patch1_func, 287, 1, 2 },
+	{ ahd_patch0_func, 288, 1, 1 },
+	{ ahd_patch2_func, 291, 1, 2 },
+	{ ahd_patch0_func, 292, 1, 1 },
+	{ ahd_patch9_func, 305, 2, 2 },
+	{ ahd_patch0_func, 307, 1, 1 },
+	{ ahd_patch1_func, 349, 1, 2 },
+	{ ahd_patch0_func, 350, 1, 1 },
+	{ ahd_patch2_func, 358, 1, 2 },
+	{ ahd_patch0_func, 359, 1, 1 },
+	{ ahd_patch2_func, 362, 1, 2 },
 	{ ahd_patch0_func, 363, 1, 1 },
-	{ ahd_patch10_func, 382, 1, 1 },
-	{ ahd_patch10_func, 385, 1, 1 },
-	{ ahd_patch10_func, 387, 1, 1 },
-	{ ahd_patch10_func, 399, 1, 1 },
-	{ ahd_patch1_func, 409, 1, 2 },
-	{ ahd_patch0_func, 410, 1, 1 },
-	{ ahd_patch1_func, 412, 1, 2 },
-	{ ahd_patch0_func, 413, 1, 1 },
-	{ ahd_patch1_func, 421, 1, 2 },
-	{ ahd_patch0_func, 422, 1, 1 },
-	{ ahd_patch2_func, 435, 1, 2 },
-	{ ahd_patch0_func, 436, 1, 1 },
-	{ ahd_patch11_func, 472, 1, 1 },
-	{ ahd_patch1_func, 480, 1, 2 },
-	{ ahd_patch0_func, 481, 1, 1 },
-	{ ahd_patch2_func, 493, 1, 2 },
-	{ ahd_patch0_func, 494, 1, 1 },
-	{ ahd_patch12_func, 497, 6, 2 },
-	{ ahd_patch0_func, 503, 1, 1 },
-	{ ahd_patch13_func, 524, 7, 1 },
-	{ ahd_patch14_func, 533, 1, 1 },
-	{ ahd_patch15_func, 542, 1, 1 },
-	{ ahd_patch16_func, 543, 1, 2 },
-	{ ahd_patch0_func, 544, 1, 1 },
-	{ ahd_patch17_func, 547, 1, 1 },
-	{ ahd_patch16_func, 548, 1, 1 },
-	{ ahd_patch18_func, 559, 1, 2 },
-	{ ahd_patch0_func, 560, 1, 1 },
-	{ ahd_patch1_func, 579, 1, 2 },
-	{ ahd_patch0_func, 580, 1, 1 },
-	{ ahd_patch1_func, 583, 1, 2 },
-	{ ahd_patch0_func, 584, 1, 1 },
-	{ ahd_patch2_func, 589, 1, 2 },
+	{ ahd_patch1_func, 369, 1, 2 },
+	{ ahd_patch0_func, 370, 1, 1 },
+	{ ahd_patch1_func, 372, 1, 2 },
+	{ ahd_patch0_func, 373, 1, 1 },
+	{ ahd_patch10_func, 392, 1, 1 },
+	{ ahd_patch10_func, 395, 1, 1 },
+	{ ahd_patch10_func, 397, 1, 1 },
+	{ ahd_patch10_func, 409, 1, 1 },
+	{ ahd_patch1_func, 419, 1, 2 },
+	{ ahd_patch0_func, 420, 1, 1 },
+	{ ahd_patch1_func, 422, 1, 2 },
+	{ ahd_patch0_func, 423, 1, 1 },
+	{ ahd_patch1_func, 431, 1, 2 },
+	{ ahd_patch0_func, 432, 1, 1 },
+	{ ahd_patch2_func, 445, 1, 2 },
+	{ ahd_patch0_func, 446, 1, 1 },
+	{ ahd_patch11_func, 482, 1, 1 },
+	{ ahd_patch1_func, 490, 1, 2 },
+	{ ahd_patch0_func, 491, 1, 1 },
+	{ ahd_patch2_func, 503, 1, 2 },
+	{ ahd_patch0_func, 504, 1, 1 },
+	{ ahd_patch12_func, 507, 6, 2 },
+	{ ahd_patch0_func, 513, 1, 1 },
+	{ ahd_patch13_func, 534, 7, 1 },
+	{ ahd_patch14_func, 543, 1, 1 },
+	{ ahd_patch15_func, 552, 1, 1 },
+	{ ahd_patch16_func, 553, 1, 2 },
+	{ ahd_patch0_func, 554, 1, 1 },
+	{ ahd_patch17_func, 557, 1, 1 },
+	{ ahd_patch16_func, 558, 1, 1 },
+	{ ahd_patch18_func, 569, 1, 2 },
+	{ ahd_patch0_func, 570, 1, 1 },
+	{ ahd_patch1_func, 589, 1, 2 },
 	{ ahd_patch0_func, 590, 1, 1 },
-	{ ahd_patch2_func, 594, 1, 2 },
-	{ ahd_patch0_func, 595, 1, 1 },
-	{ ahd_patch1_func, 596, 1, 2 },
-	{ ahd_patch0_func, 597, 1, 1 },
-	{ ahd_patch2_func, 608, 1, 2 },
-	{ ahd_patch0_func, 609, 1, 1 },
-	{ ahd_patch19_func, 613, 1, 1 },
-	{ ahd_patch20_func, 618, 1, 1 },
-	{ ahd_patch21_func, 619, 2, 1 },
-	{ ahd_patch20_func, 623, 1, 2 },
-	{ ahd_patch0_func, 624, 1, 1 },
-	{ ahd_patch2_func, 627, 1, 2 },
-	{ ahd_patch0_func, 628, 1, 1 },
-	{ ahd_patch2_func, 643, 1, 2 },
-	{ ahd_patch0_func, 644, 1, 1 },
-	{ ahd_patch13_func, 645, 14, 1 },
-	{ ahd_patch1_func, 663, 1, 2 },
-	{ ahd_patch0_func, 664, 1, 1 },
-	{ ahd_patch13_func, 665, 1, 1 },
-	{ ahd_patch1_func, 677, 1, 2 },
-	{ ahd_patch0_func, 678, 1, 1 },
-	{ ahd_patch1_func, 685, 1, 2 },
-	{ ahd_patch0_func, 686, 1, 1 },
-	{ ahd_patch19_func, 709, 1, 1 },
-	{ ahd_patch19_func, 747, 1, 1 },
-	{ ahd_patch1_func, 758, 1, 2 },
-	{ ahd_patch0_func, 759, 1, 1 },
-	{ ahd_patch1_func, 776, 1, 2 },
-	{ ahd_patch0_func, 777, 1, 1 },
-	{ ahd_patch1_func, 779, 1, 2 },
-	{ ahd_patch0_func, 780, 1, 1 },
-	{ ahd_patch1_func, 783, 1, 2 },
-	{ ahd_patch0_func, 784, 1, 1 },
-	{ ahd_patch22_func, 786, 1, 2 },
-	{ ahd_patch0_func, 787, 2, 1 },
-	{ ahd_patch23_func, 790, 4, 2 },
-	{ ahd_patch0_func, 794, 1, 1 },
-	{ ahd_patch23_func, 802, 11, 1 }
+	{ ahd_patch1_func, 593, 1, 2 },
+	{ ahd_patch0_func, 594, 1, 1 },
+	{ ahd_patch2_func, 599, 1, 2 },
+	{ ahd_patch0_func, 600, 1, 1 },
+	{ ahd_patch2_func, 604, 1, 2 },
+	{ ahd_patch0_func, 605, 1, 1 },
+	{ ahd_patch1_func, 606, 1, 2 },
+	{ ahd_patch0_func, 607, 1, 1 },
+	{ ahd_patch2_func, 618, 1, 2 },
+	{ ahd_patch0_func, 619, 1, 1 },
+	{ ahd_patch19_func, 623, 1, 1 },
+	{ ahd_patch20_func, 628, 1, 1 },
+	{ ahd_patch21_func, 629, 2, 1 },
+	{ ahd_patch20_func, 633, 1, 2 },
+	{ ahd_patch0_func, 634, 1, 1 },
+	{ ahd_patch2_func, 637, 1, 2 },
+	{ ahd_patch0_func, 638, 1, 1 },
+	{ ahd_patch2_func, 653, 1, 2 },
+	{ ahd_patch0_func, 654, 1, 1 },
+	{ ahd_patch13_func, 655, 14, 1 },
+	{ ahd_patch1_func, 673, 1, 2 },
+	{ ahd_patch0_func, 674, 1, 1 },
+	{ ahd_patch13_func, 675, 1, 1 },
+	{ ahd_patch1_func, 687, 1, 2 },
+	{ ahd_patch0_func, 688, 1, 1 },
+	{ ahd_patch1_func, 695, 1, 2 },
+	{ ahd_patch0_func, 696, 1, 1 },
+	{ ahd_patch19_func, 719, 1, 1 },
+	{ ahd_patch19_func, 757, 1, 1 },
+	{ ahd_patch1_func, 768, 1, 2 },
+	{ ahd_patch0_func, 769, 1, 1 },
+	{ ahd_patch7_func, 785, 3, 1 },
+	{ ahd_patch1_func, 789, 1, 2 },
+	{ ahd_patch0_func, 790, 1, 1 },
+	{ ahd_patch1_func, 792, 1, 2 },
+	{ ahd_patch0_func, 793, 1, 1 },
+	{ ahd_patch1_func, 796, 1, 2 },
+	{ ahd_patch0_func, 797, 1, 1 },
+	{ ahd_patch22_func, 799, 1, 2 },
+	{ ahd_patch0_func, 800, 2, 1 },
+	{ ahd_patch23_func, 803, 4, 2 },
+	{ ahd_patch0_func, 807, 1, 1 },
+	{ ahd_patch23_func, 815, 11, 1 }
 };
 
 static struct cs {
 	uint16_t	begin;
 	uint16_t	end;
 } critical_sections[] = {
-	{ 17, 28 },
-	{ 29, 30 },
+	{ 17, 30 },
 	{ 47, 58 },
 	{ 61, 63 },
 	{ 65, 66 },
 	{ 72, 92 },
-	{ 110, 137 },
-	{ 138, 175 },
-	{ 180, 188 },
-	{ 213, 264 },
-	{ 425, 433 },
-	{ 443, 445 },
-	{ 448, 457 },
-	{ 709, 739 },
-	{ 749, 753 }
+	{ 110, 142 },
+	{ 143, 180 },
+	{ 185, 193 },
+	{ 218, 274 },
+	{ 435, 443 },
+	{ 453, 455 },
+	{ 458, 467 },
+	{ 719, 749 },
+	{ 759, 763 }
 };
 
 static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c
index f936b69..9241027 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm.c
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#22 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $
  *
  * $FreeBSD$
  */
@@ -609,10 +609,10 @@
 
 		while (line < cur_instr->srcline) {
 			fgets(buf, sizeof(buf), ifile);
-				fprintf(listfile, "\t\t%s", buf);
+				fprintf(listfile, "             \t%s", buf);
 				line++;
 		}
-		fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr,
+		fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr,
 #ifdef __LITTLE_ENDIAN
 			cur_instr->format.bytes[0],
 			cur_instr->format.bytes[1],
@@ -624,14 +624,23 @@
 			cur_instr->format.bytes[1],
 			cur_instr->format.bytes[0]);
 #endif
-		fgets(buf, sizeof(buf), ifile);
-		fprintf(listfile, "\t%s", buf);
-		line++;
+		/*
+		 * Macro expansions can cause several instructions
+		 * to be output for a single source line.  Only
+		 * advance the line once in these cases.
+		 */
+		if (line == cur_instr->srcline) {
+			fgets(buf, sizeof(buf), ifile);
+			fprintf(listfile, "\t%s", buf);
+			line++;
+		} else {
+			fprintf(listfile, "\n");
+		}
 		instrptr++;
 	}
 	/* Dump the remainder of the file */
 	while(fgets(buf, sizeof(buf), ifile) != NULL)
-		fprintf(listfile, "\t\t%s", buf);
+		fprintf(listfile, "             %s", buf);
 
 	fclose(ifile);
 }
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
index 67e046d..c328596 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
@@ -38,7 +38,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#29 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#30 $
  *
  * $FreeBSD$
  */
@@ -157,6 +157,8 @@
 
 %token T_END_CS
 
+%token T_PAD_PAGE
+
 %token T_FIELD
 
 %token T_ENUM
@@ -189,6 +191,10 @@
 
 %token <value> T_OR
 
+/* 16 bit extensions */
+%token <value> T_OR16 T_AND16 T_XOR16 T_ADD16
+%token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG
+
 %token T_RET
 
 %token T_NOP
@@ -207,7 +213,7 @@
 
 %type <expression> expression immediate immediate_or_a
 
-%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
+%type <value> export ret f1_opcode f2_opcode f4_opcode jmp_jc_jnc_call jz_jnz je_jne
 
 %type <value> mode_value mode_list macro_arglist
 
@@ -1304,6 +1310,15 @@
 |	T_ROR { $$ = AIC_OP_ROR; }
 ;
 
+f4_opcode:
+	T_OR16	{ $$ = AIC_OP_OR16; }
+|	T_AND16 { $$ = AIC_OP_AND16; }
+|	T_XOR16 { $$ = AIC_OP_XOR16; }
+|	T_ADD16 { $$ = AIC_OP_ADD16; }
+|	T_ADC16 { $$ = AIC_OP_ADC16; }
+|	T_MVI16 { $$ = AIC_OP_MVI16; }
+;
+
 code:
 	f2_opcode destination ',' expression opt_source ret ';'
 	{
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
index e64f802..9df9e2c 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
@@ -37,13 +37,14 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#11 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#12 $
  *
  * $FreeBSD$
  */
 
 #include <asm/byteorder.h>
 
+/* 8bit ALU logic operations */
 struct ins_format1 {
 #ifdef __LITTLE_ENDIAN
 	uint32_t	immediate	: 8,
@@ -62,6 +63,7 @@
 #endif
 };
 
+/* 8bit ALU shift/rotate operations */
 struct ins_format2 {
 #ifdef __LITTLE_ENDIAN
 	uint32_t	shift_control	: 8,
@@ -80,6 +82,7 @@
 #endif
 };
 
+/* 8bit branch control operations */
 struct ins_format3 {
 #ifdef __LITTLE_ENDIAN
 	uint32_t	immediate	: 8,
@@ -96,10 +99,68 @@
 #endif
 };
 
+/* 16bit ALU logic operations */
+struct ins_format4 {
+#ifdef __LITTLE_ENDIAN
+	uint32_t	opcode_ext	: 8,
+			source		: 9,
+			destination	: 9,
+			ret		: 1,
+			opcode		: 4,
+			parity		: 1;
+#else
+	uint32_t	parity		: 1,
+			opcode		: 4,
+			ret		: 1,
+			destination	: 9,
+			source		: 9,
+			opcode_ext	: 8;
+#endif
+};
+
+/* 16bit branch control operations */
+struct ins_format5 {
+#ifdef __LITTLE_ENDIAN
+	uint32_t	opcode_ext	: 8,
+			source		: 9,
+			address		: 10,
+			opcode		: 4,
+			parity		: 1;
+#else
+	uint32_t	parity		: 1,
+			opcode		: 4,
+			address		: 10,
+			source		: 9,
+			opcode_ext	: 8;
+#endif
+};
+
+/*  Far branch operations */
+struct ins_format6 {
+#ifdef __LITTLE_ENDIAN
+	uint32_t	page		: 3,
+			opcode_ext	: 5,
+			source		: 9,
+			address		: 10,
+			opcode		: 4,
+			parity		: 1;
+#else
+	uint32_t	parity		: 1,
+			opcode		: 4,
+			address		: 10,
+			source		: 9,
+			opcode_ext	: 5,
+			page		: 3;
+#endif
+};
+
 union ins_formats {
 		struct ins_format1 format1;
 		struct ins_format2 format2;
 		struct ins_format3 format3;
+		struct ins_format4 format4;
+		struct ins_format5 format5;
+		struct ins_format6 format6;
 		uint8_t		   bytes[4];
 		uint32_t	   integer;
 };
@@ -118,6 +179,8 @@
 #define	AIC_OP_ROL	0x5
 #define	AIC_OP_BMOV	0x6
 
+#define	AIC_OP_MVI16	0x7
+
 #define	AIC_OP_JMP	0x8
 #define AIC_OP_JC	0x9
 #define AIC_OP_JNC	0xa
@@ -131,3 +194,26 @@
 #define	AIC_OP_SHL	0x10
 #define	AIC_OP_SHR	0x20
 #define	AIC_OP_ROR	0x30
+
+/* 16bit Ops. Low byte main opcode.  High byte extended opcode. */ 
+#define	AIC_OP_OR16	0x8005
+#define	AIC_OP_AND16	0x8105
+#define	AIC_OP_XOR16	0x8205
+#define	AIC_OP_ADD16	0x8305
+#define	AIC_OP_ADC16	0x8405
+#define AIC_OP_JNE16	0x8805
+#define AIC_OP_JNZ16	0x8905
+#define AIC_OP_JE16	0x8C05
+#define AIC_OP_JZ16	0x8B05
+#define AIC_OP_JMP16	0x9005
+#define AIC_OP_JC16	0x9105
+#define AIC_OP_JNC16	0x9205
+#define AIC_OP_CALL16	0x9305
+#define AIC_OP_CALL16	0x9305
+
+/* Page extension is low three bits of second opcode byte. */
+#define AIC_OP_JMPF	0xA005
+#define AIC_OP_CALLF	0xB005
+#define AIC_OP_JCF	0xC005
+#define AIC_OP_JNCF	0xD005
+#define AIC_OP_CMPXCHG	0xE005
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
index 45c0b23..7c3983f 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
@@ -38,7 +38,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $
  *
  * $FreeBSD$
  */
@@ -132,7 +132,7 @@
 						*string_buf_ptr++ = *yptr++;
 				}
 			}
-
+else			{ return T_ELSE; }
 VERSION			{ return T_VERSION; }
 PREFIX			{ return T_PREFIX; }
 PATCH_ARG_LIST		{ return T_PATCH_ARG_LIST; }
@@ -173,10 +173,6 @@
 					yylval.value = WO;
 				 return T_MODE;
 			}
-BEGIN_CRITICAL		{ return T_BEGIN_CS; }
-END_CRITICAL		{ return T_END_CS; }
-SET_SRC_MODE		{ return T_SET_SRC_MODE; }
-SET_DST_MODE		{ return T_SET_DST_MODE; }
 field			{ return T_FIELD; }
 enum			{ return T_ENUM; }
 mask			{ return T_MASK; }
@@ -192,6 +188,13 @@
 sindex			{ return T_SINDEX; }
 A			{ return T_A; }
 
+	/* Instruction Formatting */
+PAD_PAGE		{ return T_PAD_PAGE; }
+BEGIN_CRITICAL		{ return T_BEGIN_CS; }
+END_CRITICAL		{ return T_END_CS; }
+SET_SRC_MODE		{ return T_SET_SRC_MODE; }
+SET_DST_MODE		{ return T_SET_DST_MODE; }
+
 	/* Opcodes */
 shl			{ return T_SHL; }
 shr			{ return T_SHR; }
@@ -223,7 +226,17 @@
 or			{ return T_OR;	}
 ret			{ return T_RET; }
 nop			{ return T_NOP; }
-else			{ return T_ELSE; }
+
+	/* ARP2 16bit extensions */
+or16			{ return T_OR16; }
+and16			{ return T_AND16; }
+xor16			{ return T_XOR16; }
+add16			{ return T_ADD16; }
+adc16			{ return T_ADC16; }
+mvi16			{ return T_MVI16; }
+test16			{ return T_TEST16; }
+cmp16			{ return T_CMP16; }
+cmpxchg			{ return T_CMPXCHG; }
 
 	/* Allowed Symbols */
 \<\<			{ return T_EXPR_LSHIFT; }
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index c8a32cf..cbf8252 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -246,6 +246,7 @@
 	 * total_xfer_length in xferred. These values are restored in
 	 * pci_unmap_srb_sense. This is the only place xferred is used.
 	 */
+	unsigned char *virt_addr_req;	/* Saved virtual address of the request buffer */
 	u32 xferred;		        /* Saved copy of total_xfer_length */
 
 	u16 state;
@@ -2017,7 +2018,7 @@
 	sg_verify_length(srb);
 
 	/* we need the corresponding virtual address */
-	if (!segment) {
+	if (!segment || (srb->flag & AUTO_REQSENSE)) {
 		srb->virt_addr += xferred;
 		return;
 	}
@@ -3318,6 +3319,7 @@
 	    srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address;
 	srb->segment_x[0].length =
 	    srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].length;
+	srb->virt_addr = srb->virt_addr_req;
 }
 
 
@@ -3711,6 +3713,8 @@
 	srb->xferred = srb->total_xfer_length;
 	/* srb->segment_x : a one entry of S/G list table */
 	srb->total_xfer_length = sizeof(cmd->sense_buffer);
+	srb->virt_addr_req = srb->virt_addr;
+	srb->virt_addr = cmd->sense_buffer;
 	srb->segment_x[0].length = sizeof(cmd->sense_buffer);
 	/* Map sense buffer */
 	srb->segment_x[0].address =
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 822b9fa..eaefedd 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -87,7 +87,7 @@
 static int init_timeout = 5;
 static int max_requests = 50;
 
-#define IBMVSCSI_VERSION "1.5.7"
+#define IBMVSCSI_VERSION "1.5.8"
 
 MODULE_DESCRIPTION("IBM Virtual SCSI");
 MODULE_AUTHOR("Dave Boutcher");
@@ -534,7 +534,6 @@
 static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
 				   struct ibmvscsi_host_data *hostdata)
 {
-	struct scsi_cmnd *cmnd;
 	u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
 	int rc;
 
@@ -544,19 +543,8 @@
 	 * can handle more requests (can_queue) when we actually can't
 	 */
 	if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
-	    (atomic_dec_if_positive(&hostdata->request_limit) < 0)) {
-		/* See if the adapter is disabled */
-		if (atomic_read(&hostdata->request_limit) < 0)
-			goto send_error;
-	
-		printk(KERN_WARNING 
-		       "ibmvscsi: Warning, request_limit exceeded\n");
-		unmap_cmd_data(&evt_struct->iu.srp.cmd,
-			       evt_struct,
-			       hostdata->dev);
-		free_event_struct(&hostdata->pool, evt_struct);
-		return SCSI_MLQUEUE_HOST_BUSY;
-	}
+	    (atomic_dec_if_positive(&hostdata->request_limit) < 0))
+		goto send_error;
 
 	/* Copy the IU into the transfer area */
 	*evt_struct->xfer_iu = evt_struct->iu;
@@ -572,7 +560,7 @@
 	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
 		list_del(&evt_struct->list);
 
-		printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",
+		printk(KERN_ERR "ibmvscsi: send error %d\n",
 		       rc);
 		goto send_error;
 	}
@@ -582,14 +570,8 @@
  send_error:
 	unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
 
-	if ((cmnd = evt_struct->cmnd) != NULL) {
-		cmnd->result = DID_ERROR << 16;
-		evt_struct->cmnd_done(cmnd);
-	} else if (evt_struct->done)
-		evt_struct->done(evt_struct);
-	
 	free_event_struct(&hostdata->pool, evt_struct);
-	return 0;
+ 	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
 /**
@@ -802,7 +784,8 @@
 	case SRP_LOGIN_RSP_TYPE:	/* it worked! */
 		break;
 	case SRP_LOGIN_REJ_TYPE:	/* refused! */
-		printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REQ rejected\n");
+		printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n",
+		       evt_struct->xfer_iu->srp.login_rej.reason);
 		/* Login failed.  */
 		atomic_set(&hostdata->request_limit, -1);
 		return;
@@ -834,6 +817,9 @@
 		return;
 	}
 
+	/* If we had any pending I/Os, kick them */
+	scsi_unblock_requests(hostdata->host);
+
 	send_mad_adapter_info(hostdata);
 	return;
 }
@@ -862,6 +848,7 @@
 			  init_timeout * HZ);
 
 	login = &evt_struct->iu.srp.login_req;
+	memset(login, 0x00, sizeof(struct srp_login_req));
 	login->type = SRP_LOGIN_REQ_TYPE;
 	login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
 	login->required_buffer_formats = 0x0006;
@@ -1122,7 +1109,7 @@
  * purge_requests: Our virtual adapter just shut down.  purge any sent requests
  * @hostdata:    the adapter
  */
-static void purge_requests(struct ibmvscsi_host_data *hostdata)
+static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
 {
 	struct srp_event_struct *tmp_evt, *pos;
 	unsigned long flags;
@@ -1131,7 +1118,7 @@
 	list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
 		list_del(&tmp_evt->list);
 		if (tmp_evt->cmnd) {
-			tmp_evt->cmnd->result = (DID_ERROR << 16);
+			tmp_evt->cmnd->result = (error_code << 16);
 			unmap_cmd_data(&tmp_evt->iu.srp.cmd, 
 				       tmp_evt,	
 				       tmp_evt->hostdata->dev);
@@ -1186,12 +1173,30 @@
 			printk(KERN_ERR "ibmvscsi: unknown crq message type\n");
 		}
 		return;
-	case 0xFF:		/* Hypervisor telling us the connection is closed */
-		printk(KERN_INFO "ibmvscsi: Virtual adapter failed!\n");
+	case 0xFF:	/* Hypervisor telling us the connection is closed */
+		scsi_block_requests(hostdata->host);
+		if (crq->format == 0x06) {
+			/* We need to re-setup the interpartition connection */
+			printk(KERN_INFO
+			       "ibmvscsi: Re-enabling adapter!\n");
+			purge_requests(hostdata, DID_REQUEUE);
+			if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
+							hostdata) == 0)
+				if (ibmvscsi_send_crq(hostdata,
+						      0xC001000000000000LL, 0))
+					printk(KERN_ERR
+					       "ibmvscsi: transmit error after"
+					       " enable\n");
+		} else {
+			printk(KERN_INFO
+			       "ibmvscsi: Virtual adapter failed rc %d!\n",
+			       crq->format);
 
-		atomic_set(&hostdata->request_limit, -1);
-		purge_requests(hostdata);
-		ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
+			atomic_set(&hostdata->request_limit, -1);
+			purge_requests(hostdata, DID_ERROR);
+			ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
+		}
+		scsi_unblock_requests(hostdata->host);
 		return;
 	case 0x80:		/* real payload */
 		break;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 5b0edd1..4550d71 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -103,6 +103,9 @@
 int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
 			      struct ibmvscsi_host_data *hostdata);
 
+int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
+				struct ibmvscsi_host_data *hostdata);
+
 void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 			 struct ibmvscsi_host_data *hostdata);
 int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
index ce15d9e..7eed0b0 100644
--- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
+++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c
@@ -124,6 +124,19 @@
 }
 
 /**
+ * reenable_crq_queue: - reenables a crq after a failure
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ * no-op for iSeries
+ */
+int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
+				struct ibmvscsi_host_data *hostdata)
+{
+	return 0;
+}
+
+/**
  * ibmvscsi_send_crq: - Send a CRQ
  * @hostdata:	the adapter
  * @word1:	the first 64 bits of the data
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 75db2f5..f47dd87 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -281,6 +281,28 @@
 }
 
 /**
+ * reenable_crq_queue: - reenables a crq after
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ */
+int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
+				 struct ibmvscsi_host_data *hostdata)
+{
+	int rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	/* Re-enable the CRQ */
+	do {
+		rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address);
+	} while ((rc == H_InProgress) || (rc == H_Busy) || (H_isLongBusy(rc)));
+
+	if (rc)
+		printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
+	return rc;
+}
+
+/**
  * reset_crq_queue: - resets a crq after a failure
  * @queue:	crq_queue to initialize and register
  * @hostdata:	ibmvscsi_host_data of host
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 3c688ef..0cf0e4c 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -751,9 +751,8 @@
 	idescsi_add_settings(drive);
 }
 
-static int ide_scsi_remove(struct device *dev)
+static void ide_scsi_remove(ide_drive_t *drive)
 {
-	ide_drive_t *drive = to_ide_device(dev);
 	struct Scsi_Host *scsihost = drive->driver_data;
 	struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
 	struct gendisk *g = scsi->disk;
@@ -768,11 +767,9 @@
 
 	scsi_remove_host(scsihost);
 	ide_scsi_put(scsi);
-
-	return 0;
 }
 
-static int ide_scsi_probe(struct device *);
+static int ide_scsi_probe(ide_drive_t *);
 
 #ifdef CONFIG_PROC_FS
 static ide_proc_entry_t idescsi_proc[] = {
@@ -788,9 +785,9 @@
 		.owner		= THIS_MODULE,
 		.name		= "ide-scsi",
 		.bus		= &ide_bus_type,
-		.probe		= ide_scsi_probe,
-		.remove		= ide_scsi_remove,
 	},
+	.probe			= ide_scsi_probe,
+	.remove			= ide_scsi_remove,
 	.version		= IDESCSI_VERSION,
 	.media			= ide_scsi,
 	.supports_dsc_overlap	= 0,
@@ -1119,9 +1116,8 @@
 	.proc_name		= "ide-scsi",
 };
 
-static int ide_scsi_probe(struct device *dev)
+static int ide_scsi_probe(ide_drive_t *drive)
 {
-	ide_drive_t *drive = to_ide_device(dev);
 	idescsi_scsi_t *idescsi;
 	struct Scsi_Host *host;
 	struct gendisk *g;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index e5e1ca4..86c5461 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -3499,6 +3499,7 @@
 	int device_error;
 	uint32_t transfer_len;
 	IPS_DCDB_TABLE_TAPE *tapeDCDB;
+	IPS_SCSI_INQ_DATA inquiryData;
 
 	METHOD_TRACE("ips_map_status", 1);
 
@@ -3557,13 +3558,13 @@
 				errcode = DID_OK;
 
 				/* Restrict access to physical DASD */
-				if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
-				    ((((char *) scb->scsi_cmd->
-				       buffer)[0] & 0x1f) == TYPE_DISK)) {
-					/* underflow -- no error               */
-					/* restrict access to physical DASD    */
-					errcode = DID_TIME_OUT;
-					break;
+				if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
+				    ips_scmd_buf_read(scb->scsi_cmd, 
+                                      &inquiryData, sizeof (inquiryData));
+ 				    if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK) {
+				        errcode = DID_TIME_OUT;
+				        break;
+				    }
 				}
 			} else
 				errcode = DID_ERROR;
@@ -4135,6 +4136,7 @@
 	uint8_t basic_status;
 	uint8_t ext_status;
 	int errcode;
+	IPS_SCSI_INQ_DATA inquiryData;
 
 	METHOD_TRACE("ips_chkstatus", 1);
 
@@ -4255,11 +4257,11 @@
 			scb->scsi_cmd->result = errcode << 16;
 		} else {	/* bus == 0 */
 			/* restrict access to physical drives */
-			if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
-			    ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) ==
-			     TYPE_DISK)) {
-
-				scb->scsi_cmd->result = DID_TIME_OUT << 16;
+			if (scb->scsi_cmd->cmnd[0] == INQUIRY) { 
+			    ips_scmd_buf_read(scb->scsi_cmd, 
+                                  &inquiryData, sizeof (inquiryData));
+			    if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK) 
+			        scb->scsi_cmd->result = DID_TIME_OUT << 16;
 			}
 		}		/* else */
 	} else {		/* recovered error / success */
@@ -5012,7 +5014,7 @@
 				break;
 
 			/* Delay for 1 Second */
-			MDELAY(IPS_ONE_SEC);
+			msleep(IPS_ONE_SEC);
 		}
 
 		if (j >= 45)
@@ -5038,7 +5040,7 @@
 				break;
 
 			/* Delay for 1 Second */
-			MDELAY(IPS_ONE_SEC);
+			msleep(IPS_ONE_SEC);
 		}
 
 		if (j >= 240)
@@ -5056,7 +5058,7 @@
 			break;
 
 		/* Delay for 1 Second */
-		MDELAY(IPS_ONE_SEC);
+		msleep(IPS_ONE_SEC);
 	}
 
 	if (i >= 240)
@@ -5106,7 +5108,7 @@
 				break;
 
 			/* Delay for 1 Second */
-			MDELAY(IPS_ONE_SEC);
+			msleep(IPS_ONE_SEC);
 		}
 
 		if (j >= 45)
@@ -5132,7 +5134,7 @@
 				break;
 
 			/* Delay for 1 Second */
-			MDELAY(IPS_ONE_SEC);
+			msleep(IPS_ONE_SEC);
 		}
 
 		if (j >= 240)
@@ -5150,7 +5152,7 @@
 			break;
 
 		/* Delay for 1 Second */
-		MDELAY(IPS_ONE_SEC);
+		msleep(IPS_ONE_SEC);
 	}
 
 	if (i >= 240)
@@ -5202,7 +5204,7 @@
 			break;
 
 		/* Delay for 1 Second */
-		MDELAY(IPS_ONE_SEC);
+		msleep(IPS_ONE_SEC);
 	}
 
 	if (i >= 45) {
@@ -5228,7 +5230,7 @@
 			if (Post != 0x4F00)
 				break;
 			/* Delay for 1 Second */
-			MDELAY(IPS_ONE_SEC);
+			msleep(IPS_ONE_SEC);
 		}
 
 		if (i >= 120) {
@@ -5258,7 +5260,7 @@
 			break;
 
 		/* Delay for 1 Second */
-		MDELAY(IPS_ONE_SEC);
+		msleep(IPS_ONE_SEC);
 	}
 
 	if (i >= 240) {
@@ -5318,12 +5320,12 @@
 		outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR);
 
 		/* Delay for 1 Second */
-		MDELAY(IPS_ONE_SEC);
+		msleep(IPS_ONE_SEC);
 
 		outb(0, ha->io_addr + IPS_REG_SCPR);
 
 		/* Delay for 1 Second */
-		MDELAY(IPS_ONE_SEC);
+		msleep(IPS_ONE_SEC);
 
 		if ((*ha->func.init) (ha))
 			break;
@@ -5363,12 +5365,12 @@
 		writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR);
 
 		/* Delay for 1 Second */
-		MDELAY(IPS_ONE_SEC);
+		msleep(IPS_ONE_SEC);
 
 		writeb(0, ha->mem_ptr + IPS_REG_SCPR);
 
 		/* Delay for 1 Second */
-		MDELAY(IPS_ONE_SEC);
+		msleep(IPS_ONE_SEC);
 
 		if ((*ha->func.init) (ha))
 			break;
@@ -5409,7 +5411,7 @@
 		writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR);
 
 		/* Delay for 5 Seconds */
-		MDELAY(5 * IPS_ONE_SEC);
+		msleep(5 * IPS_ONE_SEC);
 
 		/* Do a PCI config read to wait for adapter */
 		pci_read_config_byte(ha->pcidev, 4, &junk);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index cfbceb5..07b1e7c 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1700,6 +1700,31 @@
 	return sizeof(def_rw_recovery_mpage);
 }
 
+/*
+ * We can turn this into a real blacklist if it's needed, for now just
+ * blacklist any Maxtor BANC1G10 revision firmware
+ */
+static int ata_dev_supports_fua(u16 *id)
+{
+	unsigned char model[41], fw[9];
+
+	if (!ata_id_has_fua(id))
+		return 0;
+
+	model[40] = '\0';
+	fw[8] = '\0';
+
+	ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1);
+	ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1);
+
+	if (strncmp(model, "Maxtor", 6))
+		return 1;
+	if (strncmp(fw, "BANC1G10", 8))
+		return 1;
+
+	return 0; /* blacklisted */
+}
+
 /**
  *	ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
  *	@args: device IDENTIFY data / SCSI command of interest.
@@ -1797,7 +1822,7 @@
 		return 0;
 
 	dpofua = 0;
-	if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 &&
+	if (ata_dev_supports_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 &&
 	    (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
 		dpofua = 1 << 4;
 
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 311a412..93edaa8 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -537,9 +537,9 @@
 	free_irq(fp->intr, fp);
 
 	if (fp->regs)
-		iounmap((void *) fp->regs);
+		iounmap(fp->regs);
 	if (fp->dma)
-		iounmap((void *) fp->dma);
+		iounmap(fp->dma);
 	kfree(fp->dma_cmd_space);
 
 	scsi_host_put(host);
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 511ed52..a487f41 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_sas.c
- * Version	: v00.00.02.00-rc4
+ * Version	: v00.00.02.02
  *
  * Authors:
  * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsil.com>
@@ -55,13 +55,13 @@
 
 	{
 	 PCI_VENDOR_ID_LSI_LOGIC,
-	 PCI_DEVICE_ID_LSI_SAS1064R,
+	 PCI_DEVICE_ID_LSI_SAS1064R, // xscale IOP
 	 PCI_ANY_ID,
 	 PCI_ANY_ID,
 	 },
 	{
 	 PCI_VENDOR_ID_DELL,
-	 PCI_DEVICE_ID_DELL_PERC5,
+	 PCI_DEVICE_ID_DELL_PERC5, // xscale IOP
 	 PCI_ANY_ID,
 	 PCI_ANY_ID,
 	 },
@@ -119,12 +119,18 @@
 	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
 }
 
+
 /**
- * megasas_enable_intr -	Enables interrupts
+*	The following functions are defined for xscale 
+*	(deviceid : 1064R, PERC5) controllers
+*/
+
+/**
+ * megasas_enable_intr_xscale -	Enables interrupts
  * @regs:			MFI register set
  */
 static inline void
-megasas_enable_intr(struct megasas_register_set __iomem * regs)
+megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
 {
 	writel(1, &(regs)->outbound_intr_mask);
 
@@ -133,13 +139,73 @@
 }
 
 /**
+ * megasas_read_fw_status_reg_xscale - returns the current FW status value
+ * @regs:			MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs)
+{
+	return readl(&(regs)->outbound_msg_0);
+}
+/**
+ * megasas_clear_interrupt_xscale -	Check & clear interrupt
+ * @regs:				MFI register set
+ */
+static int 
+megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
+{
+	u32 status;
+	/*
+	 * Check if it is our interrupt
+	 */
+	status = readl(&regs->outbound_intr_status);
+
+	if (!(status & MFI_OB_INTR_STATUS_MASK)) {
+		return 1;
+	}
+
+	/*
+	 * Clear the interrupt by writing back the same value
+	 */
+	writel(status, &regs->outbound_intr_status);
+
+	return 0;
+}
+
+/**
+ * megasas_fire_cmd_xscale -	Sends command to the FW
+ * @frame_phys_addr :		Physical address of cmd
+ * @frame_count :		Number of frames for the command
+ * @regs :			MFI register set
+ */
+static inline void 
+megasas_fire_cmd_xscale(dma_addr_t frame_phys_addr,u32 frame_count, struct megasas_register_set __iomem *regs)
+{
+	writel((frame_phys_addr >> 3)|(frame_count),
+	       &(regs)->inbound_queue_port);
+}
+
+static struct megasas_instance_template megasas_instance_template_xscale = {
+
+	.fire_cmd = megasas_fire_cmd_xscale,
+	.enable_intr = megasas_enable_intr_xscale,
+	.clear_intr = megasas_clear_intr_xscale,
+	.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
+};
+
+/**
+*	This is the end of set of functions & definitions specific 
+*	to xscale (deviceid : 1064R, PERC5) controllers
+*/
+
+/**
  * megasas_disable_intr -	Disables interrupts
  * @regs:			MFI register set
  */
 static inline void
 megasas_disable_intr(struct megasas_register_set __iomem * regs)
 {
-	u32 mask = readl(&regs->outbound_intr_mask) & (~0x00000001);
+	u32 mask = 0x1f; 
 	writel(mask, &regs->outbound_intr_mask);
 
 	/* Dummy readl to force pci flush */
@@ -167,8 +233,7 @@
 	/*
 	 * Issue the frame using inbound queue port
 	 */
-	writel(cmd->frame_phys_addr >> 3,
-	       &instance->reg_set->inbound_queue_port);
+	instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
 
 	/*
 	 * Wait for cmd_status to change
@@ -198,8 +263,7 @@
 {
 	cmd->cmd_status = ENODATA;
 
-	writel(cmd->frame_phys_addr >> 3,
-	       &instance->reg_set->inbound_queue_port);
+	instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
 
 	wait_event(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA));
 
@@ -242,8 +306,7 @@
 	cmd->sync_cmd = 1;
 	cmd->cmd_status = 0xFF;
 
-	writel(cmd->frame_phys_addr >> 3,
-	       &instance->reg_set->inbound_queue_port);
+	instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
 
 	/*
 	 * Wait for this cmd to complete
@@ -558,112 +621,29 @@
 }
 
 /**
- * megasas_build_cmd -	Prepares a command packet
- * @instance:		Adapter soft state
- * @scp:		SCSI command
- * @frame_count:	[OUT] Number of frames used to prepare this command
+ * megasas_is_ldio -		Checks if the cmd is for logical drive
+ * @scmd:			SCSI command
+ *	
+ * Called by megasas_queue_command to find out if the command to be queued
+ * is a logical drive command	
  */
-static struct megasas_cmd *megasas_build_cmd(struct megasas_instance
-						    *instance,
-						    struct scsi_cmnd *scp,
-						    int *frame_count)
+static inline int megasas_is_ldio(struct scsi_cmnd *cmd)
 {
-	u32 logical_cmd;
-	struct megasas_cmd *cmd;
-
-	/*
-	 * Find out if this is logical or physical drive command.
-	 */
-	logical_cmd = MEGASAS_IS_LOGICAL(scp);
-
-	/*
-	 * Logical drive command
-	 */
-	if (logical_cmd) {
-
-		if (scp->device->id >= MEGASAS_MAX_LD) {
-			scp->result = DID_BAD_TARGET << 16;
-			return NULL;
-		}
-
-		switch (scp->cmnd[0]) {
-
-		case READ_10:
-		case WRITE_10:
-		case READ_12:
-		case WRITE_12:
-		case READ_6:
-		case WRITE_6:
-		case READ_16:
-		case WRITE_16:
-			/*
-			 * Fail for LUN > 0
-			 */
-			if (scp->device->lun) {
-				scp->result = DID_BAD_TARGET << 16;
-				return NULL;
-			}
-
-			cmd = megasas_get_cmd(instance);
-
-			if (!cmd) {
-				scp->result = DID_IMM_RETRY << 16;
-				return NULL;
-			}
-
-			*frame_count = megasas_build_ldio(instance, scp, cmd);
-
-			if (!(*frame_count)) {
-				megasas_return_cmd(instance, cmd);
-				return NULL;
-			}
-
-			return cmd;
-
-		default:
-			/*
-			 * Fail for LUN > 0
-			 */
-			if (scp->device->lun) {
-				scp->result = DID_BAD_TARGET << 16;
-				return NULL;
-			}
-
-			cmd = megasas_get_cmd(instance);
-
-			if (!cmd) {
-				scp->result = DID_IMM_RETRY << 16;
-				return NULL;
-			}
-
-			*frame_count = megasas_build_dcdb(instance, scp, cmd);
-
-			if (!(*frame_count)) {
-				megasas_return_cmd(instance, cmd);
-				return NULL;
-			}
-
-			return cmd;
-		}
-	} else {
-		cmd = megasas_get_cmd(instance);
-
-		if (!cmd) {
-			scp->result = DID_IMM_RETRY << 16;
-			return NULL;
-		}
-
-		*frame_count = megasas_build_dcdb(instance, scp, cmd);
-
-		if (!(*frame_count)) {
-			megasas_return_cmd(instance, cmd);
-			return NULL;
-		}
-
-		return cmd;
+	if (!MEGASAS_IS_LOGICAL(cmd))
+		return 0;
+	switch (cmd->cmnd[0]) {
+	case READ_10:
+	case WRITE_10:
+	case READ_12:
+	case WRITE_12:
+	case READ_6:
+	case WRITE_6:
+	case READ_16:
+	case WRITE_16:
+		return 1;
+	default:
+		return 0;
 	}
-
-	return NULL;
 }
 
 /**
@@ -684,13 +664,27 @@
 	scmd->scsi_done = done;
 	scmd->result = 0;
 
-	cmd = megasas_build_cmd(instance, scmd, &frame_count);
-
-	if (!cmd) {
-		done(scmd);
-		return 0;
+	if (MEGASAS_IS_LOGICAL(scmd) &&
+	    (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) {
+		scmd->result = DID_BAD_TARGET << 16;
+		goto out_done;
 	}
 
+	cmd = megasas_get_cmd(instance);
+	if (!cmd)
+		return SCSI_MLQUEUE_HOST_BUSY;
+
+	/*
+	 * Logical drive command
+	 */
+	if (megasas_is_ldio(scmd))
+		frame_count = megasas_build_ldio(instance, scmd, cmd);
+	else
+		frame_count = megasas_build_dcdb(instance, scmd, cmd);
+
+	if (!frame_count)
+		goto out_return_cmd;
+
 	cmd->scmd = scmd;
 	scmd->SCp.ptr = (char *)cmd;
 	scmd->SCp.sent_command = jiffies;
@@ -702,10 +696,15 @@
 	instance->fw_outstanding++;
 	spin_unlock_irqrestore(&instance->instance_lock, flags);
 
-	writel(((cmd->frame_phys_addr >> 3) | (cmd->frame_count - 1)),
-	       &instance->reg_set->inbound_queue_port);
+	instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
 
 	return 0;
+
+ out_return_cmd:
+	megasas_return_cmd(instance, cmd);
+ out_done:
+	done(scmd);
+	return 0;
 }
 
 /**
@@ -1108,7 +1107,6 @@
 static int
 megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
 {
-	u32 status;
 	u32 producer;
 	u32 consumer;
 	u32 context;
@@ -1116,17 +1114,10 @@
 
 	/*
 	 * Check if it is our interrupt
+	 * Clear the interrupt 
 	 */
-	status = readl(&instance->reg_set->outbound_intr_status);
-
-	if (!(status & MFI_OB_INTR_STATUS_MASK)) {
+	if(instance->instancet->clear_intr(instance->reg_set))
 		return IRQ_NONE;
-	}
-
-	/*
-	 * Clear the interrupt by writing back the same value
-	 */
-	writel(status, &instance->reg_set->outbound_intr_status);
 
 	producer = *instance->producer;
 	consumer = *instance->consumer;
@@ -1160,7 +1151,7 @@
 
 /**
  * megasas_transition_to_ready -	Move the FW to READY state
- * @reg_set:				MFI register set
+ * @instance:				Adapter soft state
  *
  * During the initialization, FW passes can potentially be in any one of
  * several possible states. If the FW in operational, waiting-for-handshake
@@ -1168,14 +1159,14 @@
  * has to wait for the ready state.
  */
 static int
-megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set)
+megasas_transition_to_ready(struct megasas_instance* instance)
 {
 	int i;
 	u8 max_wait;
 	u32 fw_state;
 	u32 cur_state;
 
-	fw_state = readl(&reg_set->outbound_msg_0) & MFI_STATE_MASK;
+	fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
 
 	while (fw_state != MFI_STATE_READY) {
 
@@ -1193,7 +1184,7 @@
 			 * Set the CLR bit in inbound doorbell
 			 */
 			writel(MFI_INIT_CLEAR_HANDSHAKE,
-			       &reg_set->inbound_doorbell);
+				&instance->reg_set->inbound_doorbell);
 
 			max_wait = 2;
 			cur_state = MFI_STATE_WAIT_HANDSHAKE;
@@ -1203,8 +1194,8 @@
 			/*
 			 * Bring it to READY state; assuming max wait 2 secs
 			 */
-			megasas_disable_intr(reg_set);
-			writel(MFI_INIT_READY, &reg_set->inbound_doorbell);
+			megasas_disable_intr(instance->reg_set);
+			writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell);
 
 			max_wait = 10;
 			cur_state = MFI_STATE_OPERATIONAL;
@@ -1253,8 +1244,8 @@
 		 * The cur_state should not last for more than max_wait secs
 		 */
 		for (i = 0; i < (max_wait * 1000); i++) {
-			fw_state = MFI_STATE_MASK &
-			    readl(&reg_set->outbound_msg_0);
+			fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &  
+					MFI_STATE_MASK ;
 
 			if (fw_state == cur_state) {
 				msleep(1);
@@ -1616,18 +1607,20 @@
 
 	reg_set = instance->reg_set;
 
+	instance->instancet = &megasas_instance_template_xscale;
+
 	/*
 	 * We expect the FW state to be READY
 	 */
-	if (megasas_transition_to_ready(instance->reg_set))
+	if (megasas_transition_to_ready(instance))
 		goto fail_ready_state;
 
 	/*
 	 * Get various operational parameters from status register
 	 */
-	instance->max_fw_cmds = readl(&reg_set->outbound_msg_0) & 0x00FFFF;
-	instance->max_num_sge = (readl(&reg_set->outbound_msg_0) & 0xFF0000) >>
-	    0x10;
+	instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
+	instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> 
+					0x10;
 	/*
 	 * Create a pool of commands
 	 */
@@ -1936,8 +1929,7 @@
 	/*
 	 * Issue the aen registration frame
 	 */
-	writel(cmd->frame_phys_addr >> 3,
-	       &instance->reg_set->inbound_queue_port);
+	instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
 
 	return 0;
 }
@@ -2126,7 +2118,7 @@
 		goto fail_irq;
 	}
 
-	megasas_enable_intr(instance->reg_set);
+	instance->instancet->enable_intr(instance->reg_set);
 
 	/*
 	 * Store instance in PCI softstate
@@ -2681,9 +2673,8 @@
 			  unsigned long arg)
 {
 	switch (cmd) {
-	case MEGASAS_IOC_FIRMWARE:{
-			return megasas_mgmt_compat_ioctl_fw(file, arg);
-		}
+	case MEGASAS_IOC_FIRMWARE32:
+		return megasas_mgmt_compat_ioctl_fw(file, arg);
 	case MEGASAS_IOC_GET_AEN:
 		return megasas_mgmt_ioctl_aen(file, arg);
 	}
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index eaec9d5..d6d166c 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -18,10 +18,9 @@
 /**
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION				"00.00.02.00-rc4"
-#define MEGASAS_RELDATE				"Sep 16, 2005"
-#define MEGASAS_EXT_VERSION			"Fri Sep 16 12:37:08 EDT 2005"
-
+#define MEGASAS_VERSION				"00.00.02.02"
+#define MEGASAS_RELDATE				"Jan 23, 2006"
+#define MEGASAS_EXT_VERSION			"Mon Jan 23 14:09:01 PST 2006"
 /*
  * =====================================
  * MegaRAID SAS MFI firmware definitions
@@ -1013,6 +1012,16 @@
 
 } __attribute__ ((packed));
 
+ struct megasas_instance_template {
+	void (*fire_cmd)(dma_addr_t ,u32 ,struct megasas_register_set __iomem *);
+
+	void (*enable_intr)(struct megasas_register_set __iomem *) ;
+
+	int (*clear_intr)(struct megasas_register_set __iomem *);
+
+	u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
+ };
+
 struct megasas_instance {
 
 	u32 *producer;
@@ -1056,6 +1065,8 @@
 	u32 fw_outstanding;
 	u32 hw_crit_error;
 	spinlock_t instance_lock;
+
+	struct megasas_instance_template *instancet;
 };
 
 #define MEGASAS_IS_LOGICAL(scp)						\
@@ -1125,11 +1136,10 @@
 	struct compat_iovec sgl[MAX_IOCTL_SGE];
 } __attribute__ ((packed));
 
-#define MEGASAS_IOC_FIRMWARE	_IOWR('M', 1, struct compat_megasas_iocpacket)
-#else
-#define MEGASAS_IOC_FIRMWARE	_IOWR('M', 1, struct megasas_iocpacket)
 #endif
 
+#define MEGASAS_IOC_FIRMWARE	_IOWR('M', 1, struct megasas_iocpacket)
+#define MEGASAS_IOC_FIRMWARE32	_IOWR('M', 1, struct compat_megasas_iocpacket)
 #define MEGASAS_IOC_GET_AEN	_IOW('M', 3, struct megasas_aen)
 
 struct megasas_mgmt_info {
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 0878f95..e023024 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -17,9 +17,11 @@
 * General Public License for more details.
 *
 ******************************************************************************/
-#define QLA1280_VERSION      "3.25"
+#define QLA1280_VERSION      "3.26"
 /*****************************************************************************
     Revision History:
+    Rev  3.26, January 16, 2006 Jes Sorensen
+	- Ditch all < 2.6 support
     Rev  3.25.1, February 10, 2005 Christoph Hellwig
 	- use pci_map_single to map non-S/G requests
 	- remove qla1280_proc_info
@@ -356,25 +358,18 @@
 #include <asm/types.h>
 #include <asm/system.h>
 
-#if LINUX_VERSION_CODE >= 0x020545
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
-#else
-#include <linux/blk.h>
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "sd.h"
-#endif
 
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
 #include <asm/sn/io.h>
 #endif
 
-#if LINUX_VERSION_CODE < 0x020407
-#error "Kernels older than 2.4.7 are no longer supported"
+#if LINUX_VERSION_CODE < 0x020600
+#error "Kernels older than 2.6.0 are no longer supported"
 #endif
 
 
@@ -441,52 +436,6 @@
 
 #define NVRAM_DELAY()			udelay(500)	/* 2 microseconds */
 
-#if LINUX_VERSION_CODE < 0x020500
-#define HOST_LOCK			&io_request_lock
-#define irqreturn_t			void
-#define IRQ_RETVAL(foo)
-#define MSG_ORDERED_TAG			1
-
-#define DMA_BIDIRECTIONAL	SCSI_DATA_UNKNOWN
-#define DMA_TO_DEVICE		SCSI_DATA_WRITE
-#define DMA_FROM_DEVICE		SCSI_DATA_READ
-#define DMA_NONE		SCSI_DATA_NONE
-
-#ifndef HAVE_SECTOR_T
-typedef unsigned int sector_t;
-#endif
-
-static inline void
-scsi_adjust_queue_depth(struct scsi_device *device, int tag, int depth)
-{
-	if (tag) {
-		device->tagged_queue = tag;
-		device->current_tag = 0;
-	}
-	device->queue_depth = depth;
-}
-static inline struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *t, size_t s)
-{
-	return scsi_register(t, s);
-}
-static inline void scsi_host_put(struct Scsi_Host *h)
-{
-	scsi_unregister(h);
-}
-#else
-#define HOST_LOCK			ha->host->host_lock
-#endif
-#if LINUX_VERSION_CODE < 0x020600
-#define DEV_SIMPLE_TAGS(device)		device->tagged_queue
-/*
- * Hack around that qla1280_remove_one is called from
- * qla1280_release in 2.4
- */
-#undef __devexit
-#define __devexit
-#else
-#define DEV_SIMPLE_TAGS(device)		device->simple_tags
-#endif
 #if defined(__ia64__) && !defined(ia64_platform_is)
 #define ia64_platform_is(foo)		(!strcmp(x, platform_name))
 #endif
@@ -506,9 +455,6 @@
  *  QLogic Driver Support Function Prototypes.
  */
 static void qla1280_done(struct scsi_qla_host *);
-#if LINUX_VERSION_CODE < 0x020545
-static void qla1280_get_target_options(struct scsi_cmnd *, struct scsi_qla_host *);
-#endif
 static int qla1280_get_token(char *);
 static int qla1280_setup(char *s) __init;
 
@@ -610,11 +556,7 @@
 #define	CMD_SNSLEN(Cmnd)	sizeof(Cmnd->sense_buffer)
 #define	CMD_RESULT(Cmnd)	Cmnd->result
 #define	CMD_HANDLE(Cmnd)	Cmnd->host_scribble
-#if LINUX_VERSION_CODE < 0x020545
-#define CMD_REQUEST(Cmnd)	Cmnd->request.cmd
-#else
 #define CMD_REQUEST(Cmnd)	Cmnd->request->cmd
-#endif
 
 #define CMD_HOST(Cmnd)		Cmnd->device->host
 #define SCSI_BUS_32(Cmnd)	Cmnd->device->channel
@@ -1064,10 +1006,10 @@
 	add_timer(&timer);
 
 	/* wait for the action to complete (or the timer to expire) */
-	spin_unlock_irq(HOST_LOCK);
+	spin_unlock_irq(ha->host->host_lock);
 	wait_for_completion(&wait);
 	del_timer_sync(&timer);
-	spin_lock_irq(HOST_LOCK);
+	spin_lock_irq(ha->host->host_lock);
 	sp->wait = NULL;
 
 	/* the only action we might get a fail for is abort */
@@ -1173,96 +1115,6 @@
 	return 0;
 }
 
-#if LINUX_VERSION_CODE < 0x020600
-static int
-qla1280_detect(struct scsi_host_template *template)
-{
-	struct pci_device_id *id = &qla1280_pci_tbl[0];
-	struct pci_dev *pdev = NULL;
-	int num_hosts = 0;
-
-	if (sizeof(struct srb) > sizeof(Scsi_Pointer)) {
-		printk(KERN_WARNING
-		       "qla1280: struct srb too big, aborting\n");
-		return 0;
-	}
-
-	if ((DMA_BIDIRECTIONAL != PCI_DMA_BIDIRECTIONAL) ||
-	    (DMA_TO_DEVICE != PCI_DMA_TODEVICE) ||
-	    (DMA_FROM_DEVICE != PCI_DMA_FROMDEVICE) ||
-	    (DMA_NONE != PCI_DMA_NONE)) {
-		printk(KERN_WARNING
-		       "qla1280: dma direction bits don't match\n");
-		return 0;
-	}
-
-#ifdef MODULE
-	/*
-	 * If we are called as a module, the qla1280 pointer may not be null
-	 * and it would point to our bootup string, just like on the lilo
-	 * command line.  IF not NULL, then process this config string with
-	 * qla1280_setup
-	 *
-	 * Boot time Options
-	 * To add options at boot time add a line to your lilo.conf file like:
-	 * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}"
-	 * which will result in the first four devices on the first two
-	 * controllers being set to a tagged queue depth of 32.
-	 */
-	if (qla1280)
-		qla1280_setup(qla1280);
-#endif
-
-	/* First Initialize QLA12160 on PCI Bus 1 Dev 2 */
-	while ((pdev = pci_find_device(id->vendor, id->device, pdev))) {
-		if (pdev->bus->number == 1 && PCI_SLOT(pdev->devfn) == 2) {
-			if (!qla1280_probe_one(pdev, id))
-				num_hosts++;
-		}
-	}
-
-	pdev = NULL;
-	/* Try and find each different type of adapter we support */
-	for (id = &qla1280_pci_tbl[0]; id->device; id++) {
-		while ((pdev = pci_find_device(id->vendor, id->device, pdev))) {
-			/*
-			 * skip QLA12160 already initialized on
-			 * PCI Bus 1 Dev 2 since we already initialized
-			 * and presented it
-			 */
-			if (id->device == PCI_DEVICE_ID_QLOGIC_ISP12160 &&
-			    pdev->bus->number == 1 &&
-			    PCI_SLOT(pdev->devfn) == 2)
-				continue;
-
-			if (!qla1280_probe_one(pdev, id))
-				num_hosts++;
-		}
-	}
-
-	return num_hosts;
-}
-
-/*
- * This looks a bit ugly as we could just pass down host to
- * qla1280_remove_one, but I want to keep qla1280_release purely a wrapper
- * around pci_driver::remove as used from 2.6 onwards.
- */
-static int
-qla1280_release(struct Scsi_Host *host)
-{
-	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
-
-	qla1280_remove_one(ha->pdev);
-	return 0;
-}
-
-static int
-qla1280_biosparam_old(Disk * disk, kdev_t dev, int geom[])
-{
-	return qla1280_biosparam(disk->device, NULL, disk->capacity, geom);
-}
-#endif
  
 /* disable risc and host interrupts */
 static inline void
@@ -1295,7 +1147,7 @@
 	ENTER_INTR ("qla1280_intr_handler");
 	ha = (struct scsi_qla_host *)dev_id;
 
-	spin_lock(HOST_LOCK);
+	spin_lock(ha->host->host_lock);
 
 	ha->isr_count++;
 	reg = ha->iobase;
@@ -1311,7 +1163,7 @@
 	if (!list_empty(&ha->done_q))
 		qla1280_done(ha);
 
-	spin_unlock(HOST_LOCK);
+	spin_unlock(ha->host->host_lock);
 
 	qla1280_enable_intrs(ha);
 
@@ -1411,11 +1263,9 @@
 		scsi_adjust_queue_depth(device, 0, default_depth);
 	}
 
-#if LINUX_VERSION_CODE > 0x020500
 	nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;
 	nv->bus[bus].target[target].parameter.enable_wide = device->wdtr;
 	nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr;
-#endif
 
 	if (driver_setup.no_sync ||
 	    (driver_setup.sync_mask &&
@@ -1432,38 +1282,14 @@
 			nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;
 	}
 
-	spin_lock_irqsave(HOST_LOCK, flags);
+	spin_lock_irqsave(ha->host->host_lock, flags);
 	if (nv->bus[bus].target[target].parameter.enable_sync)
 		status = qla1280_set_target_parameters(ha, bus, target);
 	qla1280_get_target_parameters(ha, device);
-	spin_unlock_irqrestore(HOST_LOCK, flags);
+	spin_unlock_irqrestore(ha->host->host_lock, flags);
 	return status;
 }
 
-#if LINUX_VERSION_CODE < 0x020545
-/**************************************************************************
- *   qla1280_select_queue_depth
- *
- *   Sets the queue depth for each SCSI device hanging off the input
- *   host adapter.  We use a queue depth of 2 for devices that do not
- *   support tagged queueing.
- **************************************************************************/
-static void
-qla1280_select_queue_depth(struct Scsi_Host *host, struct scsi_device *sdev_q)
-{
-	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
-	struct scsi_device *sdev;
-
-	ENTER("qla1280_select_queue_depth");
-	for (sdev = sdev_q; sdev; sdev = sdev->next)
-		if (sdev->host == host)
-			qla1280_slave_configure(sdev);
-
-	if (sdev_q)
-		qla1280_check_for_dead_scsi_bus(ha, sdev_q->channel);
-	LEAVE("qla1280_select_queue_depth");
-}
-#endif
 
 /*
  * qla1280_done
@@ -1523,10 +1349,6 @@
 		CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE;
 		ha->actthreads--;
 
-#if LINUX_VERSION_CODE < 0x020500
-		if (cmd->cmnd[0] == INQUIRY)
-			qla1280_get_target_options(cmd, ha);
-#endif
 		(*(cmd)->scsi_done)(cmd);
 
 		if(sp->wait != NULL)
@@ -1655,9 +1477,7 @@
 	struct device_reg __iomem *reg;
 	int status;
 	int bus;
-#if LINUX_VERSION_CODE > 0x020500
 	unsigned long flags;
-#endif
 
 	ENTER("qla1280_initialize_adapter");
 
@@ -1695,15 +1515,12 @@
 			"NVRAM\n");
 	}
 
-#if LINUX_VERSION_CODE >= 0x020500
 	/*
 	 * It's necessary to grab the spin here as qla1280_mailbox_command
 	 * needs to be able to drop the lock unconditionally to wait
 	 * for completion.
-	 * In 2.4 ->detect is called with the io_request_lock held.
 	 */
-	spin_lock_irqsave(HOST_LOCK, flags);
-#endif
+	spin_lock_irqsave(ha->host->host_lock, flags);
 
 	status = qla1280_load_firmware(ha);
 	if (status) {
@@ -1735,9 +1552,8 @@
 
 	ha->flags.online = 1;
  out:
-#if LINUX_VERSION_CODE >= 0x020500
-	spin_unlock_irqrestore(HOST_LOCK, flags);
-#endif
+	spin_unlock_irqrestore(ha->host->host_lock, flags);
+
 	if (status)
 		dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n");
 
@@ -2650,14 +2466,14 @@
 	timer.function = qla1280_mailbox_timeout;
 	add_timer(&timer);
 
-	spin_unlock_irq(HOST_LOCK);
+	spin_unlock_irq(ha->host->host_lock);
 	WRT_REG_WORD(&reg->host_cmd, HC_SET_HOST_INT);
 	data = qla1280_debounce_register(&reg->istatus);
 
 	wait_for_completion(&wait);
 	del_timer_sync(&timer);
 
-	spin_lock_irq(HOST_LOCK);
+	spin_lock_irq(ha->host->host_lock);
 
 	ha->mailbox_wait = NULL;
 
@@ -2770,9 +2586,9 @@
 			ha->bus_settings[bus].scsi_bus_dead = 1;
 		ha->bus_settings[bus].failed_reset_count++;
 	} else {
-		spin_unlock_irq(HOST_LOCK);
+		spin_unlock_irq(ha->host->host_lock);
 		ssleep(reset_delay);
-		spin_lock_irq(HOST_LOCK);
+		spin_lock_irq(ha->host->host_lock);
 
 		ha->bus_settings[bus].scsi_bus_dead = 0;
 		ha->bus_settings[bus].failed_reset_count = 0;
@@ -3078,7 +2894,7 @@
 		(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
 
 	/* Enable simple tag queuing if device supports it. */
-	if (DEV_SIMPLE_TAGS(cmd->device))
+	if (cmd->device->simple_tags)
 		pkt->control_flags |= cpu_to_le16(BIT_3);
 
 	/* Load SCSI command packet. */
@@ -3377,7 +3193,7 @@
 		(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
 
 	/* Enable simple tag queuing if device supports it. */
-	if (DEV_SIMPLE_TAGS(cmd->device))
+	if (cmd->device->simple_tags)
 		pkt->control_flags |= cpu_to_le16(BIT_3);
 
 	/* Load SCSI command packet. */
@@ -3889,50 +3705,6 @@
 }
 
 
-#if LINUX_VERSION_CODE < 0x020500
-/*
- *
- */
-static void
-qla1280_get_target_options(struct scsi_cmnd *cmd, struct scsi_qla_host *ha)
-{
-	unsigned char *result;
-	struct nvram *n;
-	int bus, target, lun;
-
-	bus = SCSI_BUS_32(cmd);
-	target = SCSI_TCN_32(cmd);
-	lun = SCSI_LUN_32(cmd);
-
-	/*
-	 * Make sure to not touch anything if someone is using the
-	 * sg interface.
-	 */
-	if (cmd->use_sg || (CMD_RESULT(cmd) >> 16) != DID_OK || lun)
-		return;
-
-	result = cmd->request_buffer;
-	n = &ha->nvram;
-
-	n->bus[bus].target[target].parameter.enable_wide = 0;
-	n->bus[bus].target[target].parameter.enable_sync = 0;
-	n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;
-
-        if (result[7] & 0x60)
-		n->bus[bus].target[target].parameter.enable_wide = 1;
-        if (result[7] & 0x10)
-		n->bus[bus].target[target].parameter.enable_sync = 1;
-	if ((result[2] >= 3) && (result[4] + 5 > 56) &&
-	    (result[56] & 0x4))
-		n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1;
-
-	dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n",
-		n->bus[bus].target[target].parameter.enable_wide,
-		n->bus[bus].target[target].parameter.enable_sync,
-		n->bus[bus].target[target].ppr_1x160.flags.enable_ppr);
-}
-#endif
-
 /*
  *  qla1280_status_entry
  *      Processes received ISP status entry.
@@ -4271,7 +4043,7 @@
 	} else
 		printk(" Async");
 
-	if (DEV_SIMPLE_TAGS(device))
+	if (device->simple_tags)
 		printk(", Tagged queuing: depth %d", device->queue_depth);
 	printk("\n");
 }
@@ -4485,7 +4257,7 @@
 	return ret;
 }
 
-#if LINUX_VERSION_CODE >= 0x020600
+
 static struct scsi_host_template qla1280_driver_template = {
 	.module			= THIS_MODULE,
 	.proc_name		= "qla1280",
@@ -4504,27 +4276,7 @@
 	.cmd_per_lun		= 1,
 	.use_clustering		= ENABLE_CLUSTERING,
 };
-#else
-static struct scsi_host_template qla1280_driver_template = {
-	.proc_name		= "qla1280",
-	.name			= "Qlogic ISP 1280/12160",
-	.detect			= qla1280_detect,
-	.release		= qla1280_release,
-	.info			= qla1280_info,
-	.queuecommand		= qla1280_queuecommand,
-	.eh_abort_handler	= qla1280_eh_abort,
-	.eh_device_reset_handler= qla1280_eh_device_reset,
-	.eh_bus_reset_handler	= qla1280_eh_bus_reset,
-	.eh_host_reset_handler	= qla1280_eh_adapter_reset,
-	.bios_param		= qla1280_biosparam_old,
-	.can_queue		= 0xfffff,
-	.this_id		= -1,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= ENABLE_CLUSTERING,
-	.use_new_eh_code	= 1,
-};
-#endif
+
 
 static int __devinit
 qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -4615,10 +4367,6 @@
 	host->max_sectors = 1024;
 	host->unique_id = host->host_no;
 
-#if LINUX_VERSION_CODE < 0x020545
-	host->select_queue_depths = qla1280_select_queue_depth;
-#endif
-
 	error = -ENODEV;
 
 #if MEMORY_MAPPED_IO
@@ -4666,21 +4414,15 @@
 
 	pci_set_drvdata(pdev, host);
 
-#if LINUX_VERSION_CODE >= 0x020600
 	error = scsi_add_host(host, &pdev->dev);
 	if (error)
 		goto error_disable_adapter;
 	scsi_scan_host(host);
-#else
-	scsi_set_pci_device(host, pdev);
-#endif
 
 	return 0;
 
-#if LINUX_VERSION_CODE >= 0x020600
  error_disable_adapter:
 	qla1280_disable_intrs(ha);
-#endif
  error_free_irq:
 	free_irq(pdev->irq, ha);
  error_release_region:
@@ -4712,9 +4454,7 @@
 	struct Scsi_Host *host = pci_get_drvdata(pdev);
 	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
 
-#if LINUX_VERSION_CODE >= 0x020600
 	scsi_remove_host(host);
-#endif
 
 	qla1280_disable_intrs(ha);
 
@@ -4738,7 +4478,6 @@
 	scsi_host_put(host);
 }
 
-#if LINUX_VERSION_CODE >= 0x020600
 static struct pci_driver qla1280_pci_driver = {
 	.name		= "qla1280",
 	.id_table	= qla1280_pci_tbl,
@@ -4784,10 +4523,6 @@
 module_init(qla1280_init);
 module_exit(qla1280_exit);
 
-#else
-# define driver_template qla1280_driver_template
-# include "scsi_module.c"
-#endif
 
 MODULE_AUTHOR("Qlogic & Jes Sorensen");
 MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 79d8a91..bad066e 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1680,7 +1680,8 @@
 	uint8_t mp_byte;		/* multi-path byte (not used) */
     	uint8_t cur_path;		/* current path id */
 
-	struct fc_rport *rport;
+	spinlock_t rport_lock;
+	struct fc_rport *rport, *drport;
 	u32 supported_classes;
 	struct work_struct rport_add_work;
 	struct work_struct rport_del_work;
@@ -2270,6 +2271,7 @@
 #define LOOP_RESET_NEEDED	24
 #define BEACON_BLINK_NEEDED	25
 #define REGISTER_FDMI_NEEDED	26
+#define FCPORT_UPDATE_NEEDED	27
 
 	uint32_t	device_flags;
 #define DFLG_LOCAL_DEVICES		BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 32be4c1..35266bd 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -47,9 +47,11 @@
 extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t);
 
 extern void qla2x00_rescan_fcports(scsi_qla_host_t *);
+extern void qla2x00_update_fcports(scsi_qla_host_t *);
 
 extern int qla2x00_abort_isp(scsi_qla_host_t *);
 
+extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
 extern void qla2x00_reg_remote_port(scsi_qla_host_t *, fc_port_t *);
 
 /*
@@ -70,8 +72,8 @@
 
 extern void qla2x00_cmd_timeout(srb_t *);
 
-extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int);
-extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *);
+extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
+extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
 
 extern void qla2x00_blink_led(scsi_qla_host_t *);
 
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a91fea6..e67bb09 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -32,7 +32,6 @@
 static int qla2x00_configure_hba(scsi_qla_host_t *);
 static int qla2x00_configure_loop(scsi_qla_host_t *);
 static int qla2x00_configure_local_loop(scsi_qla_host_t *);
-static void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
 static int qla2x00_configure_fabric(scsi_qla_host_t *);
 static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *, struct list_head *);
 static int qla2x00_device_resync(scsi_qla_host_t *);
@@ -1688,10 +1687,16 @@
 qla2x00_rport_del(void *data)
 {
 	fc_port_t *fcport = data;
+	struct fc_rport *rport;
+	unsigned long flags;
 
-	if (fcport->rport)
-		fc_remote_port_delete(fcport->rport);
-	fcport->rport = NULL;
+	spin_lock_irqsave(&fcport->rport_lock, flags);
+	rport = fcport->drport;
+	fcport->drport = NULL;
+	spin_unlock_irqrestore(&fcport->rport_lock, flags);
+	if (rport)
+		fc_remote_port_delete(rport);
+
 }
 
 /**
@@ -1719,6 +1724,7 @@
 	atomic_set(&fcport->state, FCS_UNCONFIGURED);
 	fcport->flags = FCF_RLC_SUPPORT;
 	fcport->supported_classes = FC_COS_UNSPECIFIED;
+	spin_lock_init(&fcport->rport_lock);
 	INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport);
 	INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport);
 
@@ -2008,7 +2014,7 @@
 {
 	fc_port_t	*fcport;
 
-	qla2x00_mark_all_devices_lost(ha);
+	qla2x00_mark_all_devices_lost(ha, 0);
  	list_for_each_entry(fcport, &ha->fcports, list) {
 		if (fcport->port_type != FCT_TARGET)
 			continue;
@@ -2032,13 +2038,9 @@
  * Context:
  *	Kernel context.
  */
-static void
+void
 qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
 {
-	uint16_t	index;
-	unsigned long flags;
-	srb_t *sp;
-
 	fcport->ha = ha;
 	fcport->login_retry = 0;
 	fcport->port_login_retry_count = ha->port_down_retry_count *
@@ -2047,28 +2049,6 @@
 	    PORT_RETRY_TIME);
 	fcport->flags &= ~FCF_LOGIN_NEEDED;
 
-	/*
-	 * Check for outstanding cmd on tape Bypass LUN discovery if active
-	 * command on tape.
-	 */
-	if (fcport->flags & FCF_TAPE_PRESENT) {
-		spin_lock_irqsave(&ha->hardware_lock, flags);
-		for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
-			fc_port_t *sfcp;
-
-			if ((sp = ha->outstanding_cmds[index]) != 0) {
-				sfcp = sp->fcport;
-				if (sfcp == fcport) {
-					atomic_set(&fcport->state, FCS_ONLINE);
-					spin_unlock_irqrestore(
-					    &ha->hardware_lock, flags);
-					return;
-				}
-			}
-		}
-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
-	}
-
 	if (fcport->port_type == FCT_INITIATOR ||
 	    fcport->port_type == FCT_BROADCAST)
 		fcport->device_type = TYPE_PROCESSOR;
@@ -2084,24 +2064,29 @@
 {
 	struct fc_rport_identifiers rport_ids;
 	struct fc_rport *rport;
+	unsigned long flags;
 
-	if (fcport->rport) {
-		fc_remote_port_delete(fcport->rport);
-		fcport->rport = NULL;
-	}
+	if (fcport->drport)
+		qla2x00_rport_del(fcport);
+	if (fcport->rport)
+		return;
 
 	rport_ids.node_name = wwn_to_u64(fcport->node_name);
 	rport_ids.port_name = wwn_to_u64(fcport->port_name);
 	rport_ids.port_id = fcport->d_id.b.domain << 16 |
 	    fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
 	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
-	fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids);
+	rport = fc_remote_port_add(ha->host, 0, &rport_ids);
 	if (!rport) {
 		qla_printk(KERN_WARNING, ha,
 		    "Unable to allocate fc remote port!\n");
 		return;
 	}
+	spin_lock_irqsave(&fcport->rport_lock, flags);
+	fcport->rport = rport;
 	*((fc_port_t **)rport->dd_data) = fcport;
+	spin_unlock_irqrestore(&fcport->rport_lock, flags);
+
 	rport->supported_classes = fcport->supported_classes;
 
 	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
@@ -2217,12 +2202,11 @@
 
 			if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) {
 				qla2x00_mark_device_lost(ha, fcport,
-				    ql2xplogiabsentdevice);
+				    ql2xplogiabsentdevice, 0);
 				if (fcport->loop_id != FC_NO_LOOP_ID &&
 				    (fcport->flags & FCF_TAPE_PRESENT) == 0 &&
 				    fcport->port_type != FCT_INITIATOR &&
 				    fcport->port_type != FCT_BROADCAST) {
-
 					ha->isp_ops.fabric_logout(ha,
 					    fcport->loop_id,
 					    fcport->d_id.b.domain,
@@ -2694,7 +2678,8 @@
 			if (atomic_read(&fcport->state) == FCS_ONLINE) {
 				if (format != 3 ||
 				    fcport->port_type != FCT_INITIATOR) {
-					qla2x00_mark_device_lost(ha, fcport, 0);
+					qla2x00_mark_device_lost(ha, fcport,
+					    0, 0);
 				}
 			}
 			fcport->flags &= ~FCF_FARP_DONE;
@@ -2741,8 +2726,7 @@
 			ha->isp_ops.fabric_logout(ha, fcport->loop_id,
 			    fcport->d_id.b.domain, fcport->d_id.b.area,
 			    fcport->d_id.b.al_pa);
-			qla2x00_mark_device_lost(ha, fcport, 1);
-
+			qla2x00_mark_device_lost(ha, fcport, 1, 0);
 		} else {
 			qla2x00_update_fcport(ha, fcport);
 		}
@@ -2855,7 +2839,7 @@
 			ha->isp_ops.fabric_logout(ha, fcport->loop_id,
 			    fcport->d_id.b.domain, fcport->d_id.b.area,
 			    fcport->d_id.b.al_pa);
-			qla2x00_mark_device_lost(ha, fcport, 1);
+			qla2x00_mark_device_lost(ha, fcport, 1, 0);
 
 			rval = 1;
 			break;
@@ -2990,6 +2974,17 @@
 	qla2x00_probe_for_all_luns(ha);
 }
 
+void
+qla2x00_update_fcports(scsi_qla_host_t *ha)
+{
+	fc_port_t *fcport;
+
+	/* Go with deferred removal of rport references. */
+	list_for_each_entry(fcport, &ha->fcports, list)
+		if (fcport->drport)
+			qla2x00_rport_del(fcport);
+}
+
 /*
 *  qla2x00_abort_isp
 *      Resets ISP and aborts all outstanding commands.
@@ -3019,7 +3014,7 @@
 		atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
 		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
 			atomic_set(&ha->loop_state, LOOP_DOWN);
-			qla2x00_mark_all_devices_lost(ha);
+			qla2x00_mark_all_devices_lost(ha, 0);
 		} else {
 			if (!atomic_read(&ha->loop_down_timer))
 				atomic_set(&ha->loop_down_timer,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index f63af08..71a46fc 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -389,7 +389,7 @@
 		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
 			atomic_set(&ha->loop_state, LOOP_DOWN);
 			atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
-			qla2x00_mark_all_devices_lost(ha);
+			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
 		set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
@@ -432,7 +432,7 @@
 			atomic_set(&ha->loop_state, LOOP_DOWN);
 			atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
 			ha->device_flags |= DFLG_NO_CABLE;
-			qla2x00_mark_all_devices_lost(ha);
+			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
 		ha->flags.management_server_logged_in = 0;
@@ -453,7 +453,7 @@
 		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
 			atomic_set(&ha->loop_state, LOOP_DOWN);
 			atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
-			qla2x00_mark_all_devices_lost(ha);
+			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
 		set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
@@ -482,7 +482,7 @@
 			if (!atomic_read(&ha->loop_down_timer))
 				atomic_set(&ha->loop_down_timer,
 				    LOOP_DOWN_TIME);
-			qla2x00_mark_all_devices_lost(ha);
+			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
 		if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) {
@@ -506,7 +506,7 @@
 			if (!atomic_read(&ha->loop_down_timer))
 				atomic_set(&ha->loop_down_timer,
 				    LOOP_DOWN_TIME);
-			qla2x00_mark_all_devices_lost(ha);
+			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
 		set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
@@ -580,7 +580,7 @@
 		 */
 		atomic_set(&ha->loop_state, LOOP_UP);
 
-		qla2x00_mark_all_devices_lost(ha);
+		qla2x00_mark_all_devices_lost(ha, 1);
 
 		ha->flags.rscn_queue_overflow = 1;
 
@@ -1091,7 +1091,7 @@
 
 		cp->result = DID_BUS_BUSY << 16;
 		if (atomic_read(&fcport->state) == FCS_ONLINE) {
-			qla2x00_mark_device_lost(ha, fcport, 1);
+			qla2x00_mark_device_lost(ha, fcport, 1, 1);
 		}
 		break;
 
@@ -1135,7 +1135,7 @@
 
 		/* Check to see if logout occurred. */
 		if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
-			qla2x00_mark_device_lost(ha, fcport, 1);
+			qla2x00_mark_device_lost(ha, fcport, 1, 1);
 		break;
 
 	case CS_QUEUE_FULL:
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4916847..5866a7c 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -756,7 +756,7 @@
 		if (ret == SUCCESS) {
 			if (fcport->flags & FC_FABRIC_DEVICE) {
 				ha->isp_ops.fabric_logout(ha, fcport->loop_id);
-				qla2x00_mark_device_lost(ha, fcport);
+				qla2x00_mark_device_lost(ha, fcport, 0, 0);
 			}
 		}
 #endif
@@ -1642,6 +1642,31 @@
 	pci_disable_device(ha->pdev);
 }
 
+static inline void
+qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
+    int defer)
+{
+	unsigned long flags;
+	struct fc_rport *rport;
+
+	if (!fcport->rport)
+		return;
+
+	rport = fcport->rport;
+	if (defer) {
+		spin_lock_irqsave(&fcport->rport_lock, flags);
+		fcport->drport = rport;
+		fcport->rport = NULL;
+		spin_unlock_irqrestore(&fcport->rport_lock, flags);
+		set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
+	} else {
+		spin_lock_irqsave(&fcport->rport_lock, flags);
+		fcport->rport = NULL;
+		spin_unlock_irqrestore(&fcport->rport_lock, flags);
+		fc_remote_port_delete(rport);
+	}
+}
+
 /*
  * qla2x00_mark_device_lost Updates fcport state when device goes offline.
  *
@@ -1652,10 +1677,10 @@
  * Context:
  */
 void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,
-    int do_login)
+    int do_login, int defer)
 {
-	if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
-		schedule_work(&fcport->rport_del_work);
+	if (atomic_read(&fcport->state) == FCS_ONLINE)
+		qla2x00_schedule_rport_del(ha, fcport, defer);
 
 	/*
 	 * We may need to retry the login, so don't change the state of the
@@ -1702,7 +1727,7 @@
  * Context:
  */
 void
-qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha)
+qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
 {
 	fc_port_t *fcport;
 
@@ -1716,10 +1741,13 @@
 		 */
 		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
 			continue;
-		if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
-			schedule_work(&fcport->rport_del_work);
+		if (atomic_read(&fcport->state) == FCS_ONLINE)
+			qla2x00_schedule_rport_del(ha, fcport, defer);
 		atomic_set(&fcport->state, FCS_DEVICE_LOST);
 	}
+
+	if (defer && ha->dpc_wait && !ha->dpc_active)
+		up(ha->dpc_wait);
 }
 
 /*
@@ -2161,6 +2189,9 @@
 			    ha->host_no));
 		}
 
+		if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))
+			qla2x00_update_fcports(ha);
+
 		if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) {
 			DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n",
 			    ha->host_no));
@@ -2219,13 +2250,8 @@
 						DEBUG(printk("scsi(%ld): port login OK: logged in ID 0x%x\n",
 						    ha->host_no, fcport->loop_id));
 
-						fcport->port_login_retry_count =
-						    ha->port_down_retry_count * PORT_RETRY_TIME;
-						atomic_set(&fcport->state, FCS_ONLINE);
-						atomic_set(&fcport->port_down_timer,
-						    ha->port_down_retry_count * PORT_RETRY_TIME);
-
-						fcport->login_retry = 0;
+						qla2x00_update_fcport(ha,
+						    fcport);
 					} else if (status == 1) {
 						set_bit(RELOGIN_NEEDED, &ha->dpc_flags);
 						/* retry the login again */
@@ -2469,6 +2495,7 @@
 	if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
 	    test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
 	    test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) ||
+	    test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags) ||
 	    start_dpc ||
 	    test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
 	    test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index cd54244..6fddf17 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -510,6 +510,12 @@
 };
 
 /*
+ * module options
+ */
+static int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
+
+
+/*
  * Functions
  */
 
@@ -2191,7 +2197,7 @@
 	}
 
 	/* Enable interrupts */
-	if (pci_enable_msi(pdev) == 0) {
+	if (msi && pci_enable_msi(pdev) == 0) {
 		hpriv->hp_flags |= MV_HP_FLAG_MSI;
 	} else {
 		pci_intx(pdev, 1);
@@ -2246,5 +2252,8 @@
 MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
+module_param(msi, int, 0444);
+MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
+
 module_init(mv_init);
 module_exit(mv_exit);
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index b017f85..17f74d3 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -231,6 +231,10 @@
 MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
+static int slow_down = 0;
+module_param(slow_down, int, 0444);
+MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)");
+
 
 static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
 {
@@ -354,8 +358,10 @@
 		}
 
 	/* limit requests to 15 sectors */
-	if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) {
-		printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
+	if (slow_down ||
+	    ((ap->flags & SIL_FLAG_MOD15WRITE) &&
+	     (quirks & SIL_QUIRK_MOD15WRITE))) {
+		printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n",
 		       ap->id, dev->devno);
 		ap->host->max_sectors = 15;
 		ap->host->hostt->max_sectors = 15;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 245ca99..c551bb8 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1245,7 +1245,7 @@
 	if (error)
 		goto cleanup_sysctl;
 
-	for (i = 0; i < NR_CPUS; i++)
+	for_each_cpu(i)
 		INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
 
 	devfs_mk_dir("scsi");
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index a2333d2..5cc97b7 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1350,7 +1350,7 @@
 	cmnd[4] = SCSI_REMOVAL_PREVENT;
 	cmnd[5] = 0;
 
-	scsi_execute_async(sdev, cmnd, DMA_NONE, NULL, 0, 0, 10 * HZ,
+	scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ,
 			   5, NULL, NULL, GFP_KERNEL);
 }
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 3574ba9..4a60285 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -436,6 +436,7 @@
  * scsi_execute_async - insert request
  * @sdev:	scsi device
  * @cmd:	scsi command
+ * @cmd_len:	length of scsi cdb
  * @data_direction: data direction
  * @buffer:	data buffer (this can be a kernel buffer or scatterlist)
  * @bufflen:	len of buffer
@@ -445,7 +446,7 @@
  * @flags:	or into request flags
  **/
 int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
-		       int data_direction, void *buffer, unsigned bufflen,
+		       int cmd_len, int data_direction, void *buffer, unsigned bufflen,
 		       int use_sg, int timeout, int retries, void *privdata,
 		       void (*done)(void *, char *, int, int), gfp_t gfp)
 {
@@ -472,7 +473,7 @@
 	if (err)
 		goto free_req;
 
-	req->cmd_len = COMMAND_SIZE(cmd[0]);
+	req->cmd_len = cmd_len;
 	memcpy(req->cmd, cmd, req->cmd_len);
 	req->sense = sioc->sense;
 	req->sense_len = 0;
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 59a1c9d..723f7ac 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -463,7 +463,7 @@
 }
 
 static void*
-mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
+mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
 {
 	struct mempool_zone *zone = pool_data;
 
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index a3e0b7b..210dab5 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -377,7 +377,7 @@
 /**
  * sas_phy_alloc  --  allocates and initialize a SAS PHY structure
  * @parent:	Parent device
- * @number:	Port number
+ * @number:	Phy index
  *
  * Allocates an SAS PHY structure.  It will be added in the device tree
  * below the device specified by @parent, which has to be either a Scsi_Host
@@ -595,8 +595,8 @@
 	device_initialize(&rphy->dev);
 	rphy->dev.parent = get_device(&parent->dev);
 	rphy->dev.release = sas_rphy_release;
-	sprintf(rphy->dev.bus_id, "rphy-%d:%d",
-		shost->host_no, parent->number);
+	sprintf(rphy->dev.bus_id, "rphy-%d:%d-%d",
+		shost->host_no, parent->port_identifier, parent->number);
 	transport_setup_device(&rphy->dev);
 
 	return rphy;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 78aad95..2a54753 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -741,7 +741,7 @@
 	hp->duration = jiffies_to_msecs(jiffies);
 /* Now send everything of to mid-level. The next time we hear about this
    packet is when sg_cmd_done() is called (i.e. a callback). */
-	if (scsi_execute_async(sdp->device, cmnd, data_dir, srp->data.buffer,
+	if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer,
 				hp->dxfer_len, srp->data.k_use_sg, timeout,
 				SG_DEFAULT_RETRIES, srp, sg_cmd_done,
 				GFP_ATOMIC)) {
@@ -1679,7 +1679,7 @@
 sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
 {
 	int sg_bufflen = tablesize * sizeof(struct scatterlist);
-	unsigned int gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
+	gfp_t gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
 
 	/*
 	 * TODO: test without low_dma, we should not need it since
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 13b1d3a..7f96f33 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -508,7 +508,7 @@
 	STp->buffer->cmdstat.have_sense = 0;
 	STp->buffer->syscall_result = 0;
 
-	if (scsi_execute_async(STp->device, cmd, direction,
+	if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction,
 			&((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
 			       timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
 		/* could not allocate the buffer or request was too large */
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 221999b..8c5c276 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -362,11 +362,11 @@
 
 static struct uart_port serial21285_port = {
 	.mapbase	= 0x42000160,
-	.iotype		= SERIAL_IO_MEM,
+	.iotype		= UPIO_MEM,
 	.irq		= NO_IRQ,
 	.fifosize	= 16,
 	.ops		= &serial21285_ops,
-	.flags		= ASYNC_BOOT_AUTOCONF,
+	.flags		= UPF_BOOT_AUTOCONF,
 };
 
 static void serial21285_setup_ports(void)
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 8cbf0fc..7f0f35a 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -332,7 +332,7 @@
 		 * Make sure that we do not overflow the buffer
 		 */
 		if (tty_request_buffer_room(tty, 1) == 0) {
-			schedule_work(&tty->flip.work);
+			tty_schedule_flip(tty);
 			return;
 		}
 
@@ -353,7 +353,7 @@
 	} while((rx = uart->urx.w) & URX_DATA_READY);
 #endif
 
-	schedule_work(&tty->flip.work);
+	tty_schedule_flip(tty);
 
 clear_and_exit:
 	return;
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 60f5a5d..9843ae3 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -509,7 +509,7 @@
 
 	info->rx_cur = (QUICC_BD *)bdp;
 
-	schedule_work(&tty->flip.work);
+	tty_schedule_flip(tty);
 }
 
 static _INLINE_ void receive_break(ser_info_t *info)
@@ -521,7 +521,7 @@
 	 * the break.  If not, we exit now, losing the break.  FIXME
 	 */
 	tty_insert_flip_char(tty, 0, TTY_BREAK);
-	schedule_work(&tty->flip.work);
+	tty_schedule_flip(tty);
 }
 
 static _INLINE_ void transmit_chars(ser_info_t *info)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index d9ce8c5..b1fc97d 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -31,7 +31,6 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
-#include <linux/mca.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/tty.h>
@@ -2027,12 +2026,6 @@
 	int ret;
 
 	/*
-	 * Don't probe for MCA ports on non-MCA machines.
-	 */
-	if (up->port.flags & UPF_BOOT_ONLYMCA && !MCA_bus)
-		return;
-
-	/*
 	 * Find the region that we can probe for.  This in turn
 	 * tells us whether we can probe for the type of port.
 	 */
@@ -2164,7 +2157,7 @@
 /*
  *	Wait for transmitter & holding register to empty
  */
-static inline void wait_for_xmitr(struct uart_8250_port *up)
+static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
 {
 	unsigned int status, tmout = 10000;
 
@@ -2178,7 +2171,7 @@
 		if (--tmout == 0)
 			break;
 		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+	} while ((status & bits) != bits);
 
 	/* Wait up to 1s for flow control if necessary */
 	if (up->port.flags & UPF_CONS_FLOW) {
@@ -2218,7 +2211,7 @@
 	 *	Now, do each character
 	 */
 	for (i = 0; i < count; i++, s++) {
-		wait_for_xmitr(up);
+		wait_for_xmitr(up, UART_LSR_THRE);
 
 		/*
 		 *	Send the character out.
@@ -2226,7 +2219,7 @@
 		 */
 		serial_out(up, UART_TX, *s);
 		if (*s == 10) {
-			wait_for_xmitr(up);
+			wait_for_xmitr(up, UART_LSR_THRE);
 			serial_out(up, UART_TX, 13);
 		}
 	}
@@ -2235,8 +2228,9 @@
 	 *	Finally, wait for transmitter to become empty
 	 *	and restore the IER
 	 */
-	wait_for_xmitr(up);
-	serial_out(up, UART_IER, ier);
+	wait_for_xmitr(up, BOTH_EMPTY);
+	up->ier |= UART_IER_THRI;
+	serial_out(up, UART_IER, ier | UART_IER_THRI);
 }
 
 static int serial8250_console_setup(struct console *co, char *options)
@@ -2595,15 +2589,11 @@
 	if (ret)
 		goto out;
 
-	ret = platform_driver_register(&serial8250_isa_driver);
-	if (ret)
-		goto unreg_uart_drv;
-
 	serial8250_isa_devs = platform_device_alloc("serial8250",
 						    PLAT8250_DEV_LEGACY);
 	if (!serial8250_isa_devs) {
 		ret = -ENOMEM;
-		goto unreg_plat_drv;
+		goto unreg_uart_drv;
 	}
 
 	ret = platform_device_add(serial8250_isa_devs);
@@ -2612,12 +2602,13 @@
 
 	serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
 
-	goto out;
+	ret = platform_driver_register(&serial8250_isa_driver);
+	if (ret == 0)
+		goto out;
 
+	platform_device_del(serial8250_isa_devs);
  put_dev:
 	platform_device_put(serial8250_isa_devs);
- unreg_plat_drv:
-	platform_driver_unregister(&serial8250_isa_driver);
  unreg_uart_drv:
 	uart_unregister_driver(&serial8250_reg);
  out:
diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c
index a802bdc..809f89a 100644
--- a/drivers/serial/8250_acpi.c
+++ b/drivers/serial/8250_acpi.c
@@ -27,7 +27,7 @@
 static acpi_status acpi_serial_mmio(struct uart_port *port,
 				    struct acpi_resource_address64 *addr)
 {
-	port->mapbase = addr->min_address_range;
+	port->mapbase = addr->minimum;
 	port->iotype = UPIO_MEM;
 	port->flags |= UPF_IOREMAP;
 	return AE_OK;
@@ -36,8 +36,8 @@
 static acpi_status acpi_serial_port(struct uart_port *port,
 				    struct acpi_resource_io *io)
 {
-	if (io->range_length) {
-		port->iobase = io->min_base_address;
+	if (io->address_length) {
+		port->iobase = io->minimum;
 		port->iotype = UPIO_PORT;
 	} else
 		printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__);
@@ -45,13 +45,13 @@
 }
 
 static acpi_status acpi_serial_ext_irq(struct uart_port *port,
-				       struct acpi_resource_ext_irq *ext_irq)
+				       struct acpi_resource_extended_irq *ext_irq)
 {
 	int rc;
 
-	if (ext_irq->number_of_interrupts > 0) {
+	if (ext_irq->interrupt_count > 0) {
 		rc = acpi_register_gsi(ext_irq->interrupts[0],
-	                   ext_irq->edge_level, ext_irq->active_high_low);
+	                   ext_irq->triggering, ext_irq->polarity);
 		if (rc < 0)
 			return AE_ERROR;
 		port->irq = rc;
@@ -64,9 +64,9 @@
 {
 	int rc;
 
-	if (irq->number_of_interrupts > 0) {
+	if (irq->interrupt_count > 0) {
 		rc = acpi_register_gsi(irq->interrupts[0],
-	                   irq->edge_level, irq->active_high_low);
+	                   irq->triggering, irq->polarity);
 		if (rc < 0)
 			return AE_ERROR;
 		port->irq = rc;
@@ -83,11 +83,11 @@
 	status = acpi_resource_to_address64(res, &addr);
 	if (ACPI_SUCCESS(status))
 		return acpi_serial_mmio(port, &addr);
-	else if (res->id == ACPI_RSTYPE_IO)
+	else if (res->type == ACPI_RESOURCE_TYPE_IO)
 		return acpi_serial_port(port, &res->data.io);
-	else if (res->id == ACPI_RSTYPE_EXT_IRQ)
+	else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ)
 		return acpi_serial_ext_irq(port, &res->data.extended_irq);
-	else if (res->id == ACPI_RSTYPE_IRQ)
+	else if (res->type == ACPI_RESOURCE_TYPE_IRQ)
 		return acpi_serial_irq(port, &res->data.irq);
 	return AE_OK;
 }
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c
index 06ae8fb..8d8d7a7 100644
--- a/drivers/serial/8250_au1x00.c
+++ b/drivers/serial/8250_au1x00.c
@@ -56,7 +56,6 @@
 #elif defined(CONFIG_SOC_AU1550)
 	PORT(UART0_ADDR, AU1550_UART0_INT),
 	PORT(UART1_ADDR, AU1550_UART1_INT),
-	PORT(UART2_ADDR, AU1550_UART2_INT),
 	PORT(UART3_ADDR, AU1550_UART3_INT),
 #elif defined(CONFIG_SOC_AU1200)
 	PORT(UART0_ADDR, AU1200_UART0_INT),
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 589fb07..94886c0 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -439,6 +439,20 @@
 	return -ENODEV;
 }
 
+static int pci_siig_setup(struct serial_private *priv,
+			  struct pciserial_board *board,
+			  struct uart_port *port, int idx)
+{
+	unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
+
+	if (idx > 3) {
+		bar = 4;
+		offset = (idx - 4) * 8;
+	}
+
+	return setup_port(priv, port, bar, offset, 0);
+}
+
 /*
  * Timedia has an explosion of boards, and to avoid the PCI table from
  * growing *huge*, we use this function to collapse some 70 entries
@@ -748,7 +762,7 @@
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_siig_init,
-		.setup		= pci_default_setup,
+		.setup		= pci_siig_setup,
 	},
 	/*
 	 * Titan cards
@@ -940,6 +954,7 @@
 	pbn_b2_bt_2_921600,
 	pbn_b2_bt_4_921600,
 
+	pbn_b3_2_115200,
 	pbn_b3_4_115200,
 	pbn_b3_8_115200,
 
@@ -1311,6 +1326,12 @@
 		.uart_offset	= 8,
 	},
 
+	[pbn_b3_2_115200] = {
+		.flags		= FL_BASE3,
+		.num_ports	= 2,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
 	[pbn_b3_4_115200] = {
 		.flags		= FL_BASE3,
 		.num_ports	= 4,
@@ -1861,6 +1882,10 @@
 		PCI_SUBVENDOR_ID_CONNECT_TECH,
 		PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
 		pbn_b0_4_1843200 },
+	{	PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+		PCI_VENDOR_ID_AFAVLAB,
+		PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
+		pbn_b0_4_1152000 },
 	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
 		PCI_SUBVENDOR_ID_CONNECT_TECH,
 		PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
@@ -2134,6 +2159,15 @@
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b0_bt_4_921600 },
+	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b0_bt_8_921600 },
+	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b0_bt_8_921600 },
+	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b0_bt_8_921600 },
 
 	/*
 	 * Computone devices submitted by Doug McNash dmcnash@computone.com
@@ -2272,6 +2306,9 @@
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_nec_nile4 },
 
+	{	PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b3_2_115200 },
 	{	PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b3_4_115200 },
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 5e7199f..0f4361c 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -23,7 +23,7 @@
 	  work.)
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called serial.
+	  module will be called 8250.
 	  [WARNING: Do not compile this driver as a module if you are using
 	  non-standard serial ports, since the configuration information will
 	  be lost when the driver is unloaded.  This limitation may be lifted
@@ -98,6 +98,7 @@
 config SERIAL_8250_RUNTIME_UARTS
 	int "Number of 8250/16550 serial ports to register at runtime"
 	depends on SERIAL_8250
+	range 0 SERIAL_8250_NR_UARTS
 	default "4"
 	help
 	  Set this to the maximum number of serial ports you want
@@ -301,7 +302,7 @@
 	depends on SERIAL_AT91=y
 	help
 	  Say Y here if you wish to have the five internal AT91RM9200 UARTs
-	  appear as /dev/ttyAT0-4 (major 240, minor 0-4) instead of the
+	  appear as /dev/ttyAT0-4 (major 204, minor 154-158) instead of the
 	  normal /dev/ttyS0-4 (major 4, minor 64-68). This is necessary if
 	  you also want other UARTs, such as external 8250/16C550 compatible
 	  UARTs.
@@ -892,20 +893,20 @@
 	  a console on a serial port, say Y.  Otherwise, say N.
 
 config SERIAL_JSM
-        tristate "Digi International NEO PCI Support"
-	depends on PCI && BROKEN
-        select SERIAL_CORE
-        help
-          This is a driver for Digi International's Neo series
-          of cards which provide multiple serial ports. You would need
-          something like this to connect more than two modems to your Linux
-          box, for instance in order to become a dial-in server. This driver
-          supports PCI boards only.
-          If you have a card like this, say Y here and read the file
-          <file:Documentation/jsm.txt>.
+	tristate "Digi International NEO PCI Support"
+	depends on PCI
+	select SERIAL_CORE
+	help
+	  This is a driver for Digi International's Neo series
+	  of cards which provide multiple serial ports. You would need
+	  something like this to connect more than two modems to your Linux
+	  box, for instance in order to become a dial-in server. This driver
+	  supports PCI boards only.
+	  If you have a card like this, say Y here and read the file
+	  <file:Documentation/jsm.txt>.
 
-          To compile this driver as a module, choose M here: the
-          module will be called jsm.
+	  To compile this driver as a module, choose M here: the
+	  module will be called jsm.
 
 config SERIAL_SGI_IOC4
 	tristate "SGI IOC4 controller serial support"
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 3490022..321a3b3 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -561,12 +561,12 @@
 		.port	= {
 			.membase	= (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
 			.mapbase	= INTEGRATOR_UART0_BASE,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= IRQ_UARTINT0,
 			.uartclk	= 14745600,
 			.fifosize	= 16,
 			.ops		= &amba_pl010_pops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.dtr_mask	= 1 << 5,
@@ -576,12 +576,12 @@
 		.port	= {
 			.membase	= (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
 			.mapbase	= INTEGRATOR_UART1_BASE,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= IRQ_UARTINT1,
 			.uartclk	= 14745600,
 			.fifosize	= 16,
 			.ops		= &amba_pl010_pops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 		.dtr_mask	= 1 << 7,
diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c
index 0e20606..2113feb 100644
--- a/drivers/serial/at91_serial.c
+++ b/drivers/serial/at91_serial.c
@@ -222,8 +222,6 @@
 	while (status & (AT91_US_RXRDY)) {
 		ch = UART_GET_CHAR(port);
 
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			goto ignore_char;
 		port->icount.rx++;
 
 		flg = TTY_NORMAL;
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index ceb5d7f..344022f 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -892,7 +892,7 @@
 	int ret = 0;
 
 	switch (up->port.iotype) {
-	case SERIAL_IO_MEM:
+	case UPIO_MEM:
 		if (up->port.mapbase) {
 			*res = request_mem_region(up->port.mapbase, size, "serial");
 			if (!*res)
@@ -900,8 +900,8 @@
 		}
 		break;
 
-	case SERIAL_IO_HUB6:
-	case SERIAL_IO_PORT:
+	case UPIO_HUB6:
+	case UPIO_PORT:
 		*res = request_region(up->port.iobase, size, "serial");
 		if (!*res)
 			ret = -EBUSY;
@@ -919,7 +919,7 @@
 	size <<= up->port.regshift;
 
 	switch (up->port.iotype) {
-	case SERIAL_IO_MEM:
+	case UPIO_MEM:
 		if (up->port.mapbase) {
 			/*
 			 * Unmap the area.
@@ -935,8 +935,8 @@
 		}
 		break;
 
-	case SERIAL_IO_HUB6:
-	case SERIAL_IO_PORT:
+	case UPIO_HUB6:
+	case UPIO_PORT:
 		start = up->port.iobase;
 
 		if (size)
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 8ef9994..ce7b2e4 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -410,7 +410,7 @@
 		.fifosize	= 16,
 		.ops		= &clps711x_pops,
 		.line		= 0,
-		.flags		= ASYNC_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF,
 	},
 	{
 		.iobase		= SYSCON2,
@@ -419,7 +419,7 @@
 		.fifosize	= 16,
 		.ops		= &clps711x_pops,
 		.line		= 1,
-		.flags		= ASYNC_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF,
 	}
 };
 
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 16af562..b7bf4c6 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -252,12 +252,9 @@
 		/* If we have not enough room in tty flip buffer, then we try
 		 * later, which will be the next rx-interrupt or a timeout
 		 */
-		if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
-			tty->flip.work.func((void *)tty);
-			if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
-				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-				return;
-			}
+		if(tty_buffer_request_room(tty, i) < i) {
+			printk(KERN_WARNING "No room in flip buffer\n");
+			return;
 		}
 
 		/* get pointer */
@@ -276,9 +273,7 @@
 				continue;
 
 		      error_return:
-			*tty->flip.char_buf_ptr++ = ch;
-			*tty->flip.flag_buf_ptr++ = flg;
-			tty->flip.count++;
+			tty_insert_flip_char(tty, ch, flg);
 
 		}		/* End while (i--) */
 
@@ -908,7 +903,7 @@
 		.port = {
 			.irq		= SMC1_IRQ,
 			.ops		= &cpm_uart_pops,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.flags = FLAG_SMC,
@@ -922,7 +917,7 @@
 		.port = {
 			.irq		= SMC2_IRQ,
 			.ops		= &cpm_uart_pops,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.flags = FLAG_SMC,
@@ -939,7 +934,7 @@
 		.port = {
 			.irq		= SCC1_IRQ,
 			.ops		= &cpm_uart_pops,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
@@ -953,7 +948,7 @@
 		.port = {
 			.irq		= SCC2_IRQ,
 			.ops		= &cpm_uart_pops,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
@@ -967,7 +962,7 @@
 		.port = {
 			.irq		= SCC3_IRQ,
 			.ops		= &cpm_uart_pops,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
@@ -981,7 +976,7 @@
 		.port = {
 			.irq		= SCC4_IRQ,
 			.ops		= &cpm_uart_pops,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index a64ba26..ba5541d 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -262,6 +262,7 @@
 		}
 		tty_insert_flip_char(tty, ch, flag);
 	      ignore_char:
+			;
 	} while (status & DZ_DVAL);
 
 	if (tty)
@@ -650,7 +651,7 @@
 	for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) {
 		spin_lock_init(&dport->port.lock);
 		dport->port.membase	= (char *) base;
-		dport->port.iotype	= SERIAL_IO_PORT;
+		dport->port.iotype	= UPIO_PORT;
 		dport->port.irq		= dec_interrupt[DEC_IRQ_DZ11];
 		dport->port.line	= i;
 		dport->port.fifosize	= 1;
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 587cc6a..4d53fb5 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -402,10 +402,10 @@
 			     DRIVER_NAME, sport);
 	if (retval) goto error_out2;
 
-	retval = request_irq(sport->rtsirq, imx_rtsint, 0,
+	retval = request_irq(sport->rtsirq, imx_rtsint,
+			     SA_TRIGGER_FALLING | SA_TRIGGER_RISING,
 			     DRIVER_NAME, sport);
 	if (retval) goto error_out3;
-	set_irq_type(sport->rtsirq, IRQT_BOTHEDGE);
 
 	/*
 	 * Finally, clear and enable interrupts
@@ -668,13 +668,13 @@
 	.rtsirq = UART1_MINT_RTS,
 	.port	= {
 		.type		= PORT_IMX,
-		.iotype		= SERIAL_IO_MEM,
+		.iotype		= UPIO_MEM,
 		.membase	= (void *)IMX_UART1_BASE,
 		.mapbase	= IMX_UART1_BASE, /* FIXME */
 		.irq		= UART1_MINT_RX,
 		.uartclk	= 16000000,
 		.fifosize	= 8,
-		.flags		= ASYNC_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF,
 		.ops		= &imx_pops,
 		.line		= 0,
 	},
@@ -684,13 +684,13 @@
 	.rtsirq = UART2_MINT_RTS,
 	.port	= {
 		.type		= PORT_IMX,
-		.iotype		= SERIAL_IO_MEM,
+		.iotype		= UPIO_MEM,
 		.membase	= (void *)IMX_UART2_BASE,
 		.mapbase	= IMX_UART2_BASE, /* FIXME */
 		.irq		= UART2_MINT_RX,
 		.uartclk	= 16000000,
 		.fifosize	= 8,
-		.flags		= ASYNC_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF,
 		.ops		= &imx_pops,
 		.line		= 1,
 	},
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 1d85533..f3763d2 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -1717,11 +1717,9 @@
 	}
 
 	if (cflag & CRTSCTS) {
-		info->flags |= ASYNC_CTS_FLOW;
 		port->ip_sscr |= IOC4_SSCR_HFC_EN;
 	}
 	else {
-		info->flags &= ~ASYNC_CTS_FLOW;
 		port->ip_sscr &= ~IOC4_SSCR_HFC_EN;
 	}
 	writel(port->ip_sscr, &port->ip_serial_regs->sscr);
@@ -1760,18 +1758,6 @@
 
 	info = the_port->info;
 
-	if (info->tty) {
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			info->tty->alt_speed = 57600;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			info->tty->alt_speed = 115200;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			info->tty->alt_speed = 230400;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			info->tty->alt_speed = 460800;
-	}
 	local_open(port);
 
 	/* set the speed of the serial port */
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index 66f117d..419dd3c 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -215,7 +215,7 @@
 	/* Lower and upper byte of baud rate generator divisor.  */
 	write_zsreg(channel, R12, regs[R12]);
 	write_zsreg(channel, R13, regs[R13]);
-	
+
 	/* Now rewrite R14, with BRENAB (if set).  */
 	write_zsreg(channel, R14, regs[R14]);
 
@@ -571,7 +571,7 @@
 	else
 		clear_bits |= DTR;
 
-	/* NOTE: Not subject to 'transmitter active' rule.  */ 
+	/* NOTE: Not subject to 'transmitter active' rule.  */
 	up->curregs[R5] |= set_bits;
 	up->curregs[R5] &= ~clear_bits;
 	write_zsreg(channel, R5, up->curregs[R5]);
@@ -654,7 +654,7 @@
 	if (new_reg != up->curregs[R15]) {
 		up->curregs[R15] = new_reg;
 
-		/* NOTE: Not subject to 'transmitter active' rule.  */ 
+		/* NOTE: Not subject to 'transmitter active' rule.  */
 		write_zsreg(channel, R15, up->curregs[R15]);
 	}
 }
@@ -680,7 +680,7 @@
 	if (new_reg != up->curregs[R5]) {
 		up->curregs[R5] = new_reg;
 
-		/* NOTE: Not subject to 'transmitter active' rule.  */ 
+		/* NOTE: Not subject to 'transmitter active' rule.  */
 		write_zsreg(channel, R5, up->curregs[R5]);
 	}
 
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index 1875319..dfc1e86 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -380,7 +380,6 @@
 extern struct	uart_driver jsm_uart_driver;
 extern struct	board_ops jsm_neo_ops;
 extern int	jsm_debug;
-extern int	jsm_rawreadok;
 
 /*************************************************************************
  *
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index 7e56c78..b1b66e7 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -49,11 +49,8 @@
 };
 
 int jsm_debug;
-int jsm_rawreadok;
 module_param(jsm_debug, int, 0);
-module_param(jsm_rawreadok, int, 0);
 MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
-MODULE_PARM_DESC(jsm_rawreadok, "Bypass flip buffers on input");
 
 static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index 6f22b42..87e4e2c 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -965,56 +965,47 @@
 			baud = ch->ch_custom_speed;
 			if (ch->ch_flags & CH_BAUD0)
 				ch->ch_flags &= ~(CH_BAUD0);
-		} else {
-			int iindex = 0;
-			int jindex = 0;
+	} else {
+		int i;
+		unsigned int cflag;
+		static struct {
+			unsigned int rate;
+			unsigned int cflag;
+		} baud_rates[] = {
+			{ 921600, B921600 },
+			{ 460800, B460800 },
+			{ 230400, B230400 },
+			{ 115200, B115200 },
+			{  57600, B57600  },
+			{  38400, B38400  },
+			{  19200, B19200  },
+			{   9600, B9600   },
+			{   4800, B4800   },
+			{   2400, B2400   },
+			{   1200, B1200   },
+			{    600, B600    },
+			{    300, B300    },
+			{    200, B200    },
+			{    150, B150    },
+			{    134, B134    },
+			{    110, B110    },
+			{     75, B75     },
+			{     50, B50     },
+		};
 
-			const u64 bauds[4][16] = {
-				{
-					0,	50,	75,	110,
-					134,	150,	200,	300,
-					600,	1200,	1800,	2400,
-					4800,	9600,	19200,	38400 },
-				{
-					0,	57600,	115200, 230400,
-					460800, 150,	200,	921600,
-					600,	1200,	1800,	2400,
-					4800,	9600,	19200,	38400 },
-				{
-					0,	57600,	76800, 115200,
-					131657, 153600, 230400, 460800,
-					921600, 1200,	1800,	2400,
-					4800,	9600,	19200,	38400 },
-				{
-					0,	57600,	115200, 230400,
-					460800, 150,	200,	921600,
-					600,	1200,	1800,	2400,
-					4800,	9600,	19200,	38400 }
-			};
-
-			baud = C_BAUD(ch->uart_port.info->tty) & 0xff;
-
-			if (ch->ch_c_cflag & CBAUDEX)
-				iindex = 1;
-
-			jindex = baud;
-
-			if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16))
-				baud = bauds[iindex][jindex];
-			else {
-				jsm_printk(IOCTL, DEBUG, &ch->ch_bd->pci_dev,
-					"baud indices were out of range (%d)(%d)",
-				iindex, jindex);
-				baud = 0;
+		cflag = C_BAUD(ch->uart_port.info->tty);
+		baud = 9600;
+		for (i = 0; i < ARRAY_SIZE(baud_rates); i++) {
+			if (baud_rates[i].cflag == cflag) {
+				baud = baud_rates[i].rate;
+				break;
 			}
-
-			if (baud == 0)
-				baud = 9600;
-
-			if (ch->ch_flags & CH_BAUD0)
-				ch->ch_flags &= ~(CH_BAUD0);
 		}
 
+		if (ch->ch_flags & CH_BAUD0)
+			ch->ch_flags &= ~(CH_BAUD0);
+	}
+
 	if (ch->ch_c_cflag & PARENB)
 		lcr |= UART_LCR_PARITY;
 
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 6fa0d62..4d48b62 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -20,8 +20,10 @@
  *
  * Contact Information:
  * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
- *
+ * Ananda Venkatarman <mansarov@us.ibm.com>
+ * Modifications:
+ * 01/19/06:	changed jsm_input routine to use the dynamically allocated
+ *		tty_buffer changes. Contributors: Scott Kilau and Ananda V.
  ***********************************************************************/
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -497,16 +499,15 @@
 {
 	struct jsm_board *bd;
 	struct tty_struct *tp;
+	struct tty_ldisc *ld;
 	u32 rmask;
 	u16 head;
 	u16 tail;
 	int data_len;
 	unsigned long lock_flags;
-	int flip_len;
+	int flip_len = 0;
 	int len = 0;
 	int n = 0;
-	char *buf = NULL;
-	char *buf2 = NULL;
 	int s = 0;
 	int i = 0;
 
@@ -574,56 +575,50 @@
 
 	/*
 	 * If the rxbuf is empty and we are not throttled, put as much
-	 * as we can directly into the linux TTY flip buffer.
-	 * The jsm_rawreadok case takes advantage of carnal knowledge that
-	 * the char_buf and the flag_buf are next to each other and
-	 * are each of (2 * TTY_FLIPBUF_SIZE) size.
+	 * as we can directly into the linux TTY buffer.
 	 *
-	 * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf
-	 *actually still uses the flag buffer, so you can't
-	 *use it for input data
 	 */
-	if (jsm_rawreadok) {
-		if (tp->real_raw)
-			flip_len = MYFLIPLEN;
-		else
-			flip_len = 2 * TTY_FLIPBUF_SIZE;
-	} else
-		flip_len = TTY_FLIPBUF_SIZE - tp->flip.count;
+	flip_len = TTY_FLIPBUF_SIZE;
 
 	len = min(data_len, flip_len);
 	len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt);
+	ld = tty_ldisc_ref(tp);
+
+	/*
+	 * If the DONT_FLIP flag is on, don't flush our buffer, and act
+	 * like the ld doesn't have any space to put the data right now.
+	 */
+	if (test_bit(TTY_DONT_FLIP, &tp->flags))
+		len = 0;
+
+	/*
+	 * If we were unable to get a reference to the ld,
+	 * don't flush our buffer, and act like the ld doesn't
+	 * have any space to put the data right now.
+	 */
+	if (!ld) {
+		len = 0;
+	} else {
+		/*
+		 * If ld doesn't have a pointer to a receive_buf function,
+		 * flush the data, then act like the ld doesn't have any
+		 * space to put the data right now.
+		 */
+		if (!ld->receive_buf) {
+				ch->ch_r_head = ch->ch_r_tail;
+				len = 0;
+		}
+	}
 
 	if (len <= 0) {
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
 		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
+		if (ld)
+			tty_ldisc_deref(ld);
 		return;
 	}
 
-	/*
-	 * If we're bypassing flip buffers on rx, we can blast it
-	 * right into the beginning of the buffer.
-	 */
-	if (jsm_rawreadok) {
-		if (tp->real_raw) {
-			if (ch->ch_flags & CH_FLIPBUF_IN_USE) {
-				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
-					"JSM - FLIPBUF in use. delaying input\n");
-				spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-				return;
-			}
-			ch->ch_flags |= CH_FLIPBUF_IN_USE;
-			buf = ch->ch_bd->flipbuf;
-			buf2 = NULL;
-		} else {
-			buf = tp->flip.char_buf;
-			buf2 = tp->flip.flag_buf;
-		}
-	} else {
-		buf = tp->flip.char_buf_ptr;
-		buf2 = tp->flip.flag_buf_ptr;
-	}
-
+	len = tty_buffer_request_room(tp, len);
 	n = len;
 
 	/*
@@ -638,121 +633,47 @@
 		if (s <= 0)
 			break;
 
-		memcpy(buf, ch->ch_rqueue + tail, s);
+			/*
+			 * If conditions are such that ld needs to see all
+			 * UART errors, we will have to walk each character
+			 * and error byte and send them to the buffer one at
+			 * a time.
+			 */
 
-		/* buf2 is only set when port isn't raw */
-		if (buf2)
-			memcpy(buf2, ch->ch_equeue + tail, s);
-
+		if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
+			for (i = 0; i < s; i++) {
+				/*
+				 * Give the Linux ld the flags in the
+				 * format it likes.
+				 */
+				if (*(ch->ch_equeue +tail +i) & UART_LSR_BI)
+					tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i),  TTY_BREAK);
+				else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE)
+					tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_PARITY);
+				else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE)
+					tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME);
+				else
+				tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
+			}
+		} else {
+			tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ;
+		}
 		tail += s;
-		buf += s;
-		if (buf2)
-			buf2 += s;
 		n -= s;
 		/* Flip queue if needed */
 		tail &= rmask;
 	}
 
-	/*
-	 * In high performance mode, we don't have to update
-	 * flag_buf or any of the counts or pointers into flip buf.
-	 */
-	if (!jsm_rawreadok) {
-		if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
-			for (i = 0; i < len; i++) {
-				/*
-				 * Give the Linux ld the flags in the
-				 * format it likes.
-				 */
-				if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
-					tp->flip.flag_buf_ptr[i] = TTY_BREAK;
-				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
-					tp->flip.flag_buf_ptr[i] = TTY_PARITY;
-				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
-					tp->flip.flag_buf_ptr[i] = TTY_FRAME;
-				else
-					tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
-			}
-		} else {
-			memset(tp->flip.flag_buf_ptr, 0, len);
-		}
+	ch->ch_r_tail = tail & rmask;
+	ch->ch_e_tail = tail & rmask;
+	jsm_check_queue_flow_control(ch);
+	spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
 
-		tp->flip.char_buf_ptr += len;
-		tp->flip.flag_buf_ptr += len;
-		tp->flip.count += len;
-	}
-	else if (!tp->real_raw) {
-		if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
-			for (i = 0; i < len; i++) {
-				/*
-				 * Give the Linux ld the flags in the
-				 * format it likes.
-				 */
-				if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
-					tp->flip.flag_buf_ptr[i] = TTY_BREAK;
-				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
-					tp->flip.flag_buf_ptr[i] = TTY_PARITY;
-				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
-					tp->flip.flag_buf_ptr[i] = TTY_FRAME;
-				else
-					tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
-			}
-		} else
-			memset(tp->flip.flag_buf, 0, len);
-	}
+	/* Tell the tty layer its okay to "eat" the data now */
+	tty_flip_buffer_push(tp);
 
-	/*
-	 * If we're doing raw reads, jam it right into the
-	 * line disc bypassing the flip buffers.
-	 */
-	if (jsm_rawreadok) {
-		if (tp->real_raw) {
-			ch->ch_r_tail = tail & rmask;
-			ch->ch_e_tail = tail & rmask;
-
-			jsm_check_queue_flow_control(ch);
-
-			/* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
-
-			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
-			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
-				"jsm_input. %d real_raw len:%d calling receive_buf for board %d\n",
-				__LINE__, len, ch->ch_bd->boardnum);
-			tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
-
-			/* Allow use of channel flip buffer again */
-			spin_lock_irqsave(&ch->ch_lock, lock_flags);
-			ch->ch_flags &= ~CH_FLIPBUF_IN_USE;
-			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
-		} else {
-			ch->ch_r_tail = tail & rmask;
-			ch->ch_e_tail = tail & rmask;
-
-			jsm_check_queue_flow_control(ch);
-
-			/* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
-			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
-			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
-				"jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n",
-				__LINE__, len, ch->ch_bd->boardnum);
-
-			tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len);
-		}
-	} else {
-		ch->ch_r_tail = tail & rmask;
-		ch->ch_e_tail = tail & rmask;
-
-		jsm_check_queue_flow_control(ch);
-
-		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
-		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
-			"jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__);
-		tty_schedule_flip(tp);
-	}
+	if (ld)
+		tty_ldisc_deref(ld);
 
 	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
 }
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index b48066a..242a041 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -80,7 +80,7 @@
 #include <asm/serial.h>
 
 /* Standard COM flags */
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
 
 /*
  * SERIAL_PORT_DFNS tells us about built-in ports that have no
diff --git a/drivers/serial/m32r_sio.h b/drivers/serial/m32r_sio.h
index 07d0dd8..7c3ec24 100644
--- a/drivers/serial/m32r_sio.h
+++ b/drivers/serial/m32r_sio.h
@@ -37,7 +37,7 @@
 	unsigned int irq;
 	unsigned int flags;
 	unsigned char io_type;
-	unsigned char *iomem_base;
+	unsigned char __iomem *iomem_base;
 	unsigned short iomem_reg_shift;
 };
 
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index d957a3a..8cbbb95 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -57,20 +57,16 @@
  *	keep going.  Perhaps one day the cflag settings for the
  *	console can be used instead.
  */
-#if defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
-    defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
-#define	CONSOLE_BAUD_RATE	19200
-#define	DEFAULT_CBAUD		B19200
-#endif
-
 #if defined(CONFIG_HW_FEITH)
 #define	CONSOLE_BAUD_RATE	38400
 #define	DEFAULT_CBAUD		B38400
-#endif
-
-#if defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB)
+#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB)
 #define CONSOLE_BAUD_RATE 	115200
 #define DEFAULT_CBAUD		B115200
+#elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
+      defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
+#define	CONSOLE_BAUD_RATE	19200
+#define	DEFAULT_CBAUD		B19200
 #endif
 
 #ifndef CONSOLE_BAUD_RATE
@@ -350,8 +346,7 @@
 		}
 		tty_insert_flip_char(tty, ch, flag);
 	}
-
-	schedule_work(&tty->flip.work);
+	tty_schedule_flip(tty);
 	return;
 }
 
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 4e49168..868eaf4 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -462,7 +462,7 @@
 		port->mapbase	= dev->hpa.start + MUX_OFFSET +
 						(i * MUX_LINE_OFFSET);
 		port->membase	= ioremap(port->mapbase, MUX_LINE_OFFSET);
-		port->iotype	= SERIAL_IO_MEM;
+		port->iotype	= UPIO_MEM;
 		port->type	= PORT_MUX;
 		port->irq	= NO_IRQ;
 		port->uartclk	= 0;
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 4e03a87..9b7ed58 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -1492,7 +1492,7 @@
 	/*
 	 * Init remaining bits of "port" structure
 	 */
-	uap->port.iotype = SERIAL_IO_MEM;
+	uap->port.iotype = UPIO_MEM;
 	uap->port.irq = np->intrs[0].line;
 	uap->port.uartclk = ZS_CLOCK;
 	uap->port.fifosize = 1;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index eb4883e..7410e09 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -161,7 +161,11 @@
 
 /* we can support 3 uarts, but not always use them */
 
+#ifdef CONFIG_CPU_S3C2400
+#define NR_PORTS (2)
+#else
 #define NR_PORTS (3)
+#endif
 
 /* port irq numbers */
 
@@ -1060,7 +1064,7 @@
 	dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
 
 	port->mapbase	= res->start;
-	port->membase	= S3C24XX_VA_UART + (res->start - S3C2410_PA_UART);
+	port->membase	= S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
 	port->irq	= platform_get_irq(platdev, 0);
 
 	ourport->clk	= clk_get(&platdev->dev, "uart");
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 1bd9316..2c00b86 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -628,7 +628,7 @@
 		sa1100_ports[i].port.ops       = &sa1100_pops;
 		sa1100_ports[i].port.fifosize  = 8;
 		sa1100_ports[i].port.line      = i;
-		sa1100_ports[i].port.iotype    = SERIAL_IO_MEM;
+		sa1100_ports[i].port.iotype    = UPIO_MEM;
 		init_timer(&sa1100_ports[i].timer);
 		sa1100_ports[i].timer.function = sa1100_timeout;
 		sa1100_ports[i].timer.data     = (unsigned long)&sa1100_ports[i];
@@ -665,21 +665,21 @@
 		sa1100_ports[idx].port.membase = (void __iomem *)&Ser1UTCR0;
 		sa1100_ports[idx].port.mapbase = _Ser1UTCR0;
 		sa1100_ports[idx].port.irq     = IRQ_Ser1UART;
-		sa1100_ports[idx].port.flags   = ASYNC_BOOT_AUTOCONF;
+		sa1100_ports[idx].port.flags   = UPF_BOOT_AUTOCONF;
 		break;
 
 	case 2:
 		sa1100_ports[idx].port.membase = (void __iomem *)&Ser2UTCR0;
 		sa1100_ports[idx].port.mapbase = _Ser2UTCR0;
 		sa1100_ports[idx].port.irq     = IRQ_Ser2ICP;
-		sa1100_ports[idx].port.flags   = ASYNC_BOOT_AUTOCONF;
+		sa1100_ports[idx].port.flags   = UPF_BOOT_AUTOCONF;
 		break;
 
 	case 3:
 		sa1100_ports[idx].port.membase = (void __iomem *)&Ser3UTCR0;
 		sa1100_ports[idx].port.mapbase = _Ser3UTCR0;
 		sa1100_ports[idx].port.irq     = IRQ_Ser3UART;
-		sa1100_ports[idx].port.flags   = ASYNC_BOOT_AUTOCONF;
+		sa1100_ports[idx].port.flags   = UPF_BOOT_AUTOCONF;
 		break;
 
 	default:
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 9437704..95fb493 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -332,7 +332,7 @@
 		   struct termios *old, unsigned int min, unsigned int max)
 {
 	unsigned int try, baud, altbaud = 38400;
-	unsigned int flags = port->flags & UPF_SPD_MASK;
+	upf_t flags = port->flags & UPF_SPD_MASK;
 
 	if (flags == UPF_SPD_HI)
 		altbaud = 57600;
@@ -615,8 +615,9 @@
 	struct serial_struct new_serial;
 	struct uart_port *port = state->port;
 	unsigned long new_port;
-	unsigned int change_irq, change_port, old_flags, closing_wait;
+	unsigned int change_irq, change_port, closing_wait;
 	unsigned int old_custom_divisor, close_delay;
+	upf_t old_flags, new_flags;
 	int retval = 0;
 
 	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
@@ -655,6 +656,7 @@
 		      new_serial.type != port->type;
 
 	old_flags = port->flags;
+	new_flags = new_serial.flags;
 	old_custom_divisor = port->custom_divisor;
 
 	if (!capable(CAP_SYS_ADMIN)) {
@@ -664,10 +666,10 @@
 		    (close_delay != state->close_delay) ||
 		    (closing_wait != state->closing_wait) ||
 		    (new_serial.xmit_fifo_size != port->fifosize) ||
-		    (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0))
+		    (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
 			goto exit;
 		port->flags = ((port->flags & ~UPF_USR_MASK) |
-			       (new_serial.flags & UPF_USR_MASK));
+			       (new_flags & UPF_USR_MASK));
 		port->custom_divisor = new_serial.custom_divisor;
 		goto check_and_exit;
 	}
@@ -764,7 +766,7 @@
 	port->irq              = new_serial.irq;
 	port->uartclk          = new_serial.baud_base * 16;
 	port->flags            = (port->flags & ~UPF_CHANGE_MASK) |
-				 (new_serial.flags & UPF_CHANGE_MASK);
+				 (new_flags & UPF_CHANGE_MASK);
 	port->custom_divisor   = new_serial.custom_divisor;
 	state->close_delay     = close_delay;
 	state->closing_wait    = closing_wait;
@@ -1870,7 +1872,7 @@
 	mutex_lock(&state->mutex);
 
 	if (state->info && state->info->flags & UIF_INITIALIZED) {
-		struct uart_ops *ops = port->ops;
+		const struct uart_ops *ops = port->ops;
 
 		spin_lock_irq(&port->lock);
 		ops->stop_tx(port);
@@ -1932,7 +1934,7 @@
 	}
 
 	if (state->info && state->info->flags & UIF_INITIALIZED) {
-		struct uart_ops *ops = port->ops;
+		const struct uart_ops *ops = port->ops;
 		int ret;
 
 		ops->set_mctrl(port, 0);
@@ -2235,7 +2237,7 @@
 	 * If this port is a console, then the spinlock is already
 	 * initialised.
 	 */
-	if (!uart_console(port))
+	if (!(uart_console(port) && (port->cons->flags & CON_ENABLED)))
 		spin_lock_init(&port->lock);
 
 	uart_configure_port(drv, state, port);
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index d4a1f0e..04186ea 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -501,12 +501,12 @@
 		.port = {
 			.membase	= (void*) io_p2v (UART1_PHYS),
 			.mapbase	= UART1_PHYS,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= IRQ_UART1INTR,
 			.uartclk	= 14745600/2,
 			.fifosize	= 16,
 			.ops		= &lh7a40x_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 	},
@@ -514,12 +514,12 @@
 		.port = {
 			.membase	= (void*) io_p2v (UART2_PHYS),
 			.mapbase	= UART2_PHYS,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= IRQ_UART2INTR,
 			.uartclk	= 14745600/2,
 			.fifosize	= 16,
 			.ops		= &lh7a40x_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 	},
@@ -527,12 +527,12 @@
 		.port = {
 			.membase	= (void*) io_p2v (UART3_PHYS),
 			.mapbase	= UART3_PHYS,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= IRQ_UART3INTR,
 			.uartclk	= 14745600/2,
 			.fifosize	= 16,
 			.ops		= &lh7a40x_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 2,
 		},
 	},
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index a9e0707..44f6bf7 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -42,6 +42,7 @@
 #include <linux/delay.h>
 #include <linux/console.h>
 #include <linux/bitops.h>
+#include <linux/generic_serial.h>
 
 #ifdef CONFIG_CPU_FREQ
 #include <linux/notifier.h>
@@ -53,7 +54,9 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#include <linux/generic_serial.h>
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+#include <asm/clock.h>
+#endif
 
 #ifdef CONFIG_SH_STANDARD_BIOS
 #include <asm/sh_bios.h>
@@ -86,9 +89,11 @@
 static int sci_request_irq(struct sci_port *port);
 static void sci_free_irq(struct sci_port *port);
 
-static struct sci_port sci_ports[SCI_NPORTS];
+static struct sci_port sci_ports[];
 static struct uart_driver sci_uart_driver;
 
+#define SCI_NPORTS sci_uart_driver.nr
+
 #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
 
 static void handle_error(struct uart_port *port)
@@ -168,7 +173,7 @@
 	int usegdb=0;
 
 #ifdef CONFIG_SH_STANDARD_BIOS
-    	/* This call only does a trap the first time it is
+	/* This call only does a trap the first time it is
 	 * called, and so is safe to do here unconditionally
 	 */
 	usegdb |= sh_bios_in_gdb_mode();
@@ -324,47 +329,46 @@
 	/* tx mark output*/
 	H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx;
 }
-#else
-static void sci_init_pins_sci(struct uart_port *port, unsigned int cflag)
-{
-}
 #endif
 #endif
 
 #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF)
-#if defined(CONFIG_CPU_SH3)
-/* For SH7705, SH7707, SH7709, SH7709A, SH7729, SH7300*/
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+/* SH7300 doesn't use RTS/CTS */
+static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+{
+	sci_out(port, SCFCR, 0);
+}
+#elif defined(CONFIG_CPU_SH3)
+/* For SH7705, SH7707, SH7709, SH7709A, SH7729 */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 {
 	unsigned int fcr_val = 0;
-#if !defined(CONFIG_CPU_SUBTYPE_SH7300) /* SH7300 doesn't use RTS/CTS */
-	{
-		unsigned short data;
+	unsigned short data;
 
-		/* We need to set SCPCR to enable RTS/CTS */
-		data = ctrl_inw(SCPCR);
-		/* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
-		ctrl_outw(data&0x0fcf, SCPCR);
-	}
+	/* We need to set SCPCR to enable RTS/CTS */
+	data = ctrl_inw(SCPCR);
+	/* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
+	ctrl_outw(data & 0x0fcf, SCPCR);
+
 	if (cflag & CRTSCTS)
 		fcr_val |= SCFCR_MCE;
 	else {
-		unsigned short data;
-
 		/* We need to set SCPCR to enable RTS/CTS */
 		data = ctrl_inw(SCPCR);
 		/* Clear out SCP7MD1,0, SCP4MD1,0,
 		   Set SCP6MD1,0 = {01} (output)  */
-		ctrl_outw((data&0x0fcf)|0x1000, SCPCR);
+		ctrl_outw((data & 0x0fcf) | 0x1000, SCPCR);
 
 		data = ctrl_inb(SCPDR);
 		/* Set /RTS2 (bit6) = 0 */
-		ctrl_outb(data&0xbf, SCPDR);
+		ctrl_outb(data & 0xbf, SCPDR);
 	}
-#endif
+
 	sci_out(port, SCFCR, fcr_val);
 }
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
 static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag)
 {
 	unsigned int fcr_val = 0;
@@ -374,7 +378,7 @@
 
 	sci_out(port, SCFCR, fcr_val);
 }
-
+#endif
 #else
 
 /* For SH7750 */
@@ -385,7 +389,11 @@
 	if (cflag & CRTSCTS) {
 		fcr_val |= SCFCR_MCE;
 	} else {
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
+		ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
+#else
 		ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
+#endif
 	}
 	sci_out(port, SCFCR, fcr_val);
 }
@@ -422,7 +430,11 @@
 
 #if !defined(SCI_ONLY)
 	if (port->type == PORT_SCIF) {
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+		txroom = SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f);
+#else
 		txroom = SCIF_TXROOM_MAX - (sci_in(port, SCFDR)>>8);
+#endif
 	} else {
 		txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0;
 	}
@@ -491,7 +503,11 @@
 	while (1) {
 #if !defined(SCI_ONLY)
 		if (port->type == PORT_SCIF) {
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+			count = sci_in(port, SCRFDR) & 0x7f;
+#else
 			count = sci_in(port, SCFDR)&SCIF_RFDC_MASK ;
+#endif
 		} else {
 			count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0;
 		}
@@ -652,7 +668,7 @@
 	struct tty_struct *tty = port->info->tty;
 	struct sci_port *s = &sci_ports[port->line];
 
-	if (!s->break_flag && status & SCxSR_BRK(port))
+	if (!s->break_flag && status & SCxSR_BRK(port)) {
 #if defined(CONFIG_CPU_SH3)
 		/* Debounce break */
 		s->break_flag = 1;
@@ -783,6 +799,7 @@
 	    (phase == CPUFREQ_RESUMECHANGE)){
 		for (i = 0; i < SCI_NPORTS; i++) {
 			struct uart_port *port = &sci_ports[i].port;
+			struct clk *clk;
 
 			/*
 			 * Update the uartclk per-port if frequency has
@@ -795,7 +812,9 @@
 			 *
 			 * Clean this up later..
 			 */
-			port->uartclk = current_cpu_data.module_clock * 16;
+			clk = clk_get("module_clk");
+			port->uartclk = clk_get_rate(clk) * 16;
+			clk_put(clk);
 		}
 
 		printk("%s: got a postchange notification for cpu %d (old %d, new %d)\n",
@@ -1008,15 +1027,20 @@
 	sci_out(port, SCSMR, smr_val);
 
 	switch (baud) {
-		case 0:		t = -1;		break;
-		case 2400:	t = BPS_2400;	break;
-		case 4800:	t = BPS_4800;	break;
-		case 9600:	t = BPS_9600;	break;
-		case 19200:	t = BPS_19200;	break;
-		case 38400:	t = BPS_38400;	break;
-		case 57600:	t = BPS_57600;	break;
-		case 115200:	t = BPS_115200;	break;
-		default:	t = SCBRR_VALUE(baud); break;
+		case 0:
+			t = -1;
+			break;
+		default:
+		{
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+			struct clk *clk = clk_get("module_clk");
+			t = SCBRR_VALUE(baud, clk_get_rate(clk));
+			clk_put(clk);
+#else
+			t = SCBRR_VALUE(baud);
+#endif
+		}
+			break;
 	}
 
 	if (t > 0) {
@@ -1030,7 +1054,9 @@
 		udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
 	}
 
-	s->init_pins(port, termios->c_cflag);
+	if (likely(s->init_pins))
+		s->init_pins(port, termios->c_cflag);
+
 	sci_out(port, SCSCR, SCSCR_INIT(port));
 
 	if ((termios->c_cflag & CREAD) != 0)
@@ -1107,31 +1133,30 @@
 	.verify_port	= sci_verify_port,
 };
 
-static struct sci_port sci_ports[SCI_NPORTS] = {
+static struct sci_port sci_ports[] = {
 #if defined(CONFIG_CPU_SUBTYPE_SH7708)
 	{
 		.port	= {
 			.membase	= (void *)0xfffffe80,
 			.mapbase	= 0xfffffe80,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 25,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCI,
 		.irqs		= SCI_IRQS,
-		.init_pins	= sci_init_pins_sci,
 	},
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705)
 	{
 		.port	= {
 			.membase	= (void *)SCIF0,
 			.mapbase	= SCIF0,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 55,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCIF,
@@ -1142,10 +1167,10 @@
 		.port	= {
 			.membase	= (void *)SCIF2,
 			.mapbase	= SCIF2,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 59,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 		.type		= PORT_SCIF,
@@ -1157,24 +1182,23 @@
 		.port	= {
 			.membase	= (void *)0xfffffe80,
 			.mapbase	= 0xfffffe80,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 25,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCI,
 		.irqs		= SCI_IRQS,
-		.init_pins	= sci_init_pins_sci,
 	},
 	{
 		.port	= {
 			.membase	= (void *)0xa4000150,
 			.mapbase	= 0xa4000150,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 59,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 		.type		= PORT_SCIF,
@@ -1185,10 +1209,10 @@
 		.port	= {
 			.membase	= (void *)0xa4000140,
 			.mapbase	= 0xa4000140,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 55,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 2,
 		},
 		.type		= PORT_IRDA,
@@ -1200,10 +1224,10 @@
 		.port	= {
 			.membase	= (void *)0xA4430000,
 			.mapbase	= 0xA4430000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 25,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCIF,
@@ -1215,25 +1239,25 @@
 		.port	= {
 			.membase	= (void *)0xffe00000,
 			.mapbase	= 0xffe00000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 25,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCIF,
 		.irqs		= SH73180_SCIF_IRQS,
 		.init_pins	= sci_init_pins_scif,
 	},
-#elif defined(CONFIG_SH_RTS7751R2D)
+#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
 	{
 		.port	= {
 			.membase	= (void *)0xffe80000,
 			.mapbase	= 0xffe80000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 43,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCIF,
@@ -1245,24 +1269,23 @@
 		.port	= {
 			.membase	= (void *)0xffe00000,
 			.mapbase	= 0xffe00000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 25,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCI,
 		.irqs		= SCI_IRQS,
-		.init_pins	= sci_init_pins_sci,
 	},
 	{
 		.port	= {
 			.membase	= (void *)0xffe80000,
 			.mapbase	= 0xffe80000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 43,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 		.type		= PORT_SCIF,
@@ -1274,10 +1297,10 @@
 		.port	= {
 			.membase	= (void *)0xfe600000,
 			.mapbase	= 0xfe600000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 55,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCIF,
@@ -1288,10 +1311,10 @@
 		.port	= {
 			.membase	= (void *)0xfe610000,
 			.mapbase	= 0xfe610000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 75,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 		.type		= PORT_SCIF,
@@ -1302,40 +1325,25 @@
 		.port	= {
 			.membase	= (void *)0xfe620000,
 			.mapbase	= 0xfe620000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 79,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 2,
 		},
 		.type		= PORT_SCIF,
 		.irqs		= SH7760_SCIF2_IRQS,
 		.init_pins	= sci_init_pins_scif,
 	},
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-	{
-		.port	= {
-			.membase	= (void *)0xffe80000,
-			.mapbase	= 0xffe80000,
-			.iotype		= SERIAL_IO_MEM,
-			.irq		= 43,
-			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
-			.line		= 0,
-		},
-		.type		= PORT_SCIF,
-		.irqs		= SH4_SCIF_IRQS,
-		.init_pins	= sci_init_pins_scif,
-	},
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 	{
 		.port	= {
 			.membase	= (void *)0xffe00000,
 			.mapbase	= 0xffe00000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 26,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCIF,
@@ -1346,10 +1354,10 @@
 		.port	= {
 			.membase	= (void *)0xffe80000,
 			.mapbase	= 0xffe80000,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 43,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 		.type		= PORT_SCIF,
@@ -1359,10 +1367,10 @@
 #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
 	{
 		.port	= {
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 42,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCIF,
@@ -1374,10 +1382,10 @@
 		.port	= {
 			.membase	= (void *)0x00ffffb0,
 			.mapbase	= 0x00ffffb0,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 54,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCI,
@@ -1388,10 +1396,10 @@
 		.port	= {
 			.membase	= (void *)0x00ffffb8,
 			.mapbase	= 0x00ffffb8,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 58,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 		.type		= PORT_SCI,
@@ -1402,10 +1410,10 @@
 		.port	= {
 			.membase	= (void *)0x00ffffc0,
 			.mapbase	= 0x00ffffc0,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 62,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 2,
 		},
 		.type		= PORT_SCI,
@@ -1417,10 +1425,10 @@
 		.port	= {
 			.membase	= (void *)0x00ffff78,
 			.mapbase	= 0x00ffff78,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 90,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 0,
 		},
 		.type		= PORT_SCI,
@@ -1431,10 +1439,10 @@
 		.port	= {
 			.membase	= (void *)0x00ffff80,
 			.mapbase	= 0x00ffff80,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 94,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 1,
 		},
 		.type		= PORT_SCI,
@@ -1445,16 +1453,88 @@
 		.port	= {
 			.membase	= (void *)0x00ffff88,
 			.mapbase	= 0x00ffff88,
-			.iotype		= SERIAL_IO_MEM,
+			.iotype		= UPIO_MEM,
 			.irq		= 98,
 			.ops		= &sci_uart_ops,
-			.flags		= ASYNC_BOOT_AUTOCONF,
+			.flags		= UPF_BOOT_AUTOCONF,
 			.line		= 2,
 		},
 		.type		= PORT_SCI,
 		.irqs		= H8S_SCI_IRQS2,
 		.init_pins	= sci_init_pins_sci,
 	},
+#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
+	{
+		.port   = {
+			.membase	= (void *)0xff923000,
+			.mapbase	= 0xff923000,
+			.iotype		= UPIO_MEM,
+			.irq		= 61,
+			.ops		= &sci_uart_ops,
+			.flags		= UPF_BOOT_AUTOCONF,
+			.line		= 0,
+		},
+		.type		= PORT_SCIF,
+		.irqs		= SH7770_SCIF0_IRQS,
+		.init_pins	= sci_init_pins_scif,
+	},
+	{
+		.port   = {
+			.membase	= (void *)0xff924000,
+			.mapbase	= 0xff924000,
+			.iotype		= UPIO_MEM,
+			.irq		= 62,
+			.ops		= &sci_uart_ops,
+			.flags		= UPF_BOOT_AUTOCONF,
+			.line		= 1,
+		},
+		.type		= PORT_SCIF,
+		.irqs		= SH7770_SCIF1_IRQS,
+		.init_pins	= sci_init_pins_scif,
+	},
+	{
+		.port   = {
+			.membase	= (void *)0xff925000,
+			.mapbase	= 0xff925000,
+			.iotype		= UPIO_MEM,
+			.irq		= 63,
+			.ops		= &sci_uart_ops,
+			.flags		= UPF_BOOT_AUTOCONF,
+			.line		= 2,
+		},
+		.type		= PORT_SCIF,
+		.irqs		= SH7770_SCIF2_IRQS,
+		.init_pins	= sci_init_pins_scif,
+	},
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+	{
+		.port   = {
+			.membase	= (void *)0xffe00000,
+			.mapbase	= 0xffe00000,
+			.iotype		= UPIO_MEM,
+			.irq		= 43,
+			.ops		= &sci_uart_ops,
+			.flags		= UPF_BOOT_AUTOCONF,
+			.line		= 0,
+		},
+		.type		= PORT_SCIF,
+		.irqs		= SH7780_SCIF0_IRQS,
+		.init_pins	= sci_init_pins_scif,
+	},
+	{
+		.port   = {
+			.membase	= (void *)0xffe10000,
+			.mapbase	= 0xffe10000,
+			.iotype		= UPIO_MEM,
+			.irq		= 79,
+			.ops		= &sci_uart_ops,
+			.flags		= UPF_BOOT_AUTOCONF,
+			.line		= 1,
+		},
+		.type		= PORT_SCIF,
+		.irqs		= SH7780_SCIF1_IRQS,
+		.init_pins	= sci_init_pins_scif,
+	},
 #else
 #error "CPU subtype not defined"
 #endif
@@ -1480,9 +1560,6 @@
 	int flow = 'n';
 	int ret;
 
-	if (co->index >= SCI_NPORTS)
-		co->index = 0;
-
 	serial_console_port = &sci_ports[co->index];
 	port = &serial_console_port->port;
 	port->type = serial_console_port->type;
@@ -1496,14 +1573,21 @@
 	 * We need to set the initial uartclk here, since otherwise it will
 	 * only ever be setup at sci_init() time.
 	 */
-#if !defined(__H8300H__) && !defined(__H8300S__)
-	port->uartclk = current_cpu_data.module_clock * 16;
-#else
+#if defined(__H8300H__) || defined(__H8300S__)
 	port->uartclk = CONFIG_CPU_CLOCK;
-#endif
+
 #if defined(__H8300S__)
 	h8300_sci_enable(port, sci_enable);
 #endif
+#elif defined(CONFIG_SUPERH64)
+	port->uartclk = current_cpu_info.module_clock * 16;
+#else
+	{
+		struct clk *clk = clk_get("module_clk");
+		port->uartclk = clk_get_rate(clk) * 16;
+		clk_put(clk);
+	}
+#endif
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 
@@ -1566,7 +1650,7 @@
 	int parity = 'n';
 	int flow = 'n';
 
-	if (co->index >= SCI_NPORTS || co->index != kgdb_portnum)
+	if (co->index != kgdb_portnum)
 		co->index = kgdb_portnum;
 
 	if (options)
@@ -1606,7 +1690,7 @@
 #elif defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
 #define SCI_CONSOLE	&serial_console
 #else
-#define SCI_CONSOLE 	0
+#define SCI_CONSOLE	0
 #endif
 
 static char banner[] __initdata =
@@ -1621,7 +1705,6 @@
 	.dev_name	= "ttySC",
 	.major		= SCI_MAJOR,
 	.minor		= SCI_MINOR_START,
-	.nr		= SCI_NPORTS,
 	.cons		= SCI_CONSOLE,
 };
 
@@ -1631,15 +1714,21 @@
 
 	printk("%s", banner);
 
+	sci_uart_driver.nr = ARRAY_SIZE(sci_ports);
+
 	ret = uart_register_driver(&sci_uart_driver);
 	if (ret == 0) {
 		for (chan = 0; chan < SCI_NPORTS; chan++) {
 			struct sci_port *sciport = &sci_ports[chan];
 
-#if !defined(__H8300H__) && !defined(__H8300S__)
-			sciport->port.uartclk = (current_cpu_data.module_clock * 16);
-#else
+#if defined(__H8300H__) || defined(__H8300S__)
 			sciport->port.uartclk = CONFIG_CPU_CLOCK;
+#elif defined(CONFIG_SUPERH64)
+			sciport->port.uartclk = current_cpu_info.module_clock * 16;
+#else
+			struct clk *clk = clk_get("module_clk");
+			sciport->port.uartclk = clk_get_rate(clk) * 16;
+			clk_put(clk);
 #endif
 			uart_add_one_port(&sci_uart_driver, &sciport->port);
 			sciport->break_timer.data = (unsigned long)sciport;
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 2892169..1f14bb4 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -46,14 +46,17 @@
 #define H8S_SCI_IRQS1 {92, 93, 94,   0 }
 #define H8S_SCI_IRQS2 {96, 97, 98,   0 }
 #define SH5_SCIF_IRQS {39, 40, 42,   0 }
+#define	SH7770_SCIF0_IRQS {61, 61, 61, 61 }
+#define	SH7770_SCIF1_IRQS {62, 62, 62, 62 }
+#define	SH7770_SCIF2_IRQS {63, 63, 63, 63 }
+#define	SH7780_SCIF0_IRQS {40, 41, 43, 42 }
+#define	SH7780_SCIF1_IRQS {76, 77, 79, 78 }
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7708)
-# define SCI_NPORTS 1
 # define SCSPTR 0xffffff7c /* 8 bit */
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCI_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
-# define SCI_NPORTS 3
 # define SCPCR  0xA4000116 /* 16 bit SCI and SCIF */
 # define SCPDR  0xA4000136 /* 8  bit SCI and SCIF */
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
@@ -61,9 +64,8 @@
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705)
 # define SCIF0		0xA4400000
 # define SCIF2		0xA4410000
-# define SCSMR_Ir 	0xA44A0000
-# define IRDA_SCIF 	SCIF0
-# define SCI_NPORTS 2
+# define SCSMR_Ir	0xA44A0000
+# define IRDA_SCIF	SCIF0
 # define SCPCR 0xA4000116
 # define SCPDR 0xA4000136
 
@@ -74,14 +76,11 @@
 # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0
 # define SCIF_ONLY
 #elif defined(CONFIG_SH_RTS7751R2D)
-# define SCI_NPORTS 1
-# define SCSPTR1 0xffe0001c /* 8  bit SCI */
 # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
 # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
-# define SCI_NPORTS 2
 # define SCSPTR1 0xffe0001c /* 8  bit SCI */
 # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
@@ -90,34 +89,29 @@
 	0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ )
 # define SCI_AND_SCIF
 #elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-# define SCI_NPORTS 3
-# define SCSPTR0 0xfe600000 /* 16 bit SCIF */
-# define SCSPTR1 0xfe610000 /* 16 bit SCIF */
-# define SCSPTR2 0xfe620000 /* 16 bit SCIF */
+# define SCSPTR0 0xfe600024 /* 16 bit SCIF */
+# define SCSPTR1 0xfe610024 /* 16 bit SCIF */
+# define SCSPTR2 0xfe620024 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001  /* overrun error bit */
 # define SCSCR_INIT(port)          0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH7300)
-# define SCI_NPORTS 1
 # define SCPCR  0xA4050116        /* 16 bit SCIF */
 # define SCPDR  0xA4050136        /* 16 bit SCIF */
 # define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH73180)
-# define SCI_NPORTS 1
 # define SCPDR  0xA4050138        /* 16 bit SCIF */
 # define SCSPTR2 SCPDR
 # define SCIF_ORER 0x0001   /* overrun error bit */
 # define SCSCR_INIT(port)  0x0038 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-# define SCI_NPORTS 1
 # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
 # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-# define SCI_NPORTS 2
 # define SCSPTR1 0xffe00020 /* 16 bit SCIF */
 # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
@@ -129,26 +123,32 @@
 # define SCIF_ADDR_SH5     PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR
 # define SCIF_PTR2_OFFS    0x0000020
 # define SCIF_LSR2_OFFS    0x0000024
-# define SCI_NPORTS 1
-# define SCI_INIT { \
-  { {}, PORT_SCIF, 0, \
-     SH5_SCIF_IRQS, sci_init_pins_scif }  \
-}
 # define SCSPTR2           ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */
 # define SCLSR2            ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */
 # define SCSCR_INIT(port)  0x38                           /* TIE=0,RIE=0,
 							     TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
 #elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
-# define SCI_NPORTS 3
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCI_ONLY
 # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
 #elif defined(CONFIG_H8S2678)
-# define SCI_NPORTS 3
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCI_ONLY
 # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
+# define SCSPTR0 0xff923020 /* 16 bit SCIF */
+# define SCSPTR1 0xff924020 /* 16 bit SCIF */
+# define SCSPTR2 0xff925020 /* 16 bit SCIF */
+# define SCIF_ORER 0x0001  /* overrun error bit */
+# define SCSCR_INIT(port)	0x3c /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,cke=2 */
+# define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+# define SCSPTR0	0xffe00024	/* 16 bit SCIF */
+# define SCSPTR1	0xffe10024	/* 16 bit SCIF */
+# define SCIF_OPER	0x0001		/* Overrun error bit */
+# define SCSCR_INIT(port)	0x3a	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
 #else
 # error CPU subtype not defined
 #endif
@@ -158,7 +158,7 @@
 #define SCI_CTRL_FLAGS_RIE  0x40 /* all */
 #define SCI_CTRL_FLAGS_TE   0x20 /* all */
 #define SCI_CTRL_FLAGS_RE   0x10 /* all */
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
+#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
 #else
 #define SCI_CTRL_FLAGS_REIE 0
@@ -213,7 +213,7 @@
 # define SCxSR_RDxF_CLEAR(port)		0xbc
 # define SCxSR_ERROR_CLEAR(port)	0xc4
 # define SCxSR_TDxE_CLEAR(port)		0x78
-# define SCxSR_BREAK_CLEAR(port)   	0xc4
+# define SCxSR_BREAK_CLEAR(port)	0xc4
 #elif defined(SCIF_ONLY)
 # define SCxSR_TEND(port)		SCIF_TEND
 # define SCxSR_ERRORS(port)		SCIF_ERRORS
@@ -237,7 +237,7 @@
 # define SCxSR_RDxF_CLEAR(port)		0x00fc
 # define SCxSR_ERROR_CLEAR(port)	0x0073
 # define SCxSR_TDxE_CLEAR(port)		0x00df
-# define SCxSR_BREAK_CLEAR(port)   	0x00e3
+# define SCxSR_BREAK_CLEAR(port)	0x00e3
 #endif
 #else
 # define SCxSR_TEND(port)	 (((port)->type == PORT_SCI) ? SCI_TEND   : SCIF_TEND)
@@ -285,14 +285,14 @@
 
 #define SCI_IN(size, offset)					\
   unsigned int addr = port->mapbase + (offset);			\
-  if ((size) == 8) { 						\
+  if ((size) == 8) {						\
     return ctrl_inb(addr);					\
-  } else {					 		\
+  } else {							\
     return ctrl_inw(addr);					\
   }
 #define SCI_OUT(size, offset, value)				\
   unsigned int addr = port->mapbase + (offset);			\
-  if ((size) == 8) { 						\
+  if ((size) == 8) {						\
     ctrl_outb(value, addr);					\
   } else {							\
     ctrl_outw(value, addr);					\
@@ -301,10 +301,10 @@
 #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
   static inline unsigned int sci_##name##_in(struct uart_port *port)	\
   {									\
-    if (port->type == PORT_SCI) { 					\
+    if (port->type == PORT_SCI) {					\
       SCI_IN(sci_size, sci_offset)					\
     } else {								\
-      SCI_IN(scif_size, scif_offset);		 			\
+      SCI_IN(scif_size, scif_offset);					\
     }									\
   }									\
   static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
@@ -319,7 +319,7 @@
 #define CPU_SCIF_FNS(name, scif_offset, scif_size)				\
   static inline unsigned int sci_##name##_in(struct uart_port *port)	\
   {									\
-    SCI_IN(scif_size, scif_offset);		 			\
+    SCI_IN(scif_size, scif_offset);					\
   }									\
   static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
   {									\
@@ -329,7 +329,7 @@
 #define CPU_SCI_FNS(name, sci_offset, sci_size)				\
   static inline unsigned int sci_##name##_in(struct uart_port* port)	\
   {									\
-    SCI_IN(sci_size, sci_offset);		 			\
+    SCI_IN(sci_size, sci_offset);					\
   }									\
   static inline void sci_##name##_out(struct uart_port* port, unsigned int value) \
   {									\
@@ -385,10 +385,17 @@
 SCIx_FNS(SCxSR,  0x08,  8, 0x10,  8, 0x08, 16, 0x10, 16, 0x04,  8)
 SCIx_FNS(SCxRDR, 0x0a,  8, 0x14,  8, 0x0A,  8, 0x14,  8, 0x05,  8)
 SCIF_FNS(SCFCR,                      0x0c,  8, 0x18, 16)
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+SCIF_FNS(SCTFDR,		     0x0e, 16, 0x1C, 16)
+SCIF_FNS(SCRFDR,		     0x0e, 16, 0x20, 16)
+SCIF_FNS(SCSPTR,			0,  0, 0x24, 16)
+SCIF_FNS(SCLSR,				0,  0, 0x28, 16)
+#else
 SCIF_FNS(SCFDR,                      0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCSPTR,                        0,  0, 0x20, 16)
 SCIF_FNS(SCLSR,                         0,  0, 0x24, 16)
 #endif
+#endif
 #define sci_in(port, reg) sci_##reg##_in(port)
 #define sci_out(port, reg, value) sci_##reg##_out(port, value)
 
@@ -518,6 +525,24 @@
 	int ch = (port->mapbase - SMR0) >> 3;
 	return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+	if (port->mapbase == 0xff923000)
+		return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+	if (port->mapbase == 0xff924000)
+		return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+	if (port->mapbase == 0xff925000)
+		return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+	if (port->mapbase == 0xffe00000)
+		return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+	if (port->mapbase == 0xffe10000)
+		return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+}
 #endif
 
 /*
@@ -552,22 +577,15 @@
  * -- Mitch Davis - 15 Jul 2000
  */
 
-#define PCLK           (current_cpu_data.module_clock)
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-#define SCBRR_VALUE(bps) ((PCLK+16*bps)/(16*bps)-1)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-#define SCBRR_VALUE(bps) (((PCLK*2)+16*bps)/(32*bps)-1)
-#elif !defined(__H8300H__) && !defined(__H8300S__)
-#define SCBRR_VALUE(bps) ((PCLK+16*bps)/(32*bps)-1)
-#else
+#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
+#elif defined(__H8300H__) || defined(__H8300S__)
 #define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1)
+#elif defined(CONFIG_SUPERH64)
+#define SCBRR_VALUE(bps) ((current_cpu_data.module_clock+16*bps)/(32*bps)-1)
+#else /* Generic SH */
+#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
 #endif
-#define BPS_2400       SCBRR_VALUE(2400)
-#define BPS_4800       SCBRR_VALUE(4800)
-#define BPS_9600       SCBRR_VALUE(9600)
-#define BPS_19200      SCBRR_VALUE(19200)
-#define BPS_38400      SCBRR_VALUE(38400)
-#define BPS_57600      SCBRR_VALUE(57600)
-#define BPS_115200     SCBRR_VALUE(115200)
 
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 5468e5a..43e67d6 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -6,7 +6,7 @@
  * driver for that.
  *
  *
- * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2004-2006 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -829,8 +829,8 @@
 		misc.name = DEVICE_NAME_DYNAMIC;
 		retval = misc_register(&misc);
 		if (retval != 0) {
-			printk
-			    ("Failed to register console device using misc_register.\n");
+			printk(KERN_WARNING "Failed to register console "
+			       "device using misc_register.\n");
 			return -ENODEV;
 		}
 		sal_console_uart.major = MISC_MAJOR;
@@ -942,88 +942,75 @@
 {
 	unsigned long flags = 0;
 	struct sn_cons_port *port = &sal_console_port;
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 	static int stole_lock = 0;
-#endif
 
 	BUG_ON(!port->sc_is_asynch);
 
 	/* We can't look at the xmit buffer if we're not registered with serial core
 	 *  yet.  So only do the fancy recovery after registering
 	 */
-	if (port->sc_port.info) {
+	if (!port->sc_port.info) {
+		/* Not yet registered with serial core - simple case */
+		puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+		return;
+	}
 
-		/* somebody really wants this output, might be an
-		 * oops, kdb, panic, etc.  make sure they get it. */
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
-		if (spin_is_locked(&port->sc_port.lock)) {
-			int lhead = port->sc_port.info->xmit.head;
-			int ltail = port->sc_port.info->xmit.tail;
-			int counter, got_lock = 0;
+	/* somebody really wants this output, might be an
+	 * oops, kdb, panic, etc.  make sure they get it. */
+	if (spin_is_locked(&port->sc_port.lock)) {
+		int lhead = port->sc_port.info->xmit.head;
+		int ltail = port->sc_port.info->xmit.tail;
+		int counter, got_lock = 0;
 
-			/*
-			 * We attempt to determine if someone has died with the
-			 * lock. We wait ~20 secs after the head and tail ptrs
-			 * stop moving and assume the lock holder is not functional
-			 * and plow ahead. If the lock is freed within the time out
-			 * period we re-get the lock and go ahead normally. We also
-			 * remember if we have plowed ahead so that we don't have
-			 * to wait out the time out period again - the asumption
-			 * is that we will time out again.
-			 */
+		/*
+		 * We attempt to determine if someone has died with the
+		 * lock. We wait ~20 secs after the head and tail ptrs
+		 * stop moving and assume the lock holder is not functional
+		 * and plow ahead. If the lock is freed within the time out
+		 * period we re-get the lock and go ahead normally. We also
+		 * remember if we have plowed ahead so that we don't have
+		 * to wait out the time out period again - the asumption
+		 * is that we will time out again.
+		 */
 
-			for (counter = 0; counter < 150; mdelay(125), counter++) {
-				if (!spin_is_locked(&port->sc_port.lock)
-				    || stole_lock) {
-					if (!stole_lock) {
-						spin_lock_irqsave(&port->
-								  sc_port.lock,
-								  flags);
-						got_lock = 1;
-					}
-					break;
-				} else {
-					/* still locked */
-					if ((lhead !=
-					     port->sc_port.info->xmit.head)
-					    || (ltail !=
-						port->sc_port.info->xmit.
-						tail)) {
-						lhead =
-						    port->sc_port.info->xmit.
-						    head;
-						ltail =
-						    port->sc_port.info->xmit.
-						    tail;
-						counter = 0;
-					}
+		for (counter = 0; counter < 150; mdelay(125), counter++) {
+			if (!spin_is_locked(&port->sc_port.lock)
+			    || stole_lock) {
+				if (!stole_lock) {
+					spin_lock_irqsave(&port->sc_port.lock,
+							  flags);
+					got_lock = 1;
+				}
+				break;
+			} else {
+				/* still locked */
+				if ((lhead != port->sc_port.info->xmit.head)
+				    || (ltail !=
+					port->sc_port.info->xmit.tail)) {
+					lhead =
+						port->sc_port.info->xmit.head;
+					ltail =
+						port->sc_port.info->xmit.tail;
+					counter = 0;
 				}
 			}
-			/* flush anything in the serial core xmit buffer, raw */
-			sn_transmit_chars(port, 1);
-			if (got_lock) {
-				spin_unlock_irqrestore(&port->sc_port.lock,
-						       flags);
-				stole_lock = 0;
-			} else {
-				/* fell thru */
-				stole_lock = 1;
-			}
-			puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
-		} else {
-			stole_lock = 0;
-#endif
-			spin_lock_irqsave(&port->sc_port.lock, flags);
-			sn_transmit_chars(port, 1);
-			spin_unlock_irqrestore(&port->sc_port.lock, flags);
-
-			puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 		}
-#endif
-	}
-	else {
-		/* Not yet registered with serial core - simple case */
+		/* flush anything in the serial core xmit buffer, raw */
+		sn_transmit_chars(port, 1);
+		if (got_lock) {
+			spin_unlock_irqrestore(&port->sc_port.lock, flags);
+			stole_lock = 0;
+		} else {
+			/* fell thru */
+			stole_lock = 1;
+		}
+		puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+	} else {
+		stole_lock = 0;
+		spin_lock_irqsave(&port->sc_port.lock, flags);
+		sn_transmit_chars(port, 1);
+		spin_unlock_irqrestore(&port->sc_port.lock, flags);
+
 		puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
 	}
 }
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index 5fc4a62..fa4ae94 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -34,6 +34,7 @@
 	char *mode_prop = "ttyX-mode";
 	char *cd_prop = "ttyX-ignore-cd";
 	char *dtr_prop = "ttyX-rts-dtr-off";
+	char *ssp_console_modes_prop = "ssp-console-modes";
 	int baud, bits, stop, cflag;
 	char parity;
 	int carrier = 0;
@@ -43,14 +44,39 @@
 	if (!serial_console)
 		return;
 
-	if (serial_console == 1) {
+	switch (serial_console) {
+	case PROMDEV_OTTYA:
 		mode_prop[3] = 'a';
 		cd_prop[3] = 'a';
 		dtr_prop[3] = 'a';
-	} else {
+		break;
+
+	case PROMDEV_OTTYB:
 		mode_prop[3] = 'b';
 		cd_prop[3] = 'b';
 		dtr_prop[3] = 'b';
+		break;
+
+	case PROMDEV_ORSC:
+
+		nd = prom_pathtoinode("rsc");
+		if (!nd) {
+			strcpy(mode, "115200,8,n,1,-");
+			goto no_options;
+		}
+
+		if (!prom_node_has_property(nd, ssp_console_modes_prop)) {
+			strcpy(mode, "115200,8,n,1,-");
+			goto no_options;
+		}
+
+		memset(mode, 0, sizeof(mode));
+		prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode));
+		goto no_options;
+
+	default:
+		strcpy(mode, "9600,8,n,1,-");
+		goto no_options;
 	}
 
 	topnd = prom_getchild(prom_root_node);
@@ -110,6 +136,10 @@
 		case 9600: cflag |= B9600; break;
 		case 19200: cflag |= B19200; break;
 		case 38400: cflag |= B38400; break;
+		case 57600: cflag |= B57600; break;
+		case 115200: cflag |= B115200; break;
+		case 230400: cflag |= B230400; break;
+		case 460800: cflag |= B460800; break;
 		default: baud = 9600; cflag |= B9600; break;
 	}
 
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 7e773ff..8566422 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -897,9 +897,6 @@
 
 	sunserial_console_termios(con);
 
-	/* Firmware console speed is limited to 150-->38400 baud so
-	 * this hackish cflag thing is OK.
-	 */
 	switch (con->cflag & CBAUD) {
 	case B150: baud = 150; break;
 	case B300: baud = 300; break;
@@ -910,6 +907,10 @@
 	default: case B9600: baud = 9600; break;
 	case B19200: baud = 19200; break;
 	case B38400: baud = 38400; break;
+	case B57600: baud = 57600; break;
+	case B115200: baud = 115200; break;
+	case B230400: baud = 230400; break;
+	case B460800: baud = 460800; break;
 	};
 
 	/*
@@ -1035,7 +1036,7 @@
 		up->port.irq = edev->irqs[0];
 		up->port.fifosize = SAB82532_XMIT_FIFO_SIZE;
 		up->port.mapbase = (unsigned long)up->regs;
-		up->port.iotype = SERIAL_IO_MEM;
+		up->port.iotype = UPIO_MEM;
 
 		writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc);
 
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 9a3665b..3087045 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -109,11 +109,11 @@
 	offset <<= up->port.regshift;
 
 	switch (up->port.iotype) {
-	case SERIAL_IO_HUB6:
+	case UPIO_HUB6:
 		outb(up->port.hub6 - 1 + offset, up->port.iobase);
 		return inb(up->port.iobase + 1);
 
-	case SERIAL_IO_MEM:
+	case UPIO_MEM:
 		return readb(up->port.membase + offset);
 
 	default:
@@ -139,12 +139,12 @@
 	offset <<= up->port.regshift;
 
 	switch (up->port.iotype) {
-	case SERIAL_IO_HUB6:
+	case UPIO_HUB6:
 		outb(up->port.hub6 - 1 + offset, up->port.iobase);
 		outb(value, up->port.iobase + 1);
 		break;
 
-	case SERIAL_IO_MEM:
+	case UPIO_MEM:
 		writeb(value, up->port.membase + offset);
 		break;
 
@@ -669,7 +669,7 @@
 	 * if it is, then bail out, because there's likely no UART
 	 * here.
 	 */
-	if (!(up->port.flags & ASYNC_BUGGY_UART) &&
+	if (!(up->port.flags & UPF_BUGGY_UART) &&
 	    (serial_inp(up, UART_LSR) == 0xff)) {
 		printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
 		return -ENODEV;
@@ -707,7 +707,7 @@
 	up->ier = UART_IER_RLSI | UART_IER_RDI;
 	serial_outp(up, UART_IER, up->ier);
 
-	if (up->port.flags & ASYNC_FOURPORT) {
+	if (up->port.flags & UPF_FOURPORT) {
 		unsigned int icp;
 		/*
 		 * Enable interrupts on the AST Fourport board
@@ -740,7 +740,7 @@
 	serial_outp(up, UART_IER, 0);
 
 	spin_lock_irqsave(&up->port.lock, flags);
-	if (up->port.flags & ASYNC_FOURPORT) {
+	if (up->port.flags & UPF_FOURPORT) {
 		/* reset interrupts on the AST Fourport board */
 		inb((up->port.iobase & 0xfe0) | 0x1f);
 		up->port.mctrl |= TIOCM_OUT1;
@@ -1052,7 +1052,7 @@
 		return;
 
 	up->type_probed = PORT_UNKNOWN;
-	up->port.iotype = SERIAL_IO_MEM;
+	up->port.iotype = UPIO_MEM;
 
 	/*
 	 * First we look for Ebus-bases su's
@@ -1132,7 +1132,7 @@
 
 	spin_lock_irqsave(&up->port.lock, flags);
 
-	if (!(up->port.flags & ASYNC_BUGGY_UART)) {
+	if (!(up->port.flags & UPF_BUGGY_UART)) {
 		/*
 		 * Do a simple existence test first; if we fail this, there's
 		 * no point trying anything else.
@@ -1170,7 +1170,7 @@
 	 * manufacturer would be stupid enough to design a board
 	 * that conflicts with COM 1-4 --- we hope!
 	 */
-	if (!(up->port.flags & ASYNC_SKIP_TEST)) {
+	if (!(up->port.flags & UPF_SKIP_TEST)) {
 		serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
 		status1 = serial_inp(up, UART_MSR) & 0xF0;
 		serial_outp(up, UART_MCR, save_mcr);
@@ -1371,7 +1371,7 @@
 	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
 
 	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & ASYNC_CONS_FLOW) {
+	if (up->port.flags & UPF_CONS_FLOW) {
 		tmout = 1000000;
 		while (--tmout &&
 		       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
@@ -1513,7 +1513,7 @@
 		    up->su_type == SU_PORT_KBD)
 			continue;
 
-		up->port.flags |= ASYNC_BOOT_AUTOCONF;
+		up->port.flags |= UPF_BOOT_AUTOCONF;
 		up->port.type = PORT_UNKNOWN;
 		up->port.uartclk = (SU_BASE_BAUD * 16);
 
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 3c72484..5cc4d4c 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1487,7 +1487,7 @@
 		up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB;
 
 		/* Channel A */
-		up[(chip * 2) + 0].port.iotype = SERIAL_IO_MEM;
+		up[(chip * 2) + 0].port.iotype = UPIO_MEM;
 		up[(chip * 2) + 0].port.irq = zilog_irq;
 		up[(chip * 2) + 0].port.uartclk = ZS_CLOCK;
 		up[(chip * 2) + 0].port.fifosize = 1;
@@ -1498,7 +1498,7 @@
 		up[(chip * 2) + 0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
 
 		/* Channel B */
-		up[(chip * 2) + 1].port.iotype = SERIAL_IO_MEM;
+		up[(chip * 2) + 1].port.iotype = UPIO_MEM;
 		up[(chip * 2) + 1].port.irq = zilog_irq;
 		up[(chip * 2) + 1].port.uartclk = ZS_CLOCK;
 		up[(chip * 2) + 1].port.fifosize = 1;
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c
index 9378895..df705fd 100644
--- a/drivers/serial/v850e_uart.c
+++ b/drivers/serial/v850e_uart.c
@@ -496,7 +496,7 @@
 
 			port->ops = &v850e_uart_ops;
 			port->line = chan;
-			port->iotype = SERIAL_IO_MEM;
+			port->iotype = UPIO_MEM;
 			port->flags = UPF_BOOT_AUTOCONF;
 
 			/* We actually use multiple IRQs, but the serial
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index aaa009f..12357e1 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -38,10 +38,10 @@
 
 static int nic_wait(struct ioc3_driver_data *idd)
 {
-	volatile unsigned mcr;
+	unsigned mcr;
 
         do {
-                mcr = (volatile unsigned)idd->vma->mcr;
+                mcr = readl(&idd->vma->mcr);
         } while (!(mcr & 2));
 
         return mcr & 1;
@@ -53,7 +53,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	idd->vma->mcr = mcr_pack(500, 65);
+	writel(mcr_pack(500, 65), &idd->vma->mcr);
 	presence = nic_wait(idd);
 	local_irq_restore(flags);
 
@@ -68,7 +68,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	idd->vma->mcr = mcr_pack(6, 13);
+	writel(mcr_pack(6, 13), &idd->vma->mcr);
 	result = nic_wait(idd);
 	local_irq_restore(flags);
 
@@ -80,9 +80,9 @@
 static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit)
 {
 	if (bit)
-		idd->vma->mcr = mcr_pack(6, 110);
+		writel(mcr_pack(6, 110), &idd->vma->mcr);
 	else
-		idd->vma->mcr = mcr_pack(80, 30);
+		writel(mcr_pack(80, 30), &idd->vma->mcr);
 
 	nic_wait(idd);
 }
@@ -337,7 +337,7 @@
         int save = 0, loops = 3;
         unsigned long first, addr;
 
-        idd->vma->gpcr_s = GPCR_MLAN_EN;
+        writel(GPCR_MLAN_EN, &idd->vma->gpcr_s);
 
         while(loops>0) {
                 idd->nic_part[0] = 0;
@@ -408,7 +408,7 @@
 
 	read_lock_irqsave(&ioc3_submodules_lock, flags);
 
-	if(idd->dual_irq && idd->vma->eisr) {
+	if(idd->dual_irq && readb(&idd->vma->eisr)) {
 		/* send Ethernet IRQ to the driver */
 		if(ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
 						ioc3_ethernet->intr) {
@@ -682,7 +682,7 @@
 	idd->id = ioc3_counter++;
 	up_write(&ioc3_devices_rwsem);
 
-	idd->gpdr_shadow = idd->vma->gpdr;
+	idd->gpdr_shadow = readl(&idd->vma->gpdr);
 
 	/* Read IOC3 NIC contents */
 	probe_nic(idd);
@@ -843,9 +843,9 @@
 MODULE_DESCRIPTION("PCI driver for SGI IOC3");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(ioc3_register_submodule);
-EXPORT_SYMBOL(ioc3_unregister_submodule);
-EXPORT_SYMBOL(ioc3_ack);
-EXPORT_SYMBOL(ioc3_gpcr_set);
-EXPORT_SYMBOL(ioc3_disable);
-EXPORT_SYMBOL(ioc3_enable);
+EXPORT_SYMBOL_GPL(ioc3_register_submodule);
+EXPORT_SYMBOL_GPL(ioc3_unregister_submodule);
+EXPORT_SYMBOL_GPL(ioc3_ack);
+EXPORT_SYMBOL_GPL(ioc3_gpcr_set);
+EXPORT_SYMBOL_GPL(ioc3_disable);
+EXPORT_SYMBOL_GPL(ioc3_enable);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b77dbd6..7a75fae 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -75,16 +75,6 @@
 	  inexpensive battery powered microcontroller evaluation board.
 	  This same cable can be used to flash new firmware.
 
-config SPI_BUTTERFLY
-	tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
-	depends on SPI_MASTER && PARPORT && EXPERIMENTAL
-	select SPI_BITBANG
-	help
-	  This uses a custom parallel port cable to connect to an AVR
-	  Butterfly <http://www.atmel.com/products/avr/butterfly>, an
-	  inexpensive battery powered microcontroller evaluation board.
-	  This same cable can be used to flash new firmware.
-
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
index 79a3c59..ff9e5fa 100644
--- a/drivers/spi/spi_butterfly.c
+++ b/drivers/spi/spi_butterfly.c
@@ -163,21 +163,20 @@
 	struct butterfly	*pp = spidev_to_pp(spi);
 
 	/* set default clock polarity */
-	if (value)
+	if (value != BITBANG_CS_INACTIVE)
 		setsck(spi, spi->mode & SPI_CPOL);
 
 	/* no chipselect on this USI link config */
 	if (is_usidev(spi))
 		return;
 
-	/* here, value == "activate or not" */
-
-	/* most PARPORT_CONTROL_* bits are negated */
+	/* here, value == "activate or not";
+	 * most PARPORT_CONTROL_* bits are negated, so we must
+	 * morph it to value == "bit value to write in control register"
+	 */
 	if (spi_cs_bit == PARPORT_CONTROL_INIT)
 		value = !value;
 
-	/* here, value == "bit value to write in control register"  */
-
 	parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
 }
 
@@ -202,7 +201,9 @@
 
 /* override default partitioning with cmdlinepart */
 static struct mtd_partition partitions[] = { {
-	/* JFFS2 wants partitions of 4*N blocks for this device ... */
+	/* JFFS2 wants partitions of 4*N blocks for this device,
+	 * so sectors 0 and 1 can't be partitions by themselves.
+	 */
 
 	/* sector 0 = 8 pages * 264 bytes/page (1 block)
 	 * sector 1 = 248 pages * 264 bytes/page
@@ -316,8 +317,9 @@
 	if (status < 0)
 		goto clean2;
 
-	/* Bus 1 lets us talk to at45db041b (firmware disables AVR)
-	 * or AVR (firmware resets at45, acts as spi slave)
+	/* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR
+	 * (firmware resets at45, acts as spi slave) or neither (we ignore
+	 * both, AVR uses AT45).  Here we expect firmware for the first option.
 	 */
 	pp->info[0].max_speed_hz = 15 * 1000 * 1000;
 	strcpy(pp->info[0].modalias, "mtd_dataflash");
@@ -330,7 +332,9 @@
 				pp->dataflash->dev.bus_id);
 
 #ifdef	HAVE_USI
-	/* even more custom AVR firmware */
+	/* Bus 2 is only for talking to the AVR, and it can work no
+	 * matter who masters bus 1; needs appropriate AVR firmware.
+	 */
 	pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000;
 	strcpy(pp->info[1].modalias, "butterfly");
 	// pp->info[1].platform_data = ... TBD ... ;
@@ -378,13 +382,8 @@
 	pp = butterfly;
 	butterfly = NULL;
 
-#ifdef	HAVE_USI
-	spi_unregister_device(pp->butterfly);
-	pp->butterfly = NULL;
-#endif
-	spi_unregister_device(pp->dataflash);
-	pp->dataflash = NULL;
-
+	/* stop() unregisters child devices too */
+	pdev = to_platform_device(pp->bitbang.master->cdev.dev);
 	status = spi_bitbang_stop(&pp->bitbang);
 
 	/* turn off VCC */
@@ -394,8 +393,6 @@
 	parport_release(pp->pd);
 	parport_unregister_device(pp->pd);
 
-	pdev = to_platform_device(pp->bitbang.master->cdev.dev);
-
 	(void) spi_master_put(pp->bitbang.master);
 
 	platform_device_unregister(pdev);
@@ -420,4 +417,5 @@
 }
 module_exit(butterfly_exit);
 
+MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly");
 MODULE_LICENSE("GPL");
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c
index a0e5af6..4a51e56 100644
--- a/drivers/tc/tc.c
+++ b/drivers/tc/tc.c
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
-#include <asm/bug.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/paccess.h>
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index f670468..5578a9d 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -3558,10 +3558,16 @@
 				}
 			/* Add word 0 to G.729 frames for the 8021.  Right now we don't do VAD/CNG  */
 				if (j->play_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) {
-					if(j->write_buffer_rp + cnt == 0 && j->write_buffer_rp + cnt + 1 == 0 && j->write_buffer_rp + cnt + 2 == 0 &&
-					   j->write_buffer_rp + cnt + 3 == 0 && j->write_buffer_rp + cnt + 4 == 0 && j->write_buffer_rp + cnt + 5 == 0 &&
-					   j->write_buffer_rp + cnt + 6 == 0 && j->write_buffer_rp + cnt + 7 == 0 && j->write_buffer_rp + cnt + 8 == 0 &&
-					   j->write_buffer_rp + cnt + 9 == 0) {
+					if (j->write_buffer_rp[cnt] == 0 &&
+					    j->write_buffer_rp[cnt + 1] == 0 &&
+					    j->write_buffer_rp[cnt + 2] == 0 &&
+					    j->write_buffer_rp[cnt + 3] == 0 &&
+					    j->write_buffer_rp[cnt + 4] == 0 &&
+					    j->write_buffer_rp[cnt + 5] == 0 &&
+					    j->write_buffer_rp[cnt + 6] == 0 &&
+					    j->write_buffer_rp[cnt + 7] == 0 &&
+					    j->write_buffer_rp[cnt + 8] == 0 &&
+					    j->write_buffer_rp[cnt + 9] == 0) {
 					/* someone is trying to write silence lets make this a type 0 frame. */
 						outb_p(0x00, j->DSPbase + 0x0C);
 						outb_p(0x00, j->DSPbase + 0x0D);
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 3639c3f..36e476d 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -38,6 +38,7 @@
 
 obj-$(CONFIG_USB_DABUSB)	+= media/
 obj-$(CONFIG_USB_DSBR)		+= media/
+obj-$(CONFIG_USB_ET61X251)	+= media/
 obj-$(CONFIG_USB_IBMCAM)	+= media/
 obj-$(CONFIG_USB_KONICAWC)	+= media/
 obj-$(CONFIG_USB_OV511)		+= media/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index af0a41e..04631dc 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -36,6 +36,7 @@
 #include <linux/init.h>
 #include <linux/device.h>	/* FIXME: linux/firmware.h should include it itself */
 #include <linux/firmware.h>
+#include <linux/mutex.h>
 
 #include "usbatm.h"
 
@@ -160,7 +161,7 @@
 	struct work_struct poll_work;
 
 	/* contol handles */
-	struct semaphore cm_serialize;
+	struct mutex cm_serialize;
 	u8 *rcv_buf;
 	u8 *snd_buf;
 	struct urb *rcv_urb;
@@ -219,7 +220,7 @@
 		goto fail;
 	}
 
-	down(&instance->cm_serialize);
+	mutex_lock(&instance->cm_serialize);
 
 	/* submit reading urb before the writing one */
 	init_completion(&instance->rcv_done);
@@ -288,7 +289,7 @@
 	ret = offd;
 	dbg("cm %#x", cm);
 fail:
-	up(&instance->cm_serialize);
+	mutex_unlock(&instance->cm_serialize);
 	return ret;
 }
 
@@ -352,7 +353,6 @@
 		struct atm_dev *atm_dev)
 {
 	struct cxacru_data *instance = usbatm_instance->driver_data;
-	struct device *dev = &usbatm_instance->usb_intf->dev;
 	/*
 	struct atm_dev *atm_dev = usbatm_instance->atm_dev;
 	*/
@@ -364,14 +364,14 @@
 	ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0,
 			atm_dev->esi, sizeof(atm_dev->esi));
 	if (ret < 0) {
-		dev_err(dev, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);
+		atm_err(usbatm_instance, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);
 		return ret;
 	}
 
 	/* start ADSL */
 	ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
 	if (ret < 0) {
-		dev_err(dev, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
+		atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
 		return ret;
 	}
 
@@ -383,13 +383,13 @@
 static void cxacru_poll_status(struct cxacru_data *instance)
 {
 	u32 buf[CXINF_MAX] = {};
-	struct device *dev = &instance->usbatm->usb_intf->dev;
-	struct atm_dev *atm_dev = instance->usbatm->atm_dev;
+	struct usbatm_data *usbatm = instance->usbatm;
+	struct atm_dev *atm_dev = usbatm->atm_dev;
 	int ret;
 
 	ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX);
 	if (ret < 0) {
-		dev_warn(dev, "poll status: error %d\n", ret);
+		atm_warn(usbatm, "poll status: error %d\n", ret);
 		goto reschedule;
 	}
 
@@ -400,50 +400,50 @@
 	switch (instance->line_status) {
 	case 0:
 		atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(dev, "ADSL line: down\n");
+		atm_info(usbatm, "ADSL line: down\n");
 		break;
 
 	case 1:
 		atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(dev, "ADSL line: attemtping to activate\n");
+		atm_info(usbatm, "ADSL line: attempting to activate\n");
 		break;
 
 	case 2:
 		atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(dev, "ADSL line: training\n");
+		atm_info(usbatm, "ADSL line: training\n");
 		break;
 
 	case 3:
 		atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(dev, "ADSL line: channel analysis\n");
+		atm_info(usbatm, "ADSL line: channel analysis\n");
 		break;
 
 	case 4:
 		atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(dev, "ADSL line: exchange\n");
+		atm_info(usbatm, "ADSL line: exchange\n");
 		break;
 
 	case 5:
 		atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424;
 		atm_dev->signal = ATM_PHY_SIG_FOUND;
 
-		dev_info(dev, "ADSL line: up (%d kb/s down | %d kb/s up)\n",
+		atm_info(usbatm, "ADSL line: up (%d kb/s down | %d kb/s up)\n",
 		     buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]);
 		break;
 
 	case 6:
 		atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(dev, "ADSL line: waiting\n");
+		atm_info(usbatm, "ADSL line: waiting\n");
 		break;
 
 	case 7:
 		atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(dev, "ADSL line: initializing\n");
+		atm_info(usbatm, "ADSL line: initializing\n");
 		break;
 
 	default:
 		atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
-		dev_info(dev, "Unknown line state %02x\n", instance->line_status);
+		atm_info(usbatm, "Unknown line state %02x\n", instance->line_status);
 		break;
 	}
 reschedule:
@@ -504,8 +504,8 @@
 {
 	int ret;
 	int off;
-	struct usb_device *usb_dev = instance->usbatm->usb_dev;
-	struct device *dev = &instance->usbatm->usb_intf->dev;
+	struct usbatm_data *usbatm = instance->usbatm;
+	struct usb_device *usb_dev = usbatm->usb_dev;
 	u16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct };
 	u32 val;
 
@@ -515,7 +515,7 @@
 	val = cpu_to_le32(instance->modem_type->pll_f_clk);
 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
 	if (ret) {
-		dev_err(dev, "FirmwarePllFClkValue failed: %d\n", ret);
+		usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret);
 		return;
 	}
 
@@ -523,7 +523,7 @@
 	val = cpu_to_le32(instance->modem_type->pll_b_clk);
 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
 	if (ret) {
-		dev_err(dev, "FirmwarePllBClkValue failed: %d\n", ret);
+		usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret);
 		return;
 	}
 
@@ -531,14 +531,14 @@
 	val = cpu_to_le32(SDRAM_ENA);
 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
 	if (ret) {
-		dev_err(dev, "Enable SDRAM failed: %d\n", ret);
+		usb_err(usbatm, "Enable SDRAM failed: %d\n", ret);
 		return;
 	}
 
 	/* Firmware */
 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
 	if (ret) {
-		dev_err(dev, "Firmware upload failed: %d\n", ret);
+		usb_err(usbatm, "Firmware upload failed: %d\n", ret);
 		return;
 	}
 
@@ -546,7 +546,7 @@
 	if (instance->modem_type->boot_rom_patch) {
 		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);
 		if (ret) {
-			dev_err(dev, "Boot ROM patching failed: %d\n", ret);
+			usb_err(usbatm, "Boot ROM patching failed: %d\n", ret);
 			return;
 		}
 	}
@@ -554,7 +554,7 @@
 	/* Signature */
 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4);
 	if (ret) {
-		dev_err(dev, "Signature storing failed: %d\n", ret);
+		usb_err(usbatm, "Signature storing failed: %d\n", ret);
 		return;
 	}
 
@@ -566,7 +566,7 @@
 		ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
 	}
 	if (ret) {
-		dev_err(dev, "Passing control to firmware failed: %d\n", ret);
+		usb_err(usbatm, "Passing control to firmware failed: %d\n", ret);
 		return;
 	}
 
@@ -580,7 +580,7 @@
 
 	ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
 	if (ret < 0) {
-		dev_err(dev, "modem failed to initialize: %d\n", ret);
+		usb_err(usbatm, "modem failed to initialize: %d\n", ret);
 		return;
 	}
 
@@ -597,7 +597,7 @@
 			ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET,
 					(u8 *) buf, len, NULL, 0);
 			if (ret < 0) {
-				dev_err(dev, "load config data failed: %d\n", ret);
+				usb_err(usbatm, "load config data failed: %d\n", ret);
 				return;
 			}
 		}
@@ -608,18 +608,19 @@
 static int cxacru_find_firmware(struct cxacru_data *instance,
 				char* phase, const struct firmware **fw_p)
 {
-	struct device *dev = &instance->usbatm->usb_intf->dev;
+	struct usbatm_data *usbatm = instance->usbatm;
+	struct device *dev = &usbatm->usb_intf->dev;
 	char buf[16];
 
 	sprintf(buf, "cxacru-%s.bin", phase);
 	dbg("cxacru_find_firmware: looking for %s", buf);
 
 	if (request_firmware(fw_p, buf, dev)) {
-		dev_dbg(dev, "no stage %s firmware found\n", phase);
+		usb_dbg(usbatm, "no stage %s firmware found\n", phase);
 		return -ENOENT;
 	}
 
-	dev_info(dev, "found firmware %s\n", buf);
+	usb_info(usbatm, "found firmware %s\n", buf);
 
 	return 0;
 }
@@ -627,20 +628,19 @@
 static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
 			     struct usb_interface *usb_intf)
 {
-	struct device *dev = &usbatm_instance->usb_intf->dev;
 	const struct firmware *fw, *bp, *cf;
 	struct cxacru_data *instance = usbatm_instance->driver_data;
 
 	int ret = cxacru_find_firmware(instance, "fw", &fw);
 	if (ret) {
-		dev_warn(dev, "firmware (cxacru-fw.bin) unavailable (hotplug misconfiguration?)\n");
+		usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n");
 		return ret;
 	}
 
 	if (instance->modem_type->boot_rom_patch) {
 		ret = cxacru_find_firmware(instance, "bp", &bp);
 		if (ret) {
-			dev_warn(dev, "boot ROM patch (cxacru-bp.bin) unavailable (hotplug misconfiguration?)\n");
+			usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n");
 			release_firmware(fw);
 			return ret;
 		}
@@ -667,22 +667,19 @@
 }
 
 static int cxacru_bind(struct usbatm_data *usbatm_instance,
-		       struct usb_interface *intf, const struct usb_device_id *id,
-		       int *need_heavy_init)
+		       struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct cxacru_data *instance;
 	struct usb_device *usb_dev = interface_to_usbdev(intf);
 	int ret;
 
 	/* instance init */
-	instance = kmalloc(sizeof(*instance), GFP_KERNEL);
+	instance = kzalloc(sizeof(*instance), GFP_KERNEL);
 	if (!instance) {
 		dbg("cxacru_bind: no memory for instance data");
 		return -ENOMEM;
 	}
 
-	memset(instance, 0, sizeof(*instance));
-
 	instance->usbatm = usbatm_instance;
 	instance->modem_type = (struct cxacru_modem_type *) id->driver_info;
 
@@ -721,13 +718,13 @@
 			instance->snd_buf, PAGE_SIZE,
 			cxacru_blocking_completion, &instance->snd_done, 4);
 
-	init_MUTEX(&instance->cm_serialize);
+	mutex_init(&instance->cm_serialize);
 
 	INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance);
 
 	usbatm_instance->driver_data = instance;
 
-	*need_heavy_init = cxacru_card_status(instance);
+	usbatm_instance->flags = (cxacru_card_status(instance) ? 0 : UDSL_SKIP_HEAVY_INIT);
 
 	return 0;
 
@@ -787,12 +784,12 @@
 	{ /* V = Conexant			P = ADSL modem (Hasbani project)	*/
 		USB_DEVICE(0x0572, 0xcb00),	.driver_info = (unsigned long) &cxacru_cb00
 	},
-	{ /* V = Conexant             P = ADSL modem (Well PTI-800 */
-		USB_DEVICE(0x0572, 0xcb02),	.driver_info = (unsigned long) &cxacru_cb00
-	},
 	{ /* V = Conexant			P = ADSL modem				*/
 		USB_DEVICE(0x0572, 0xcb01),	.driver_info = (unsigned long) &cxacru_cb00
 	},
+	{ /* V = Conexant			P = ADSL modem (Well PTI-800) */
+		USB_DEVICE(0x0572, 0xcb02),	.driver_info = (unsigned long) &cxacru_cb00
+	},
 	{ /* V = Conexant			P = ADSL modem				*/
 		USB_DEVICE(0x0572, 0xcb06),	.driver_info = (unsigned long) &cxacru_cb00
 	},
@@ -835,14 +832,13 @@
 MODULE_DEVICE_TABLE(usb, cxacru_usb_ids);
 
 static struct usbatm_driver cxacru_driver = {
-	.owner		= THIS_MODULE,
 	.driver_name	= cxacru_driver_name,
 	.bind		= cxacru_bind,
 	.heavy_init	= cxacru_heavy_init,
 	.unbind		= cxacru_unbind,
 	.atm_start	= cxacru_atm_start,
-	.in		= CXACRU_EP_DATA,
-	.out		= CXACRU_EP_DATA,
+	.bulk_in	= CXACRU_EP_DATA,
+	.bulk_out	= CXACRU_EP_DATA,
 	.rx_padding	= 3,
 	.tx_padding	= 11,
 };
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index c1b47d7..7860c8a 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -35,12 +35,14 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/usb_ch9.h>
 #include <linux/workqueue.h>
 
 #include "usbatm.h"
 
 #define DRIVER_AUTHOR	"Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
-#define DRIVER_VERSION	"1.9"
+#define DRIVER_VERSION	"1.10"
 #define DRIVER_DESC	"Alcatel SpeedTouch USB driver version " DRIVER_VERSION
 
 static const char speedtch_driver_name[] = "speedtch";
@@ -66,31 +68,42 @@
 
 #define RESUBMIT_DELAY		1000	/* milliseconds */
 
-#define DEFAULT_ALTSETTING	1
+#define DEFAULT_BULK_ALTSETTING	1
+#define DEFAULT_ISOC_ALTSETTING	2
 #define DEFAULT_DL_512_FIRST	0
+#define DEFAULT_ENABLE_ISOC	0
 #define DEFAULT_SW_BUFFERING	0
 
-static int altsetting = DEFAULT_ALTSETTING;
+static unsigned int altsetting = 0; /* zero means: use the default */
 static int dl_512_first = DEFAULT_DL_512_FIRST;
+static int enable_isoc = DEFAULT_ENABLE_ISOC;
 static int sw_buffering = DEFAULT_SW_BUFFERING;
 
-module_param(altsetting, int, S_IRUGO | S_IWUSR);
+module_param(altsetting, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(altsetting,
-		 "Alternative setting for data interface (default: "
-		 __MODULE_STRING(DEFAULT_ALTSETTING) ")");
+		"Alternative setting for data interface (bulk_default: "
+		__MODULE_STRING(DEFAULT_BULK_ALTSETTING) "; isoc_default: "
+		__MODULE_STRING(DEFAULT_ISOC_ALTSETTING) ")");
 
 module_param(dl_512_first, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(dl_512_first,
 		 "Read 512 bytes before sending firmware (default: "
 		 __MODULE_STRING(DEFAULT_DL_512_FIRST) ")");
 
+module_param(enable_isoc, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_isoc,
+		"Use isochronous transfers if available (default: "
+		__MODULE_STRING(DEFAULT_ENABLE_ISOC) ")");
+
 module_param(sw_buffering, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(sw_buffering,
 		 "Enable software buffering (default: "
 		 __MODULE_STRING(DEFAULT_SW_BUFFERING) ")");
 
+#define INTERFACE_DATA		1
 #define ENDPOINT_INT		0x81
-#define ENDPOINT_DATA		0x07
+#define ENDPOINT_BULK_DATA	0x07
+#define ENDPOINT_ISOC_DATA	0x07
 #define ENDPOINT_FIRMWARE	0x05
 
 #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) )
@@ -98,6 +111,8 @@
 struct speedtch_instance_data {
 	struct usbatm_data *usbatm;
 
+	unsigned int altsetting;
+
 	struct work_struct status_checker;
 
 	unsigned char last_status;
@@ -205,7 +220,7 @@
 				   buffer, 0x200, &actual_length, 2000);
 
 		if (ret < 0 && ret != -ETIMEDOUT)
-			usb_dbg(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret);
+			usb_warn(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret);
 		else
 			usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret);
 	}
@@ -219,7 +234,7 @@
 				   buffer, thislen, &actual_length, DATA_TIMEOUT);
 
 		if (ret < 0) {
-			usb_dbg(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret);
+			usb_err(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret);
 			goto out_free;
 		}
 		usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size);
@@ -232,7 +247,7 @@
 			   buffer, 0x200, &actual_length, DATA_TIMEOUT);
 
 	if (ret < 0) {
-		usb_dbg(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret);
+		usb_err(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret);
 		goto out_free;
 	}
 	usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length);
@@ -246,7 +261,7 @@
 				   buffer, thislen, &actual_length, DATA_TIMEOUT);
 
 		if (ret < 0) {
-			usb_dbg(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret);
+			usb_err(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret);
 			goto out_free;
 		}
 	}
@@ -259,7 +274,7 @@
 			   buffer, 0x200, &actual_length, DATA_TIMEOUT);
 
 	if (ret < 0) {
-		usb_dbg(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret);
+		usb_err(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret);
 		goto out_free;
 	}
 
@@ -270,6 +285,11 @@
 	   because we're in our own kernel thread anyway. */
 	msleep_interruptible(1000);
 
+	if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
+		usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret);
+		goto out_free;
+	}
+
 	/* Enable software buffering, if requested */
 	if (sw_buffering)
 		speedtch_set_swbuff(instance, 1);
@@ -285,8 +305,8 @@
 	return ret;
 }
 
-static int speedtch_find_firmware(struct usb_interface *intf, int phase,
-				  const struct firmware **fw_p)
+static int speedtch_find_firmware(struct usbatm_data *usbatm, struct usb_interface *intf,
+				  int phase, const struct firmware **fw_p)
 {
 	struct device *dev = &intf->dev;
 	const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice);
@@ -295,24 +315,24 @@
 	char buf[24];
 
 	sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision);
-	dev_dbg(dev, "%s: looking for %s\n", __func__, buf);
+	usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);
 
 	if (request_firmware(fw_p, buf, dev)) {
 		sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision);
-		dev_dbg(dev, "%s: looking for %s\n", __func__, buf);
+		usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);
 
 		if (request_firmware(fw_p, buf, dev)) {
 			sprintf(buf, "speedtch-%d.bin", phase);
-			dev_dbg(dev, "%s: looking for %s\n", __func__, buf);
+			usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);
 
 			if (request_firmware(fw_p, buf, dev)) {
-				dev_warn(dev, "no stage %d firmware found!\n", phase);
+				usb_err(usbatm, "%s: no stage %d firmware found!\n", __func__, phase);
 				return -ENOENT;
 			}
 		}
 	}
 
-	dev_info(dev, "found stage %d firmware %s\n", phase, buf);
+	usb_info(usbatm, "found stage %d firmware %s\n", phase, buf);
 
 	return 0;
 }
@@ -323,15 +343,16 @@
 	struct speedtch_instance_data *instance = usbatm->driver_data;
 	int ret;
 
-	if ((ret = speedtch_find_firmware(intf, 1, &fw1)) < 0)
-			return ret;
+	if ((ret = speedtch_find_firmware(usbatm, intf, 1, &fw1)) < 0)
+		return ret;
 
-	if ((ret = speedtch_find_firmware(intf, 2, &fw2)) < 0) {
+	if ((ret = speedtch_find_firmware(usbatm, intf, 2, &fw2)) < 0) {
 		release_firmware(fw1);
 		return ret;
 	}
 
-	ret = speedtch_upload_firmware(instance, fw1, fw2);
+	if ((ret = speedtch_upload_firmware(instance, fw1, fw2)) < 0)
+		usb_err(usbatm, "%s: firmware upload failed (%d)!\n", __func__, ret);
 
 	release_firmware(fw2);
 	release_firmware(fw1);
@@ -428,7 +449,9 @@
 	int down_speed, up_speed, ret;
 	unsigned char status;
 
+#ifdef VERBOSE_DEBUG
 	atm_dbg(usbatm, "%s entered\n", __func__);
+#endif
 
 	ret = speedtch_read_status(instance);
 	if (ret < 0) {
@@ -441,9 +464,9 @@
 
 	status = buf[OFFSET_7];
 
-	atm_dbg(usbatm, "%s: line state %02x\n", __func__, status);
-
 	if ((status != instance->last_status) || !status) {
+		atm_dbg(usbatm, "%s: line state 0x%02x\n", __func__, status);
+
 		switch (status) {
 		case 0:
 			atm_dev->signal = ATM_PHY_SIG_LOST;
@@ -484,7 +507,7 @@
 
 		default:
 			atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
-			atm_info(usbatm, "Unknown line state %02x\n", status);
+			atm_info(usbatm, "unknown line state %02x\n", status);
 			break;
 		}
 
@@ -583,11 +606,6 @@
 
 	atm_dbg(usbatm, "%s entered\n", __func__);
 
-	if ((ret = usb_set_interface(usb_dev, 1, altsetting)) < 0) {
-		atm_dbg(usbatm, "%s: usb_set_interface returned %d!\n", __func__, ret);
-		return ret;
-	}
-
 	/* Set MAC address, it is stored in the serial number */
 	memset(atm_dev->esi, 0, sizeof(atm_dev->esi));
 	if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) {
@@ -678,20 +696,27 @@
 
 static int speedtch_bind(struct usbatm_data *usbatm,
 			 struct usb_interface *intf,
-			 const struct usb_device_id *id,
-			 int *need_heavy_init)
+			 const struct usb_device_id *id)
 {
 	struct usb_device *usb_dev = interface_to_usbdev(intf);
-	struct usb_interface *cur_intf;
+	struct usb_interface *cur_intf, *data_intf;
 	struct speedtch_instance_data *instance;
 	int ifnum = intf->altsetting->desc.bInterfaceNumber;
 	int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces;
 	int i, ret;
+	int use_isoc;
 
 	usb_dbg(usbatm, "%s entered\n", __func__);
 
+	/* sanity checks */
+
 	if (usb_dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
-		usb_dbg(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass);
+		usb_err(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass);
+		return -ENODEV;
+	}
+
+	if (!(data_intf = usb_ifnum_to_if(usb_dev, INTERFACE_DATA))) {
+		usb_err(usbatm, "%s: data interface not found!\n", __func__);
 		return -ENODEV;
 	}
 
@@ -704,25 +729,71 @@
 			ret = usb_driver_claim_interface(&speedtch_usb_driver, cur_intf, usbatm);
 
 			if (ret < 0) {
-				usb_dbg(usbatm, "%s: failed to claim interface %d (%d)\n", __func__, i, ret);
+				usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, i, ret);
 				speedtch_release_interfaces(usb_dev, i);
 				return ret;
 			}
 		}
 	}
 
-	instance = kmalloc(sizeof(*instance), GFP_KERNEL);
+	instance = kzalloc(sizeof(*instance), GFP_KERNEL);
 
 	if (!instance) {
-		usb_dbg(usbatm, "%s: no memory for instance data!\n", __func__);
+		usb_err(usbatm, "%s: no memory for instance data!\n", __func__);
 		ret = -ENOMEM;
 		goto fail_release;
 	}
 
-	memset(instance, 0, sizeof(struct speedtch_instance_data));
-
 	instance->usbatm = usbatm;
 
+	/* altsetting and enable_isoc may change at any moment, so take a snapshot */
+	instance->altsetting = altsetting;
+	use_isoc = enable_isoc;
+
+	if (instance->altsetting)
+		if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
+			usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->altsetting, ret);
+			instance->altsetting = 0; /* fall back to default */
+		}
+
+	if (!instance->altsetting && use_isoc)
+		if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) {
+			usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret);
+			use_isoc = 0; /* fall back to bulk */
+		}
+
+	if (use_isoc) {
+		const struct usb_host_interface *desc = data_intf->cur_altsetting;
+		const __u8 target_address = USB_DIR_IN | usbatm->driver->isoc_in;
+		int i;
+
+		use_isoc = 0; /* fall back to bulk if endpoint not found */
+
+		for (i=0; i<desc->desc.bNumEndpoints; i++) {
+			const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc;
+
+			if ((endpoint_desc->bEndpointAddress == target_address)) {
+				use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+					USB_ENDPOINT_XFER_ISOC;
+				break;
+			}
+		}
+
+		if (!use_isoc)
+			usb_info(usbatm, "isochronous transfer not supported - using bulk\n");
+	}
+
+	if (!use_isoc && !instance->altsetting)
+		if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_BULK_ALTSETTING)) < 0) {
+			usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_BULK_ALTSETTING, ret);
+			goto fail_free;
+		}
+
+	if (!instance->altsetting)
+		instance->altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING;
+
+	usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
+
 	INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);
 
 	instance->status_checker.timer.function = speedtch_status_poll;
@@ -749,13 +820,15 @@
 			      0x12, 0xc0, 0x07, 0x00,
 			      instance->scratch_buffer + OFFSET_7, SIZE_7, 500);
 
-	*need_heavy_init = (ret != SIZE_7);
+	usbatm->flags |= (ret == SIZE_7 ? UDSL_SKIP_HEAVY_INIT : 0);
 
-	usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, need_heavy_init ? "not" : "already");
+	usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, usbatm->flags & UDSL_SKIP_HEAVY_INIT ? "already" : "not");
 
-	if (*need_heavy_init)
-		if ((ret = usb_reset_device(usb_dev)) < 0)
+	if (!(usbatm->flags & UDSL_SKIP_HEAVY_INIT))
+		if ((ret = usb_reset_device(usb_dev)) < 0) {
+			usb_err(usbatm, "%s: device reset failed (%d)!\n", __func__, ret);
 			goto fail_free;
+		}
 
         usbatm->driver_data = instance;
 
@@ -787,15 +860,15 @@
 ***********/
 
 static struct usbatm_driver speedtch_usbatm_driver = {
-	.owner		= THIS_MODULE,
 	.driver_name	= speedtch_driver_name,
 	.bind		= speedtch_bind,
 	.heavy_init	= speedtch_heavy_init,
 	.unbind		= speedtch_unbind,
 	.atm_start	= speedtch_atm_start,
 	.atm_stop	= speedtch_atm_stop,
-	.in		= ENDPOINT_DATA,
-	.out		= ENDPOINT_DATA
+	.bulk_in	= ENDPOINT_BULK_DATA,
+	.bulk_out	= ENDPOINT_BULK_DATA,
+	.isoc_in	= ENDPOINT_ISOC_DATA
 };
 
 static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 7d2a679..830d2c9 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -63,11 +63,12 @@
 #include <linux/ctype.h>
 #include <linux/kthread.h>
 #include <linux/version.h>
+#include <linux/mutex.h>
 #include <asm/unaligned.h>
 
 #include "usbatm.h"
 
-#define EAGLEUSBVERSION "ueagle 1.1"
+#define EAGLEUSBVERSION "ueagle 1.2"
 
 
 /*
@@ -358,16 +359,19 @@
 #define INTR_PKT_SIZE 28
 
 static struct usb_driver uea_driver;
-static DECLARE_MUTEX(uea_semaphore);
+static DEFINE_MUTEX(uea_mutex);
 static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"};
 
 static int modem_index;
 static unsigned int debug;
+static int use_iso[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = 1};
 static int sync_wait[NB_MODEM];
 static char *cmv_file[NB_MODEM];
 
 module_param(debug, uint, 0644);
 MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)");
+module_param_array(use_iso, bool, NULL, 0644);
+MODULE_PARM_DESC(use_iso, "use isochronous usb pipe for incoming traffic");
 module_param_array(sync_wait, bool, NULL, 0644);
 MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM");
 module_param_array(cmv_file, charp, NULL, 0644);
@@ -628,8 +632,7 @@
 			dsp_name = FW_DIR "DSPep.bin";
 	}
 
-	ret = request_firmware(&sc->dsp_firm,
-				dsp_name, &sc->usb_dev->dev);
+	ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev);
 	if (ret < 0) {
 		uea_err(INS_TO_USBDEV(sc),
 		       "requesting firmware %s failed with error %d\n",
@@ -744,7 +747,6 @@
 		return ret;
 
 	return (ret == 0) ? -ETIMEDOUT : 0;
-
 }
 
 #define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
@@ -935,6 +937,7 @@
 	 * ADI930 don't support it (-EPIPE error).
 	 */
 	if (UEA_CHIP_VERSION(sc) != ADI930
+		    && !use_iso[sc->modem_index]
 		    && sc->stats.phy.dsrate != (data >> 16) * 32) {
 		/* Original timming from ADI(used in windows driver)
 		 * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits
@@ -1010,7 +1013,7 @@
 	int ret, size;
 	u8 *data;
 	char *file;
-	static char cmv_name[256] = FW_DIR;
+	char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */
 
 	if (cmv_file[sc->modem_index] == NULL) {
 		if (UEA_CHIP_VERSION(sc) == ADI930)
@@ -1184,8 +1187,7 @@
 		}
 	}
 
-	/* finish to send the fpga
-	 */
+	/* finish to send the fpga */
 	ret = uea_request(sc, 0xe, 1, 0, NULL);
 	if (ret < 0) {
 		uea_err(INS_TO_USBDEV(sc),
@@ -1193,9 +1195,7 @@
 		goto err1;
 	}
 
-	/*
-	 * Tell the modem we finish : de-assert reset
-	 */
+	/* Tell the modem we finish : de-assert reset */
 	value = 0;
 	ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
 	if (ret < 0)
@@ -1209,6 +1209,7 @@
 	return ret;
 }
 
+/* The modem send us an ack. First with check if it right */
 static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
 {
 	uea_enters(INS_TO_USBDEV(sc));
@@ -1268,23 +1269,19 @@
  */
 static void uea_intr(struct urb *urb, struct pt_regs *regs)
 {
-	struct uea_softc *sc = (struct uea_softc *)urb->context;
-	struct intr_pkt *intr;
+	struct uea_softc *sc = urb->context;
+	struct intr_pkt *intr = urb->transfer_buffer;
 	uea_enters(INS_TO_USBDEV(sc));
 
-	if (urb->status < 0) {
+	if (unlikely(urb->status < 0)) {
 		uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n",
 		       urb->status);
 		return;
 	}
 
-	intr = (struct intr_pkt *) urb->transfer_buffer;
-
 	/* device-to-host interrupt */
 	if (intr->bType != 0x08 || sc->booting) {
-		uea_err(INS_TO_USBDEV(sc), "wrong intr\n");
-		// rebooting ?
-		// sc->reset = 1;
+		uea_err(INS_TO_USBDEV(sc), "wrong interrupt\n");
 		goto resubmit;
 	}
 
@@ -1300,7 +1297,7 @@
 		break;
 
 	default:
-		uea_err(INS_TO_USBDEV(sc), "unknown intr %u\n",
+		uea_err(INS_TO_USBDEV(sc), "unknown interrupt %u\n",
 		       le16_to_cpu(intr->wInterrupt));
 	}
 
@@ -1379,7 +1376,7 @@
 	int ret;
 	uea_enters(INS_TO_USBDEV(sc));
 	ret = kthread_stop(sc->kthread);
-	uea_info(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
+	uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
 
 	/* stop any pending boot process */
 	flush_scheduled_work();
@@ -1418,13 +1415,13 @@
 	int ret = -ENODEV;
 	struct uea_softc *sc;
 
-	down(&uea_semaphore);
+	mutex_lock(&uea_mutex);
 	sc = dev_to_uea(dev);
 	if (!sc)
 		goto out;
 	ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state);
 out:
-	up(&uea_semaphore);
+	mutex_unlock(&uea_mutex);
 	return ret;
 }
 
@@ -1434,14 +1431,14 @@
 	int ret = -ENODEV;
 	struct uea_softc *sc;
 
-	down(&uea_semaphore);
+	mutex_lock(&uea_mutex);
 	sc = dev_to_uea(dev);
 	if (!sc)
 		goto out;
 	sc->reset = 1;
 	ret = count;
 out:
-	up(&uea_semaphore);
+	mutex_unlock(&uea_mutex);
 	return ret;
 }
 
@@ -1453,7 +1450,7 @@
 	int ret = -ENODEV;
 	struct uea_softc *sc;
 
-	down(&uea_semaphore);
+	mutex_lock(&uea_mutex);
 	sc = dev_to_uea(dev);
 	if (!sc)
 		goto out;
@@ -1473,7 +1470,7 @@
 		break;
 	}
 out:
-	up(&uea_semaphore);
+	mutex_unlock(&uea_mutex);
 	return ret;
 }
 
@@ -1485,7 +1482,7 @@
 	int ret = -ENODEV;
 	struct uea_softc *sc;
 
-	down(&uea_semaphore);
+	mutex_lock(&uea_mutex);
 	sc = dev_to_uea(dev);
 	if (!sc)
 		goto out;
@@ -1497,7 +1494,7 @@
 	else
 		ret = sprintf(buf, "GOOD\n");
 out:
-	up(&uea_semaphore);
+	mutex_unlock(&uea_mutex);
 	return ret;
 }
 
@@ -1511,7 +1508,7 @@
 	int ret = -ENODEV; 					\
 	struct uea_softc *sc; 					\
  								\
-	down(&uea_semaphore); 					\
+	mutex_lock(&uea_mutex); 					\
 	sc = dev_to_uea(dev);					\
 	if (!sc) 						\
 		goto out; 					\
@@ -1519,7 +1516,7 @@
 	if (reset)						\
 		sc->stats.phy.name = 0;				\
 out: 								\
-	up(&uea_semaphore); 					\
+	mutex_unlock(&uea_mutex); 					\
 	return ret; 						\
 } 								\
 								\
@@ -1617,7 +1614,7 @@
 }
 
 static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
-		   const struct usb_device_id *id, int *heavy)
+		   const struct usb_device_id *id)
 {
 	struct usb_device *usb = interface_to_usbdev(intf);
 	struct uea_softc *sc;
@@ -1629,16 +1626,14 @@
 	if (ifnum != UEA_INTR_IFACE_NO)
 		return -ENODEV;
 
-	*heavy = sync_wait[modem_index];
+	usbatm->flags = (sync_wait[modem_index] ? 0 : UDSL_SKIP_HEAVY_INIT);
 
 	/* interface 1 is for outbound traffic */
 	ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO);
 	if (ret < 0)
 		return ret;
 
-	/* ADI930 has only 2 interfaces and inbound traffic
-	 * is on interface 1
-	 */
+	/* ADI930 has only 2 interfaces and inbound traffic is on interface 1 */
 	if (UEA_CHIP_VERSION(id) != ADI930) {
 		/* interface 2 is for inbound traffic */
 		ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO);
@@ -1658,6 +1653,25 @@
 	sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0;
 	sc->driver_info = id->driver_info;
 
+	/* ADI930 don't support iso */
+	if (UEA_CHIP_VERSION(id) != ADI930 && use_iso[sc->modem_index]) {
+		int i;
+
+		/* try set fastest alternate for inbound traffic interface */
+		for (i = FASTEST_ISO_INTF; i > 0; i--)
+			if (usb_set_interface(usb, UEA_DS_IFACE_NO, i) == 0)
+				break;
+
+		if (i > 0) {
+			uea_dbg(usb, "set alternate %d for 2 interface\n", i);
+			uea_info(usb, "using iso mode\n");
+			usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ;
+		} else {
+			uea_err(usb, "setting any alternate failed for "
+					"2 interface, using bulk mode\n");
+		}
+	}
+
 	ret = uea_boot(sc);
 	if (ret < 0) {
 		kfree(sc);
@@ -1701,13 +1715,13 @@
 
 static struct usbatm_driver uea_usbatm_driver = {
 	.driver_name = "ueagle-atm",
-	.owner = THIS_MODULE,
 	.bind = uea_bind,
 	.atm_start = uea_atm_open,
 	.unbind = uea_unbind,
 	.heavy_init = uea_heavy,
-	.in = UEA_BULK_DATA_PIPE,
-	.out = UEA_BULK_DATA_PIPE,
+	.bulk_in = UEA_BULK_DATA_PIPE,
+	.bulk_out = UEA_BULK_DATA_PIPE,
+	.isoc_in = UEA_ISO_DATA_PIPE,
 };
 
 static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -1738,9 +1752,9 @@
 	 * Pre-firmware device has one interface
 	 */
 	if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) {
-		down(&uea_semaphore);
+		mutex_lock(&uea_mutex);
 		usbatm_usb_disconnect(intf);
-		up(&uea_semaphore);
+		mutex_unlock(&uea_mutex);
 		uea_info(usb, "ADSL device removed\n");
 	}
 
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 7af1883..c1211fc 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -72,6 +72,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/netdevice.h>
 #include <linux/proc_fs.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -91,19 +92,18 @@
 #endif
 
 #define DRIVER_AUTHOR	"Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
-#define DRIVER_VERSION	"1.9"
+#define DRIVER_VERSION	"1.10"
 #define DRIVER_DESC	"Generic USB ATM/DSL I/O, version " DRIVER_VERSION
 
 static const char usbatm_driver_name[] = "usbatm";
 
 #define UDSL_MAX_RCV_URBS		16
 #define UDSL_MAX_SND_URBS		16
-#define UDSL_MAX_RCV_BUF_SIZE		1024	/* ATM cells */
-#define UDSL_MAX_SND_BUF_SIZE		1024	/* ATM cells */
+#define UDSL_MAX_BUF_SIZE		64 * 1024	/* bytes */
 #define UDSL_DEFAULT_RCV_URBS		4
 #define UDSL_DEFAULT_SND_URBS		4
-#define UDSL_DEFAULT_RCV_BUF_SIZE	64	/* ATM cells */
-#define UDSL_DEFAULT_SND_BUF_SIZE	64	/* ATM cells */
+#define UDSL_DEFAULT_RCV_BUF_SIZE	64 * ATM_CELL_SIZE	/* bytes */
+#define UDSL_DEFAULT_SND_BUF_SIZE	64 * ATM_CELL_SIZE	/* bytes */
 
 #define ATM_CELL_HEADER			(ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
 
@@ -111,8 +111,8 @@
 
 static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS;
 static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS;
-static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE;
-static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE;
+static unsigned int rcv_buf_bytes = UDSL_DEFAULT_RCV_BUF_SIZE;
+static unsigned int snd_buf_bytes = UDSL_DEFAULT_SND_BUF_SIZE;
 
 module_param(num_rcv_urbs, uint, S_IRUGO);
 MODULE_PARM_DESC(num_rcv_urbs,
@@ -126,15 +126,15 @@
 		 __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: "
 		 __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")");
 
-module_param(rcv_buf_size, uint, S_IRUGO);
-MODULE_PARM_DESC(rcv_buf_size,
-		 "Size of the buffers used for reception in ATM cells (range: 1-"
-		 __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: "
+module_param(rcv_buf_bytes, uint, S_IRUGO);
+MODULE_PARM_DESC(rcv_buf_bytes,
+		 "Size of the buffers used for reception, in bytes (range: 1-"
+		 __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: "
 		 __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")");
 
-module_param(snd_buf_size, uint, S_IRUGO);
-MODULE_PARM_DESC(snd_buf_size,
-		 "Size of the buffers used for transmission in ATM cells (range: 1-"
+module_param(snd_buf_bytes, uint, S_IRUGO);
+MODULE_PARM_DESC(snd_buf_bytes,
+		 "Size of the buffers used for transmission, in bytes (range: 1-"
 		 __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
 		 __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
 
@@ -166,10 +166,10 @@
 
 /* ATM */
 
-static void usbatm_atm_dev_close(struct atm_dev *dev);
+static void usbatm_atm_dev_close(struct atm_dev *atm_dev);
 static int usbatm_atm_open(struct atm_vcc *vcc);
 static void usbatm_atm_close(struct atm_vcc *vcc);
-static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg);
+static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg);
 static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
 static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);
 
@@ -199,7 +199,7 @@
 	if (vcc->pop)
 		vcc->pop(vcc, skb);
 	else
-		dev_kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 }
 
 
@@ -234,8 +234,9 @@
 
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
-		atm_dbg(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n",
-			__func__, urb, ret);
+		if (printk_ratelimit())
+			atm_warn(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n",
+				__func__, urb, ret);
 
 		/* consider all errors transient and return the buffer back to the queue */
 		urb->status = -EAGAIN;
@@ -269,10 +270,16 @@
 
 	spin_unlock_irqrestore(&channel->lock, flags);
 
-	if (unlikely(urb->status))
+	if (unlikely(urb->status) &&
+			(!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) ||
+			 urb->status != -EILSEQ ))
+	{
+		if (printk_ratelimit())
+			atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n",
+				__func__, urb, urb->status);
 		/* throttle processing in case of an error */
 		mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS));
-	else
+	} else
 		tasklet_schedule(&channel->tasklet);
 }
 
@@ -284,128 +291,166 @@
 static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance,
 						  short vpi, int vci)
 {
-	struct usbatm_vcc_data *vcc;
+	struct usbatm_vcc_data *vcc_data;
 
-	list_for_each_entry(vcc, &instance->vcc_list, list)
-		if ((vcc->vci == vci) && (vcc->vpi == vpi))
-			return vcc;
+	list_for_each_entry(vcc_data, &instance->vcc_list, list)
+		if ((vcc_data->vci == vci) && (vcc_data->vpi == vpi))
+			return vcc_data;
 	return NULL;
 }
 
-static void usbatm_extract_cells(struct usbatm_data *instance,
-			       unsigned char *source, unsigned int avail_data)
+static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char *source)
 {
-	struct usbatm_vcc_data *cached_vcc = NULL;
 	struct atm_vcc *vcc;
 	struct sk_buff *sarb;
-	unsigned int stride = instance->rx_channel.stride;
-	int vci, cached_vci = 0;
-	short vpi, cached_vpi = 0;
-	u8 pti;
+	short vpi = ((source[0] & 0x0f) << 4)  | (source[1] >> 4);
+	int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
+	u8 pti = ((source[3] & 0xe) >> 1);
 
-	for (; avail_data >= stride; avail_data -= stride, source += stride) {
-		vpi = ((source[0] & 0x0f) << 4)  | (source[1] >> 4);
-		vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
-		pti = ((source[3] & 0xe) >> 1);
+	vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
 
-		vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
+	if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) {
+		instance->cached_vpi = vpi;
+		instance->cached_vci = vci;
 
-		if ((vci != cached_vci) || (vpi != cached_vpi)) {
-			cached_vpi = vpi;
-			cached_vci = vci;
+		instance->cached_vcc = usbatm_find_vcc(instance, vpi, vci);
 
-			cached_vcc = usbatm_find_vcc(instance, vpi, vci);
+		if (!instance->cached_vcc)
+			atm_rldbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);
+	}
 
-			if (!cached_vcc)
-				atm_dbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);
-		}
+	if (!instance->cached_vcc)
+		return;
 
-		if (!cached_vcc)
-			continue;
+	vcc = instance->cached_vcc->vcc;
 
-		vcc = cached_vcc->vcc;
+	/* OAM F5 end-to-end */
+	if (pti == ATM_PTI_E2EF5) {
+		if (printk_ratelimit())
+			atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
+				__func__, vpi, vci);
+		atomic_inc(&vcc->stats->rx_err);
+		return;
+	}
 
-		/* OAM F5 end-to-end */
-		if (pti == ATM_PTI_E2EF5) {
-			atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n", __func__, vpi, vci);
+	sarb = instance->cached_vcc->sarb;
+
+	if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {
+		atm_rldbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",
+				__func__, sarb->len, vcc);
+		/* discard cells already received */
+		skb_trim(sarb, 0);
+		UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
+	}
+
+	memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
+	__skb_put(sarb, ATM_CELL_PAYLOAD);
+
+	if (pti & 1) {
+		struct sk_buff *skb;
+		unsigned int length;
+		unsigned int pdu_length;
+
+		length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5];
+
+		/* guard against overflow */
+		if (length > ATM_MAX_AAL5_PDU) {
+			atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
+				  __func__, length, vcc);
 			atomic_inc(&vcc->stats->rx_err);
-			continue;
+			goto out;
 		}
 
-		sarb = cached_vcc->sarb;
+		pdu_length = usbatm_pdu_length(length);
 
-		if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {
-			atm_dbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",
-					__func__, sarb->len, vcc);
-			/* discard cells already received */
-			skb_trim(sarb, 0);
-			UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
+		if (sarb->len < pdu_length) {
+			atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
+				  __func__, pdu_length, sarb->len, vcc);
+			atomic_inc(&vcc->stats->rx_err);
+			goto out;
 		}
 
-		memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
-		__skb_put(sarb, ATM_CELL_PAYLOAD);
-
-		if (pti & 1) {
-			struct sk_buff *skb;
-			unsigned int length;
-			unsigned int pdu_length;
-
-			length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5];
-
-			/* guard against overflow */
-			if (length > ATM_MAX_AAL5_PDU) {
-				atm_dbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
-						__func__, length, vcc);
-				atomic_inc(&vcc->stats->rx_err);
-				goto out;
-			}
-
-			pdu_length = usbatm_pdu_length(length);
-
-			if (sarb->len < pdu_length) {
-				atm_dbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
-						__func__, pdu_length, sarb->len, vcc);
-				atomic_inc(&vcc->stats->rx_err);
-				goto out;
-			}
-
-			if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
-				atm_dbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
-						__func__, vcc);
-				atomic_inc(&vcc->stats->rx_err);
-				goto out;
-			}
-
-			vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);
-
-			if (!(skb = dev_alloc_skb(length))) {
-				atm_dbg(instance, "%s: no memory for skb (length: %u)!\n", __func__, length);
-				atomic_inc(&vcc->stats->rx_drop);
-				goto out;
-			}
-
-			vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);
-
-			if (!atm_charge(vcc, skb->truesize)) {
-				atm_dbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n", __func__, skb->truesize);
-				dev_kfree_skb(skb);
-				goto out;	/* atm_charge increments rx_drop */
-			}
-
-			memcpy(skb->data, sarb->tail - pdu_length, length);
-			__skb_put(skb, length);
-
-			vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
-			     __func__, skb, skb->len, skb->truesize);
-
-			PACKETDEBUG(skb->data, skb->len);
-
-			vcc->push(vcc, skb);
-
-			atomic_inc(&vcc->stats->rx);
-		out:
-			skb_trim(sarb, 0);
+		if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
+			atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
+				  __func__, vcc);
+			atomic_inc(&vcc->stats->rx_err);
+			goto out;
 		}
+
+		vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);
+
+		if (!(skb = dev_alloc_skb(length))) {
+			if (printk_ratelimit())
+				atm_err(instance, "%s: no memory for skb (length: %u)!\n",
+					__func__, length);
+			atomic_inc(&vcc->stats->rx_drop);
+			goto out;
+		}
+
+		vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);
+
+		if (!atm_charge(vcc, skb->truesize)) {
+			atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n",
+				  __func__, skb->truesize);
+			dev_kfree_skb_any(skb);
+			goto out;	/* atm_charge increments rx_drop */
+		}
+
+		memcpy(skb->data, sarb->tail - pdu_length, length);
+		__skb_put(skb, length);
+
+		vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
+		     __func__, skb, skb->len, skb->truesize);
+
+		PACKETDEBUG(skb->data, skb->len);
+
+		vcc->push(vcc, skb);
+
+		atomic_inc(&vcc->stats->rx);
+	out:
+		skb_trim(sarb, 0);
+	}
+}
+
+static void usbatm_extract_cells(struct usbatm_data *instance,
+		unsigned char *source, unsigned int avail_data)
+{
+	unsigned int stride = instance->rx_channel.stride;
+	unsigned int buf_usage = instance->buf_usage;
+
+	/* extract cells from incoming data, taking into account that
+	 * the length of avail data may not be a multiple of stride */
+
+	if (buf_usage > 0) {
+		/* we have a partially received atm cell */
+		unsigned char *cell_buf = instance->cell_buf;
+		unsigned int space_left = stride - buf_usage;
+
+		UDSL_ASSERT(buf_usage <= stride);
+
+		if (avail_data >= space_left) {
+			/* add new data and process cell */
+			memcpy(cell_buf + buf_usage, source, space_left);
+			source += space_left;
+			avail_data -= space_left;
+			usbatm_extract_one_cell(instance, cell_buf);
+			instance->buf_usage = 0;
+		} else {
+			/* not enough data to fill the cell */
+			memcpy(cell_buf + buf_usage, source, avail_data);
+			instance->buf_usage = buf_usage + avail_data;
+			return;
+		}
+	}
+
+	for (; avail_data >= stride; avail_data -= stride, source += stride)
+		usbatm_extract_one_cell(instance, source);
+
+	if (avail_data > 0) {
+		/* length was not a multiple of stride -
+		 * save remaining data for next call */
+		memcpy(instance->cell_buf, source, avail_data);
+		instance->buf_usage = avail_data;
 	}
 }
 
@@ -420,14 +465,14 @@
 {
 	struct usbatm_control *ctrl = UDSL_SKB(skb);
 	struct atm_vcc *vcc = ctrl->atm.vcc;
-	unsigned int num_written;
+	unsigned int bytes_written;
 	unsigned int stride = instance->tx_channel.stride;
 
 	vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space);
 	UDSL_ASSERT(!(avail_space % stride));
 
-	for (num_written = 0; num_written < avail_space && ctrl->len;
-	     num_written += stride, target += stride) {
+	for (bytes_written = 0; bytes_written < avail_space && ctrl->len;
+	     bytes_written += stride, target += stride) {
 		unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD);
 		unsigned int left = ATM_CELL_PAYLOAD - data_len;
 		u8 *ptr = target;
@@ -470,7 +515,7 @@
 			ctrl->crc = crc32_be(ctrl->crc, ptr, left);
 	}
 
-	return num_written;
+	return bytes_written;
 }
 
 
@@ -487,16 +532,40 @@
 		vdbg("%s: processing urb 0x%p", __func__, urb);
 
 		if (usb_pipeisoc(urb->pipe)) {
+			unsigned char *merge_start = NULL;
+			unsigned int merge_length = 0;
+			const unsigned int packet_size = instance->rx_channel.packet_size;
 			int i;
-			for (i = 0; i < urb->number_of_packets; i++)
-				if (!urb->iso_frame_desc[i].status)
-					usbatm_extract_cells(instance,
-							     (u8 *)urb->transfer_buffer + urb->iso_frame_desc[i].offset,
-							     urb->iso_frame_desc[i].actual_length);
-		}
-		else
+
+			for (i = 0; i < urb->number_of_packets; i++) {
+				if (!urb->iso_frame_desc[i].status) {
+					unsigned int actual_length = urb->iso_frame_desc[i].actual_length;
+
+					UDSL_ASSERT(actual_length <= packet_size);
+
+					if (!merge_length)
+						merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+					merge_length += actual_length;
+					if (merge_length && (actual_length < packet_size)) {
+						usbatm_extract_cells(instance, merge_start, merge_length);
+						merge_length = 0;
+					}
+				} else {
+					atm_rldbg(instance, "%s: status %d in frame %d!\n", __func__, urb->status, i);
+					if (merge_length)
+						usbatm_extract_cells(instance, merge_start, merge_length);
+					merge_length = 0;
+					instance->buf_usage = 0;
+				}
+			}
+
+			if (merge_length)
+				usbatm_extract_cells(instance, merge_start, merge_length);
+		} else
 			if (!urb->status)
 				usbatm_extract_cells(instance, urb->transfer_buffer, urb->actual_length);
+			else
+				instance->buf_usage = 0;
 
 		if (usbatm_submit_urb(urb))
 			return;
@@ -514,7 +583,7 @@
 	struct sk_buff *skb = instance->current_skb;
 	struct urb *urb = NULL;
 	const unsigned int buf_size = instance->tx_channel.buf_size;
-	unsigned int num_written = 0;
+	unsigned int bytes_written = 0;
 	u8 *buffer = NULL;
 
 	if (!skb)
@@ -526,16 +595,16 @@
 			if (!urb)
 				break;		/* no more senders */
 			buffer = urb->transfer_buffer;
-			num_written = (urb->status == -EAGAIN) ?
+			bytes_written = (urb->status == -EAGAIN) ?
 				urb->transfer_buffer_length : 0;
 		}
 
-		num_written += usbatm_write_cells(instance, skb,
-						  buffer + num_written,
-						  buf_size - num_written);
+		bytes_written += usbatm_write_cells(instance, skb,
+						  buffer + bytes_written,
+						  buf_size - bytes_written);
 
 		vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p",
-		     __func__, num_written, skb, urb);
+		     __func__, bytes_written, skb, urb);
 
 		if (!UDSL_SKB(skb)->len) {
 			struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc;
@@ -546,8 +615,8 @@
 			skb = skb_dequeue(&instance->sndqueue);
 		}
 
-		if (num_written == buf_size || (!skb && num_written)) {
-			urb->transfer_buffer_length = num_written;
+		if (bytes_written == buf_size || (!skb && bytes_written)) {
+			urb->transfer_buffer_length = bytes_written;
 
 			if (usbatm_submit_urb(urb))
 				break;
@@ -593,20 +662,24 @@
 
 	vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len);
 
-	if (!instance) {
-		dbg("%s: NULL data!", __func__);
+	/* racy disconnection check - fine */
+	if (!instance || instance->disconnected) {
+#ifdef DEBUG
+		if (printk_ratelimit())
+			printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
+#endif
 		err = -ENODEV;
 		goto fail;
 	}
 
 	if (vcc->qos.aal != ATM_AAL5) {
-		atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
+		atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
 		err = -EINVAL;
 		goto fail;
 	}
 
 	if (skb->len > ATM_MAX_AAL5_PDU) {
-		atm_dbg(instance, "%s: packet too long (%d vs %d)!\n",
+		atm_rldbg(instance, "%s: packet too long (%d vs %d)!\n",
 				__func__, skb->len, ATM_MAX_AAL5_PDU);
 		err = -EINVAL;
 		goto fail;
@@ -665,16 +738,16 @@
 **  ATM  **
 **********/
 
-static void usbatm_atm_dev_close(struct atm_dev *dev)
+static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
 {
-	struct usbatm_data *instance = dev->dev_data;
+	struct usbatm_data *instance = atm_dev->dev_data;
 
 	dbg("%s", __func__);
 
 	if (!instance)
 		return;
 
-	dev->dev_data = NULL;
+	atm_dev->dev_data = NULL; /* catch bugs */
 	usbatm_put_instance(instance);	/* taken in usbatm_atm_init */
 }
 
@@ -706,15 +779,19 @@
 			       atomic_read(&atm_dev->stats.aal5.rx_err),
 			       atomic_read(&atm_dev->stats.aal5.rx_drop));
 
-	if (!left--)
-		switch (atm_dev->signal) {
-		case ATM_PHY_SIG_FOUND:
-			return sprintf(page, "Line up\n");
-		case ATM_PHY_SIG_LOST:
-			return sprintf(page, "Line down\n");
-		default:
-			return sprintf(page, "Line state unknown\n");
-		}
+	if (!left--) {
+		if (instance->disconnected)
+			return sprintf(page, "Disconnected\n");
+		else
+			switch (atm_dev->signal) {
+			case ATM_PHY_SIG_FOUND:
+				return sprintf(page, "Line up\n");
+			case ATM_PHY_SIG_LOST:
+				return sprintf(page, "Line down\n");
+			default:
+				return sprintf(page, "Line state unknown\n");
+			}
+	}
 
 	return 0;
 }
@@ -735,13 +812,24 @@
 	atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci);
 
 	/* only support AAL5 */
-	if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0)
-	    || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {
-		atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
+	if ((vcc->qos.aal != ATM_AAL5)) {
+		atm_warn(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
 		return -EINVAL;
 	}
 
-	down(&instance->serialize);	/* vs self, usbatm_atm_close */
+	/* sanity checks */
+	if ((vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {
+		atm_dbg(instance, "%s: max_sdu %d out of range!\n", __func__, vcc->qos.rxtp.max_sdu);
+		return -EINVAL;
+	}
+
+	mutex_lock(&instance->serialize);	/* vs self, usbatm_atm_close, usbatm_usb_disconnect */
+
+	if (instance->disconnected) {
+		atm_dbg(instance, "%s: disconnected!\n", __func__);
+		ret = -ENODEV;
+		goto fail;
+	}
 
 	if (usbatm_find_vcc(instance, vpi, vci)) {
 		atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci);
@@ -749,20 +837,19 @@
 		goto fail;
 	}
 
-	if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
-		atm_dbg(instance, "%s: no memory for vcc_data!\n", __func__);
+	if (!(new = kzalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
+		atm_err(instance, "%s: no memory for vcc_data!\n", __func__);
 		ret = -ENOMEM;
 		goto fail;
 	}
 
-	memset(new, 0, sizeof(struct usbatm_vcc_data));
 	new->vcc = vcc;
 	new->vpi = vpi;
 	new->vci = vci;
 
 	new->sarb = alloc_skb(usbatm_pdu_length(vcc->qos.rxtp.max_sdu), GFP_KERNEL);
 	if (!new->sarb) {
-		atm_dbg(instance, "%s: no memory for SAR buffer!\n", __func__);
+		atm_err(instance, "%s: no memory for SAR buffer!\n", __func__);
 		ret = -ENOMEM;
 		goto fail;
 	}
@@ -770,6 +857,9 @@
 	vcc->dev_data = new;
 
 	tasklet_disable(&instance->rx_channel.tasklet);
+	instance->cached_vcc = new;
+	instance->cached_vpi = vpi;
+	instance->cached_vci = vci;
 	list_add(&new->list, &instance->vcc_list);
 	tasklet_enable(&instance->rx_channel.tasklet);
 
@@ -777,7 +867,7 @@
 	set_bit(ATM_VF_PARTIAL, &vcc->flags);
 	set_bit(ATM_VF_READY, &vcc->flags);
 
-	up(&instance->serialize);
+	mutex_unlock(&instance->serialize);
 
 	atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new);
 
@@ -785,7 +875,7 @@
 
 fail:
 	kfree(new);
-	up(&instance->serialize);
+	mutex_unlock(&instance->serialize);
 	return ret;
 }
 
@@ -806,9 +896,14 @@
 
 	usbatm_cancel_send(instance, vcc);
 
-	down(&instance->serialize);	/* vs self, usbatm_atm_open */
+	mutex_lock(&instance->serialize);	/* vs self, usbatm_atm_open, usbatm_usb_disconnect */
 
 	tasklet_disable(&instance->rx_channel.tasklet);
+	if (instance->cached_vcc == vcc_data) {
+		instance->cached_vcc = NULL;
+		instance->cached_vpi = ATM_VPI_UNSPEC;
+		instance->cached_vci = ATM_VCI_UNSPEC;
+	}
 	list_del(&vcc_data->list);
 	tasklet_enable(&instance->rx_channel.tasklet);
 
@@ -824,14 +919,21 @@
 	clear_bit(ATM_VF_PARTIAL, &vcc->flags);
 	clear_bit(ATM_VF_ADDR, &vcc->flags);
 
-	up(&instance->serialize);
+	mutex_unlock(&instance->serialize);
 
 	atm_dbg(instance, "%s successful\n", __func__);
 }
 
-static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd,
+static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
 			  void __user * arg)
 {
+	struct usbatm_data *instance = atm_dev->dev_data;
+
+	if (!instance || instance->disconnected) {
+		dbg("%s: %s!", __func__, instance ? "disconnected" : "NULL instance");
+		return -ENODEV;
+	}
+
 	switch (cmd) {
 	case ATM_QUERYLOOP:
 		return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0;
@@ -845,10 +947,13 @@
 	struct atm_dev *atm_dev;
 	int ret, i;
 
-	/* ATM init */
+	/* ATM init.  The ATM initialization scheme suffers from an intrinsic race
+	 * condition: callbacks we register can be executed at once, before we have
+	 * initialized the struct atm_dev.  To protect against this, all callbacks
+	 * abort if atm_dev->dev_data is NULL. */
 	atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);
 	if (!atm_dev) {
-		usb_dbg(instance, "%s: failed to register ATM device!\n", __func__);
+		usb_err(instance, "%s: failed to register ATM device!\n", __func__);
 		return -1;
 	}
 
@@ -862,12 +967,13 @@
 	atm_dev->link_rate = 128 * 1000 / 424;
 
 	if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
-		atm_dbg(instance, "%s: atm_start failed: %d!\n", __func__, ret);
+		atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
 		goto fail;
 	}
 
-	/* ready for ATM callbacks */
 	usbatm_get_instance(instance);	/* dropped in usbatm_atm_dev_close */
+
+	/* ready for ATM callbacks */
 	mb();
 	atm_dev->dev_data = instance;
 
@@ -903,9 +1009,9 @@
 	if (!ret)
 		ret = usbatm_atm_init(instance);
 
-	down(&instance->serialize);
+	mutex_lock(&instance->serialize);
 	instance->thread_pid = -1;
-	up(&instance->serialize);
+	mutex_unlock(&instance->serialize);
 
 	complete_and_exit(&instance->thread_exited, ret);
 }
@@ -915,13 +1021,13 @@
 	int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);
 
 	if (ret < 0) {
-		usb_dbg(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
+		usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
 		return ret;
 	}
 
-	down(&instance->serialize);
+	mutex_lock(&instance->serialize);
 	instance->thread_pid = ret;
-	up(&instance->serialize);
+	mutex_unlock(&instance->serialize);
 
 	wait_for_completion(&instance->thread_started);
 
@@ -951,9 +1057,9 @@
 	char *buf;
 	int error = -ENOMEM;
 	int i, length;
-	int need_heavy;
+	unsigned int maxpacket, num_packets;
 
-	dev_dbg(dev, "%s: trying driver %s with vendor=0x%x, product=0x%x, ifnum %d\n",
+	dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n",
 			__func__, driver->driver_name,
 			le16_to_cpu(usb_dev->descriptor.idVendor),
 			le16_to_cpu(usb_dev->descriptor.idProduct),
@@ -962,7 +1068,7 @@
 	/* instance init */
 	instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
 	if (!instance) {
-		dev_dbg(dev, "%s: no memory for instance data!\n", __func__);
+		dev_err(dev, "%s: no memory for instance data!\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -996,66 +1102,96 @@
 	snprintf(buf, length, ")");
 
  bind:
-	need_heavy = 1;
-	if (driver->bind && (error = driver->bind(instance, intf, id, &need_heavy)) < 0) {
-			dev_dbg(dev, "%s: bind failed: %d!\n", __func__, error);
+	if (driver->bind && (error = driver->bind(instance, intf, id)) < 0) {
+			dev_err(dev, "%s: bind failed: %d!\n", __func__, error);
 			goto fail_free;
 	}
 
 	/* private fields */
 
 	kref_init(&instance->refcount);		/* dropped in usbatm_usb_disconnect */
-	init_MUTEX(&instance->serialize);
+	mutex_init(&instance->serialize);
 
 	instance->thread_pid = -1;
 	init_completion(&instance->thread_started);
 	init_completion(&instance->thread_exited);
 
 	INIT_LIST_HEAD(&instance->vcc_list);
+	skb_queue_head_init(&instance->sndqueue);
 
 	usbatm_init_channel(&instance->rx_channel);
 	usbatm_init_channel(&instance->tx_channel);
 	tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance);
 	tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance);
-	instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->in);
-	instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out);
 	instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding;
 	instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding;
-	instance->rx_channel.buf_size = rcv_buf_size * instance->rx_channel.stride;
-	instance->tx_channel.buf_size = snd_buf_size * instance->tx_channel.stride;
 	instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance;
 
-	skb_queue_head_init(&instance->sndqueue);
+	if ((instance->flags & UDSL_USE_ISOC) && driver->isoc_in)
+		instance->rx_channel.endpoint = usb_rcvisocpipe(usb_dev, driver->isoc_in);
+	else
+		instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->bulk_in);
+
+	instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out);
+
+	/* tx buffer size must be a positive multiple of the stride */
+	instance->tx_channel.buf_size = max (instance->tx_channel.stride,
+			snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride));
+
+	/* rx buffer size must be a positive multiple of the endpoint maxpacket */
+	maxpacket = usb_maxpacket(usb_dev, instance->rx_channel.endpoint, 0);
+
+	if ((maxpacket < 1) || (maxpacket > UDSL_MAX_BUF_SIZE)) {
+		dev_err(dev, "%s: invalid endpoint %02x!\n", __func__,
+				usb_pipeendpoint(instance->rx_channel.endpoint));
+		error = -EINVAL;
+		goto fail_unbind;
+	}
+
+	num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */
+
+	if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE)
+		num_packets--;
+
+	instance->rx_channel.buf_size = num_packets * maxpacket;
+	instance->rx_channel.packet_size = maxpacket;
+
+#ifdef DEBUG
+	for (i = 0; i < 2; i++) {
+		struct usbatm_channel *channel = i ?
+			&instance->tx_channel : &instance->rx_channel;
+
+		dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel);
+	}
+#endif
+
+	/* initialize urbs */
 
 	for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
-		struct urb *urb;
 		u8 *buffer;
-		unsigned int iso_packets = 0, iso_size = 0;
 		struct usbatm_channel *channel = i < num_rcv_urbs ?
 			&instance->rx_channel : &instance->tx_channel;
+		struct urb *urb;
+		unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0;
 
-		if (usb_pipeisoc(channel->endpoint)) {
-			/* don't expect iso out endpoints */
-			iso_size = usb_maxpacket(instance->usb_dev, channel->endpoint, 0);
-			iso_size -= iso_size % channel->stride;	/* alignment */
-			BUG_ON(!iso_size);
-			iso_packets = (channel->buf_size - 1) / iso_size + 1;
-		}
+		UDSL_ASSERT(!usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint));
 
 		urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
 		if (!urb) {
-			dev_dbg(dev, "%s: no memory for urb %d!\n", __func__, i);
+			dev_err(dev, "%s: no memory for urb %d!\n", __func__, i);
+			error = -ENOMEM;
 			goto fail_unbind;
 		}
 
 		instance->urbs[i] = urb;
 
-		buffer = kmalloc(channel->buf_size, GFP_KERNEL);
+		/* zero the tx padding to avoid leaking information */
+		buffer = kzalloc(channel->buf_size, GFP_KERNEL);
 		if (!buffer) {
-			dev_dbg(dev, "%s: no memory for buffer %d!\n", __func__, i);
+			dev_err(dev, "%s: no memory for buffer %d!\n", __func__, i);
+			error = -ENOMEM;
 			goto fail_unbind;
 		}
-		memset(buffer, 0, channel->buf_size);
 
 		usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint,
 				  buffer, channel->buf_size, usbatm_complete, channel);
@@ -1065,9 +1201,8 @@
 			urb->transfer_flags = URB_ISO_ASAP;
 			urb->number_of_packets = iso_packets;
 			for (j = 0; j < iso_packets; j++) {
-				urb->iso_frame_desc[j].offset = iso_size * j;
-				urb->iso_frame_desc[j].length = min_t(int, iso_size,
-								      channel->buf_size - urb->iso_frame_desc[j].offset);
+				urb->iso_frame_desc[j].offset = channel->packet_size * j;
+				urb->iso_frame_desc[j].length = channel->packet_size;
 			}
 		}
 
@@ -1079,7 +1214,17 @@
 		     __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);
 	}
 
-	if (need_heavy && driver->heavy_init) {
+	instance->cached_vpi = ATM_VPI_UNSPEC;
+	instance->cached_vci = ATM_VCI_UNSPEC;
+	instance->cell_buf = kmalloc(instance->rx_channel.stride, GFP_KERNEL);
+
+	if (!instance->cell_buf) {
+		dev_err(dev, "%s: no memory for cell buffer!\n", __func__);
+		error = -ENOMEM;
+		goto fail_unbind;
+	}
+
+	if (!(instance->flags & UDSL_SKIP_HEAVY_INIT) && driver->heavy_init) {
 		error = usbatm_heavy_init(instance);
 	} else {
 		complete(&instance->thread_exited);	/* pretend that heavy_init was run */
@@ -1098,6 +1243,8 @@
 	if (instance->driver->unbind)
 		instance->driver->unbind(instance, intf);
  fail_free:
+	kfree(instance->cell_buf);
+
 	for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
 		if (instance->urbs[i])
 			kfree(instance->urbs[i]->transfer_buffer);
@@ -1114,6 +1261,7 @@
 {
 	struct device *dev = &intf->dev;
 	struct usbatm_data *instance = usb_get_intfdata(intf);
+	struct usbatm_vcc_data *vcc_data;
 	int i;
 
 	dev_dbg(dev, "%s entered\n", __func__);
@@ -1125,13 +1273,19 @@
 
 	usb_set_intfdata(intf, NULL);
 
-	down(&instance->serialize);
+	mutex_lock(&instance->serialize);
+	instance->disconnected = 1;
 	if (instance->thread_pid >= 0)
 		kill_proc(instance->thread_pid, SIGTERM, 1);
-	up(&instance->serialize);
+	mutex_unlock(&instance->serialize);
 
 	wait_for_completion(&instance->thread_exited);
 
+	mutex_lock(&instance->serialize);
+	list_for_each_entry(vcc_data, &instance->vcc_list, list)
+		vcc_release_async(vcc_data->vcc, -EPIPE);
+	mutex_unlock(&instance->serialize);
+
 	tasklet_disable(&instance->rx_channel.tasklet);
 	tasklet_disable(&instance->tx_channel.tasklet);
 
@@ -1141,6 +1295,14 @@
 	del_timer_sync(&instance->rx_channel.delay);
 	del_timer_sync(&instance->tx_channel.delay);
 
+	/* turn usbatm_[rt]x_process into something close to a no-op */
+	/* no need to take the spinlock */
+	INIT_LIST_HEAD(&instance->rx_channel.list);
+	INIT_LIST_HEAD(&instance->tx_channel.list);
+
+	tasklet_enable(&instance->rx_channel.tasklet);
+	tasklet_enable(&instance->tx_channel.tasklet);
+
 	if (instance->atm_dev && instance->driver->atm_stop)
 		instance->driver->atm_stop(instance, instance->atm_dev);
 
@@ -1149,19 +1311,13 @@
 
 	instance->driver_data = NULL;
 
-	/* turn usbatm_[rt]x_process into noop */
-	/* no need to take the spinlock */
-	INIT_LIST_HEAD(&instance->rx_channel.list);
-	INIT_LIST_HEAD(&instance->tx_channel.list);
-
-	tasklet_enable(&instance->rx_channel.tasklet);
-	tasklet_enable(&instance->tx_channel.tasklet);
-
 	for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
 		kfree(instance->urbs[i]->transfer_buffer);
 		usb_free_urb(instance->urbs[i]);
 	}
 
+	kfree(instance->cell_buf);
+
 	/* ATM finalize */
 	if (instance->atm_dev)
 		atm_dev_deregister(instance->atm_dev);
@@ -1186,10 +1342,10 @@
 
 	if ((num_rcv_urbs > UDSL_MAX_RCV_URBS)
 	    || (num_snd_urbs > UDSL_MAX_SND_URBS)
-	    || (rcv_buf_size < 1)
-	    || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE)
-	    || (snd_buf_size < 1)
-	    || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE))
+	    || (rcv_buf_bytes < 1)
+	    || (rcv_buf_bytes > UDSL_MAX_BUF_SIZE)
+	    || (snd_buf_bytes < 1)
+	    || (snd_buf_bytes > UDSL_MAX_BUF_SIZE))
 		return -EINVAL;
 
 	return 0;
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
index 1adacd6..ff8551e 100644
--- a/drivers/usb/atm/usbatm.h
+++ b/drivers/usb/atm/usbatm.h
@@ -24,21 +24,21 @@
 #ifndef	_USBATM_H_
 #define	_USBATM_H_
 
-#include <linux/config.h>
-
-/*
-#define VERBOSE_DEBUG
-*/
-
 #include <asm/semaphore.h>
 #include <linux/atm.h>
 #include <linux/atmdev.h>
 #include <linux/completion.h>
 #include <linux/device.h>
+#include <linux/kernel.h>
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/stringify.h>
 #include <linux/usb.h>
+#include <linux/mutex.h>
+
+/*
+#define VERBOSE_DEBUG
+*/
 
 #ifdef DEBUG
 #define UDSL_ASSERT(x)	BUG_ON(!(x))
@@ -52,8 +52,13 @@
 	dev_info(&(instance)->usb_intf->dev , format , ## arg)
 #define usb_warn(instance, format, arg...)	\
 	dev_warn(&(instance)->usb_intf->dev , format , ## arg)
+#ifdef DEBUG
 #define usb_dbg(instance, format, arg...)	\
-	dev_dbg(&(instance)->usb_intf->dev , format , ## arg)
+        dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg)
+#else
+#define usb_dbg(instance, format, arg...)	\
+	do {} while (0)
+#endif
 
 /* FIXME: move to dev_* once ATM is driver model aware */
 #define atm_printk(level, instance, format, arg...)	\
@@ -69,12 +74,24 @@
 #ifdef DEBUG
 #define atm_dbg(instance, format, arg...)	\
 	atm_printk(KERN_DEBUG, instance , format , ## arg)
+#define atm_rldbg(instance, format, arg...)	\
+	if (printk_ratelimit())				\
+		atm_printk(KERN_DEBUG, instance , format , ## arg)
 #else
 #define atm_dbg(instance, format, arg...)	\
 	do {} while (0)
+#define atm_rldbg(instance, format, arg...)	\
+	do {} while (0)
 #endif
 
 
+/* flags, set by mini-driver in bind() */
+
+#define UDSL_SKIP_HEAVY_INIT	(1<<0)
+#define UDSL_USE_ISOC		(1<<1)
+#define UDSL_IGNORE_EILSEQ	(1<<2)
+
+
 /* mini driver */
 
 struct usbatm_data;
@@ -86,16 +103,11 @@
 */
 
 struct usbatm_driver {
-	struct module *owner;
-
 	const char *driver_name;
 
-	/*
-	*  init device ... can sleep, or cause probe() failure.  Drivers with a heavy_init
-	*  method can avoid having it called by setting need_heavy_init to zero.
-	*/
+	/* init device ... can sleep, or cause probe() failure */
         int (*bind) (struct usbatm_data *, struct usb_interface *,
-		     const struct usb_device_id *id, int *need_heavy_init);
+		     const struct usb_device_id *id);
 
 	/* additional device initialization that is too slow to be done in probe() */
         int (*heavy_init) (struct usbatm_data *, struct usb_interface *);
@@ -109,8 +121,9 @@
 	/* cleanup ATM device ... can sleep, but can't fail */
 	void (*atm_stop) (struct usbatm_data *, struct atm_dev *);
 
-        int in;		/* rx endpoint */
-        int out;	/* tx endpoint */
+        int bulk_in;	/* bulk rx endpoint */
+        int isoc_in;	/* isochronous rx endpoint */
+        int bulk_out;	/* bulk tx endpoint */
 
 	unsigned rx_padding;
 	unsigned tx_padding;
@@ -125,6 +138,7 @@
 	int endpoint;			/* usb pipe */
 	unsigned int stride;		/* ATM cell size + padding */
 	unsigned int buf_size;		/* urb buffer size */
+	unsigned int packet_size;	/* endpoint maxpacket */
 	spinlock_t lock;
 	struct list_head list;
 	struct tasklet_struct tasklet;
@@ -143,6 +157,7 @@
 	struct usbatm_driver *driver;
 	void *driver_data;
 	char driver_name[16];
+	unsigned int flags; /* set by mini-driver in bind() */
 
 	/* USB device */
 	struct usb_device *usb_dev;
@@ -157,7 +172,8 @@
         ********************************/
 
 	struct kref refcount;
-	struct semaphore serialize;
+	struct mutex serialize;
+	int disconnected;
 
 	/* heavy init */
 	int thread_pid;
@@ -171,7 +187,14 @@
 	struct usbatm_channel tx_channel;
 
 	struct sk_buff_head sndqueue;
-	struct sk_buff *current_skb;			/* being emptied */
+	struct sk_buff *current_skb;	/* being emptied */
+
+	struct usbatm_vcc_data *cached_vcc;
+	int cached_vci;
+	short cached_vpi;
+
+	unsigned char *cell_buf;	/* holds partial rx cell */
+	unsigned int buf_usage;
 
 	struct urb *urbs[0];
 };
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index 5c76e3a..42d6823 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -41,6 +41,8 @@
 XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number");
 XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)");
 XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)");
+XUSBATM_PARM(rx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
+XUSBATM_PARM(tx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
 
 static const char xusbatm_driver_name[] = "xusbatm";
 
@@ -48,82 +50,118 @@
 static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1];
 static struct usb_driver xusbatm_usb_driver;
 
-static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep)
+static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int altsetting, u8 ep)
 {
+	struct usb_host_interface *alt;
+	struct usb_interface *intf;
 	int i, j;
 
-	for (i = 0; i < intf->num_altsetting; i++) {
-		struct usb_host_interface *alt = intf->altsetting;
-		for (j = 0; j < alt->desc.bNumEndpoints; j++)
-			if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep)
-				return 1;
+	for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++)
+		if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting)))
+			for (j = 0; j < alt->desc.bNumEndpoints; j++)
+				if (alt->endpoint[j].desc.bEndpointAddress == ep)
+					return intf;
+	return NULL;
+}
+
+static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device *usb_dev,
+		struct usb_interface *intf, int altsetting, int claim)
+{
+	int ifnum = intf->altsetting->desc.bInterfaceNumber;
+	int ret;
+
+	if (claim && (ret = usb_driver_claim_interface(&xusbatm_usb_driver, intf, usbatm))) {
+		usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, ifnum, ret);
+		return ret;
+	}
+	if ((ret = usb_set_interface(usb_dev, ifnum, altsetting))) {
+		usb_err(usbatm, "%s: altsetting %2d for interface %2d failed (%d)!\n", __func__, altsetting, ifnum, ret);
+		return ret;
 	}
 	return 0;
 }
 
-static int xusbatm_bind(struct usbatm_data *usbatm_instance,
-			struct usb_interface *intf, const struct usb_device_id *id,
-			int *need_heavy_init)
+static void xusbatm_release_intf (struct usb_device *usb_dev, struct usb_interface *intf, int claimed)
+{
+	if (claimed) {
+		usb_set_intfdata(intf, NULL);
+		usb_driver_release_interface(&xusbatm_usb_driver, intf);
+	}
+}
+
+static int xusbatm_bind(struct usbatm_data *usbatm,
+			struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *usb_dev = interface_to_usbdev(intf);
 	int drv_ix = id - xusbatm_usb_ids;
-	int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]);
-	int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]);
-	u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix];
-	int i, ret;
+	int rx_alt = rx_altsetting[drv_ix];
+	int tx_alt = tx_altsetting[drv_ix];
+	struct usb_interface *rx_intf = xusbatm_find_intf(usb_dev, rx_alt, rx_endpoint[drv_ix]);
+	struct usb_interface *tx_intf = xusbatm_find_intf(usb_dev, tx_alt, tx_endpoint[drv_ix]);
+	int ret;
 
-	usb_dbg(usbatm_instance, "%s: binding driver %d: vendor %#x product %#x"
-		" rx: ep %#x padd %d tx: ep %#x padd %d\n",
+	usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x"
+		" rx: ep %02x padd %d alt %2d tx: ep %02x padd %d alt %2d\n",
 		__func__, drv_ix, vendor[drv_ix], product[drv_ix],
-		rx_endpoint[drv_ix], rx_padding[drv_ix],
-		tx_endpoint[drv_ix], tx_padding[drv_ix]);
+		rx_endpoint[drv_ix], rx_padding[drv_ix], rx_alt,
+		tx_endpoint[drv_ix], tx_padding[drv_ix], tx_alt);
 
-	if (!rx_ep_present && !tx_ep_present) {
-		usb_dbg(usbatm_instance, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n",
-			__func__, intf->altsetting->desc.bInterfaceNumber,
-			rx_endpoint[drv_ix], tx_endpoint[drv_ix]);
+	if (!rx_intf || !tx_intf) {
+		if (!rx_intf)
+			usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
+				__func__, rx_endpoint[drv_ix], rx_alt);
+		if (!tx_intf)
+			usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
+				__func__, tx_endpoint[drv_ix], tx_alt);
 		return -ENODEV;
 	}
 
-	if (rx_ep_present && tx_ep_present)
-		return 0;
+	if ((rx_intf != intf) && (tx_intf != intf))
+		return -ENODEV;
 
-	for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
-		struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
-
-		if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) {
-			ret = usb_driver_claim_interface(&xusbatm_usb_driver,
-							 cur_if, usbatm_instance);
-			if (!ret)
-				usb_err(usbatm_instance, "%s: failed to claim interface #%d (%d)\n",
-					__func__, cur_if->altsetting->desc.bInterfaceNumber, ret);
-			return ret;
-		}
+	if ((rx_intf == tx_intf) && (rx_alt != tx_alt)) {
+		usb_err(usbatm, "%s: altsettings clash on interface %2d (%2d vs %2d)!\n", __func__,
+				rx_intf->altsetting->desc.bInterfaceNumber, rx_alt, tx_alt);
+		return -EINVAL;
 	}
 
-	usb_err(usbatm_instance, "%s: no interface has endpoint %#x\n",
-		__func__, searched_ep);
-	return -ENODEV;
+	usb_dbg(usbatm, "%s: rx If#=%2d; tx If#=%2d\n", __func__,
+			rx_intf->altsetting->desc.bInterfaceNumber,
+			tx_intf->altsetting->desc.bInterfaceNumber);
+
+	if ((ret = xusbatm_capture_intf(usbatm, usb_dev, rx_intf, rx_alt, rx_intf != intf)))
+		return ret;
+
+	if ((tx_intf != rx_intf) && (ret = xusbatm_capture_intf(usbatm, usb_dev, tx_intf, tx_alt, tx_intf != intf))) {
+		xusbatm_release_intf(usb_dev, rx_intf, rx_intf != intf);
+		return ret;
+	}
+
+	return 0;
 }
 
-static void xusbatm_unbind(struct usbatm_data *usbatm_instance,
+static void xusbatm_unbind(struct usbatm_data *usbatm,
 			   struct usb_interface *intf)
 {
 	struct usb_device *usb_dev = interface_to_usbdev(intf);
 	int i;
-	usb_dbg(usbatm_instance, "%s entered\n", __func__);
+
+	usb_dbg(usbatm, "%s entered\n", __func__);
 
 	for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
-		struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
-		usb_set_intfdata(cur_if, NULL);
-		usb_driver_release_interface(&xusbatm_usb_driver, cur_if);
+		struct usb_interface *cur_intf = usb_dev->actconfig->interface[i];
+
+		if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) {
+			usb_set_intfdata(cur_intf, NULL);
+			usb_driver_release_interface(&xusbatm_usb_driver, cur_intf);
+		}
 	}
 }
 
-static int xusbatm_atm_start(struct usbatm_data *usbatm_instance,
+static int xusbatm_atm_start(struct usbatm_data *usbatm,
 			     struct atm_dev *atm_dev)
 {
-	atm_dbg(usbatm_instance, "%s entered\n", __func__);
+	atm_dbg(usbatm, "%s entered\n", __func__);
 
 	/* use random MAC as we've no way to get it from the device */
 	random_ether_addr(atm_dev->esi);
@@ -161,18 +199,19 @@
 	}
 
 	for (i = 0; i < num_vendor; i++) {
+		rx_endpoint[i] |= USB_DIR_IN;
+		tx_endpoint[i] &= USB_ENDPOINT_NUMBER_MASK;
+
 		xusbatm_usb_ids[i].match_flags	= USB_DEVICE_ID_MATCH_DEVICE;
 		xusbatm_usb_ids[i].idVendor	= vendor[i];
 		xusbatm_usb_ids[i].idProduct	= product[i];
 
-
-		xusbatm_drivers[i].owner	= THIS_MODULE;
 		xusbatm_drivers[i].driver_name	= xusbatm_driver_name;
 		xusbatm_drivers[i].bind		= xusbatm_bind;
 		xusbatm_drivers[i].unbind	= xusbatm_unbind;
 		xusbatm_drivers[i].atm_start	= xusbatm_atm_start;
-		xusbatm_drivers[i].in		= rx_endpoint[i];
-		xusbatm_drivers[i].out		= tx_endpoint[i];
+		xusbatm_drivers[i].bulk_in	= rx_endpoint[i];
+		xusbatm_drivers[i].bulk_out	= tx_endpoint[i];
 		xusbatm_drivers[i].rx_padding	= rx_padding[i];
 		xusbatm_drivers[i].tx_padding	= tx_padding[i];
 	}
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index b9fd39f..97bdeb1 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1014,8 +1014,13 @@
 	}
 
 	down(&open_sem);
+	if (!usb_get_intfdata(intf)) {
+		up(&open_sem);
+		return;
+	}
 	acm->dev = NULL;
-	usb_set_intfdata (intf, NULL);
+	usb_set_intfdata(acm->control, NULL);
+	usb_set_intfdata(acm->data, NULL);
 
 	tasklet_disable(&acm->urb_task);
 
@@ -1036,7 +1041,7 @@
 	for (i = 0; i < ACM_NRB; i++)
 		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
 
-	usb_driver_release_interface(&acm_driver, acm->data);
+	usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf);
 
 	if (!acm->used) {
 		acm_tty_unregister(acm);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index dba4cc0..d34848a 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -7,6 +7,7 @@
  * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
  # Copyright (c) 2001 Pete Zaitcev	<zaitcev@redhat.com>
  # Copyright (c) 2001 David Paschal	<paschal@rcsis.com>
+ * Copyright (c) 2006 Oliver Neukum	<oliver@neukum.name>
  *
  * USB Printer Device Class driver for USB printers and printer cables
  *
@@ -273,13 +274,16 @@
 {
 	struct usblp *usblp = urb->context;
 
-	if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
+	if (unlikely(!usblp || !usblp->dev || !usblp->used))
 		return;
 
+	if (unlikely(!usblp->present))
+		goto unplug;
 	if (unlikely(urb->status))
 		warn("usblp%d: nonzero read/write bulk status received: %d",
 			usblp->minor, urb->status);
 	usblp->rcomplete = 1;
+unplug:
 	wake_up_interruptible(&usblp->wait);
 }
 
@@ -287,13 +291,15 @@
 {
 	struct usblp *usblp = urb->context;
 
-	if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
+	if (unlikely(!usblp || !usblp->dev || !usblp->used))
 		return;
-
+	if (unlikely(!usblp->present))
+		goto unplug;
 	if (unlikely(urb->status))
 		warn("usblp%d: nonzero read/write bulk status received: %d",
 			usblp->minor, urb->status);
 	usblp->wcomplete = 1;
+unplug:
 	wake_up_interruptible(&usblp->wait);
 }
 
@@ -627,9 +633,8 @@
 
 static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-	DECLARE_WAITQUEUE(wait, current);
 	struct usblp *usblp = file->private_data;
-	int timeout, err = 0, transfer_length = 0;
+	int timeout, rv, err = 0, transfer_length = 0;
 	size_t writecount = 0;
 
 	while (writecount < count) {
@@ -641,24 +646,11 @@
 			}
 
 			timeout = USBLP_WRITE_TIMEOUT;
-			add_wait_queue(&usblp->wait, &wait);
-			while ( 1==1 ) {
 
-				if (signal_pending(current)) {
-					remove_wait_queue(&usblp->wait, &wait);
-					return writecount ? writecount : -EINTR;
-				}
-				set_current_state(TASK_INTERRUPTIBLE);
-				if (timeout && !usblp->wcomplete) {
-					timeout = schedule_timeout(timeout);
-				} else {
-					set_current_state(TASK_RUNNING);
-					break;
-				}
-			}
-			remove_wait_queue(&usblp->wait, &wait);
+			rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout);
+			if (rv < 0)
+				return writecount ? writecount : -EINTR;
 		}
-
 		down (&usblp->sem);
 		if (!usblp->present) {
 			up (&usblp->sem);
@@ -724,7 +716,7 @@
 static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct usblp *usblp = file->private_data;
-	DECLARE_WAITQUEUE(wait, current);
+	int rv;
 
 	if (!usblp->bidir)
 		return -EINVAL;
@@ -742,26 +734,13 @@
 			count = -EAGAIN;
 			goto done;
 		}
-
-		add_wait_queue(&usblp->wait, &wait);
-		while (1==1) {
-			if (signal_pending(current)) {
-				count = -EINTR;
-				remove_wait_queue(&usblp->wait, &wait);
-				goto done;
-			}
-			up (&usblp->sem);
-			set_current_state(TASK_INTERRUPTIBLE);
-			if (!usblp->rcomplete) {
-				schedule();
-			} else {
-				set_current_state(TASK_RUNNING);
-				down(&usblp->sem);
-				break;
-			}
-			down (&usblp->sem);
+		up(&usblp->sem);
+		rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
+		down(&usblp->sem);
+		if (rv < 0) {
+			count = -EINTR;
+			goto done;
 		}
-		remove_wait_queue(&usblp->wait, &wait);
 	}
 
 	if (!usblp->present) {
@@ -874,11 +853,10 @@
 
 	/* Malloc and start initializing usblp structure so we can use it
 	 * directly. */
-	if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
+	if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
 		err("out of memory for usblp");
 		goto abort;
 	}
-	memset(usblp, 0, sizeof(struct usblp));
 	usblp->dev = dev;
 	init_MUTEX (&usblp->sem);
 	init_waitqueue_head(&usblp->wait);
@@ -1214,10 +1192,9 @@
 {
 	int retval;
 	retval = usb_register(&usblp_driver);
-	if (retval)
-		goto out;
-	info(DRIVER_VERSION ": " DRIVER_DESC);
-out:
+	if (!retval)
+		info(DRIVER_VERSION ": " DRIVER_DESC);
+
 	return retval;
 }
 
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 076462c..dce9d98 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -378,7 +378,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(usb_match_id);
+EXPORT_SYMBOL(usb_match_id);
 
 int usb_device_match(struct device *dev, struct device_driver *drv)
 {
@@ -446,7 +446,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL_GPL(usb_register_driver);
+EXPORT_SYMBOL(usb_register_driver);
 
 /**
  * usb_deregister - unregister a USB driver
@@ -469,4 +469,4 @@
 
 	usbfs_update_special();
 }
-EXPORT_SYMBOL_GPL(usb_deregister);
+EXPORT_SYMBOL(usb_deregister);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 319de03..7135e54 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -13,6 +13,7 @@
 #include <linux/ctype.h>
 #include <linux/device.h>
 #include <asm/byteorder.h>
+#include <asm/scatterlist.h>
 
 #include "hcd.h"	/* for usbcore internals */
 #include "usb.h"
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 0817967..dad4d8f 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -468,6 +468,7 @@
  */
 void usb_kill_urb(struct urb *urb)
 {
+	might_sleep();
 	if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op))
 		return;
 	spin_lock_irq(&urb->lock);
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 9a4edc5..0aab7d2 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -135,6 +135,7 @@
 					setup_out_ready : 1,
 					setup_out_error : 1,
 					setup_abort : 1;
+	unsigned			setup_wLength;
 
 	/* the rest is basically write-once */
 	struct usb_config_descriptor	*config, *hs_config;
@@ -942,6 +943,7 @@
 	}
 	req->complete = ep0_complete;
 	req->length = len;
+	req->zero = 0;
 	return 0;
 }
 
@@ -1161,10 +1163,13 @@
 				spin_unlock_irq (&dev->lock);
 				if (copy_from_user (dev->req->buf, buf, len))
 					retval = -EFAULT;
-				else
+				else {
+					if (len < dev->setup_wLength)
+						dev->req->zero = 1;
 					retval = usb_ep_queue (
 						dev->gadget->ep0, dev->req,
 						GFP_KERNEL);
+				}
 				if (retval < 0) {
 					spin_lock_irq (&dev->lock);
 					clean_req (dev->gadget->ep0, dev->req);
@@ -1483,6 +1488,7 @@
 delegate:
 			dev->setup_in = (ctrl->bRequestType & USB_DIR_IN)
 						? 1 : 0;
+			dev->setup_wLength = w_length;
 			dev->setup_out_ready = 0;
 			dev->setup_out_error = 0;
 			value = 0;
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index c32e1f7..67b13ab 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -47,6 +47,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 2fc110d..ae7a1c0 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -165,8 +165,8 @@
 static unsigned qlen = 32;
 static unsigned pattern = 0;
 
-module_param (buflen, uint, S_IRUGO|S_IWUSR);
-module_param (qlen, uint, S_IRUGO|S_IWUSR);
+module_param (buflen, uint, S_IRUGO);
+module_param (qlen, uint, S_IRUGO);
 module_param (pattern, uint, S_IRUGO|S_IWUSR);
 
 /*
@@ -1127,8 +1127,10 @@
 	DBG (dev, "unbind\n");
 
 	/* we've already been disconnected ... no i/o is active */
-	if (dev->req)
+	if (dev->req) {
+		dev->req->length = USB_BUFSIZ;
 		free_ep_req (gadget->ep0, dev->req);
+	}
 	del_timer_sync (&dev->resume);
 	kfree (dev);
 	set_gadget_data (gadget, NULL);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 08ca0f8..3a6687d 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -24,46 +24,11 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
- * off the controller (maybe it can boot from highspeed USB disks).
- */
-static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap)
-{
-	struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-
-	/* always say Linux will own the hardware */
-	pci_write_config_byte(pdev, where + 3, 1);
-
-	/* maybe wait a while for BIOS to respond */
-	if (cap & (1 << 16)) {
-		int msec = 5000;
-
-		do {
-			msleep(10);
-			msec -= 10;
-			pci_read_config_dword(pdev, where, &cap);
-		} while ((cap & (1 << 16)) && msec);
-		if (cap & (1 << 16)) {
-			ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
-				where, cap);
-			// some BIOS versions seem buggy...
-			// return 1;
-			ehci_warn(ehci, "continuing after BIOS bug...\n");
-			/* disable all SMIs, and clear "BIOS owns" flag */
-			pci_write_config_dword(pdev, where + 4, 0);
-			pci_write_config_byte(pdev, where + 2, 0);
-		} else
-			ehci_dbg(ehci, "BIOS handoff succeeded\n");
-	}
-	return 0;
-}
-
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
 {
 	u32			temp;
 	int			retval;
-	unsigned		count = 256/4;
 
 	/* optional debug port, normally in the first BAR */
 	temp = pci_find_capability(pdev, 0x0a);
@@ -84,32 +49,9 @@
 		}
 	}
 
-	temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params));
-
-	/* EHCI 0.96 and later may have "extended capabilities" */
-	while (temp && count--) {
-		u32		cap;
-
-		pci_read_config_dword(pdev, temp, &cap);
-		ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp);
-		switch (cap & 0xff) {
-		case 1:			/* BIOS/SMM/... handoff */
-			if (bios_handoff(ehci, temp, cap) != 0)
-				return -EOPNOTSUPP;
-			break;
-		case 0:			/* illegal reserved capability */
-			ehci_dbg(ehci, "illegal capability!\n");
-			cap = 0;
-			/* FALLTHROUGH */
-		default:		/* unknown */
-			break;
-		}
-		temp = (cap >> 8) & 0xff;
-	}
-	if (!count) {
-		ehci_err(ehci, "bogus capabilities ... PCI problems!\n");
-		return -EIO;
-	}
+	/* we expect static quirk code to handle the "extended capabilities"
+	 * (currently just BIOS handoff) allowed starting with EHCI 0.96
+	 */
 
 	/* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */
 	retval = pci_set_mwi(pdev);
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 57e7737..ebcca97 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1063,6 +1063,7 @@
 
 		/* for IN, check CSPLIT */
 		if (stream->c_usecs) {
+			uf = uframe & 7;
 			max_used = 100 - stream->c_usecs;
 			do {
 				tmp = 1 << uf;
@@ -1843,8 +1844,7 @@
 #else
 
 static inline int
-sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
-	unsigned mem_flags)
+sitd_submit (struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags)
 {
 	ehci_dbg (ehci, "split iso support is disabled\n");
 	return -ENOSYS;
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 584b8dc..972ce04 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1420,20 +1420,22 @@
 	int ret = 0;
 
 	spin_lock_irqsave(&isp116x->lock, flags);
-
 	val = isp116x_read_reg32(isp116x, HCCONTROL);
+
 	switch (val & HCCONTROL_HCFS) {
 	case HCCONTROL_USB_OPER:
+		spin_unlock_irqrestore(&isp116x->lock, flags);
 		val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
 		val |= HCCONTROL_USB_SUSPEND;
 		if (device_may_wakeup(&hcd->self.root_hub->dev))
 			val |= HCCONTROL_RWE;
 		/* Wait for usb transfers to finish */
-		mdelay(2);
+		msleep(2);
+		spin_lock_irqsave(&isp116x->lock, flags);
 		isp116x_write_reg32(isp116x, HCCONTROL, val);
+		spin_unlock_irqrestore(&isp116x->lock, flags);
 		/* Wait for devices to suspend */
-		mdelay(5);
-	case HCCONTROL_USB_SUSPEND:
+		msleep(5);
 		break;
 	case HCCONTROL_USB_RESUME:
 		isp116x_write_reg32(isp116x, HCCONTROL,
@@ -1441,12 +1443,11 @@
 				    HCCONTROL_USB_RESET);
 	case HCCONTROL_USB_RESET:
 		ret = -EBUSY;
+	default:		/* HCCONTROL_USB_SUSPEND */
+		spin_unlock_irqrestore(&isp116x->lock, flags);
 		break;
-	default:
-		ret = -EINVAL;
 	}
 
-	spin_unlock_irqrestore(&isp116x->lock, flags);
 	return ret;
 }
 
@@ -1715,9 +1716,9 @@
 	.remove = isp116x_remove,
 	.suspend = isp116x_suspend,
 	.resume = isp116x_resume,
-	.driver	= {
-		.name = (char *)hcd_name,
-	},
+	.driver = {
+		   .name = (char *)hcd_name,
+		   },
 };
 
 /*-----------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 77cd6ac..db280ca 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -67,7 +67,7 @@
 	       ": stopping Au1xxx OHCI USB Controller\n");
 
 	/* Disable clock */
-	au_writel(readl((void *)USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
+	au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
 }
 
 
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 3ef2c0c..e9e5bc1 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -190,7 +190,7 @@
 			msleep(10);
 		}
 		if (wait_time <= 0)
-			printk(KERN_WARNING "%s %s: early BIOS handoff "
+			printk(KERN_WARNING "%s %s: BIOS handoff "
 					"failed (BIOS bug ?)\n",
 					pdev->dev.bus_id, "OHCI");
 
@@ -212,8 +212,9 @@
 {
 	int wait_time, delta;
 	void __iomem *base, *op_reg_base;
-	u32 hcc_params, val, temp;
-	u8 cap_length;
+	u32	hcc_params, val;
+	u8	offset, cap_length;
+	int	count = 256/4;
 
 	if (!mmio_resource_enabled(pdev, 0))
 		return;
@@ -224,51 +225,80 @@
 
 	cap_length = readb(base);
 	op_reg_base = base + cap_length;
-	hcc_params = readl(base + EHCI_HCC_PARAMS);
-	hcc_params = (hcc_params >> 8) & 0xff;
-	if (hcc_params) {
-		pci_read_config_dword(pdev,
-					hcc_params + EHCI_USBLEGSUP,
-					&val);
-		if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
-			/*
-			 * Ok, BIOS is in smm mode, try to hand off...
-			 */
-			pci_read_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						&temp);
-			pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						temp | EHCI_USBLEGCTLSTS_SOOE);
-			val |= EHCI_USBLEGSUP_OS;
-			pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
-						val);
 
-			wait_time = 500;
-			do {
-				msleep(10);
-				wait_time -= 10;
-				pci_read_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
-						&val);
-			} while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
-			if (!wait_time) {
-				/*
-				 * well, possibly buggy BIOS...
+	/* EHCI 0.96 and later may have "extended capabilities"
+	 * spec section 5.1 explains the bios handoff, e.g. for
+	 * booting from USB disk or using a usb keyboard
+	 */
+	hcc_params = readl(base + EHCI_HCC_PARAMS);
+	offset = (hcc_params >> 8) & 0xff;
+	while (offset && count--) {
+		u32		cap;
+		int		msec;
+
+		pci_read_config_dword(pdev, offset, &cap);
+		switch (cap & 0xff) {
+		case 1:			/* BIOS/SMM/... handoff support */
+			if ((cap & EHCI_USBLEGSUP_BIOS)) {
+				pr_debug("%s %s: BIOS handoff\n",
+						pdev->dev.bus_id, "EHCI");
+
+				/* BIOS workaround (?): be sure the
+				 * pre-Linux code receives the SMI
 				 */
-				printk(KERN_WARNING "%s %s: early BIOS handoff "
+				pci_read_config_dword(pdev,
+						offset + EHCI_USBLEGCTLSTS,
+						&val);
+				pci_write_config_dword(pdev,
+						offset + EHCI_USBLEGCTLSTS,
+						val | EHCI_USBLEGCTLSTS_SOOE);
+			}
+
+			/* always say Linux will own the hardware
+			 * by setting EHCI_USBLEGSUP_OS.
+			 */
+			pci_write_config_byte(pdev, offset + 3, 1);
+
+			/* if boot firmware now owns EHCI, spin till
+			 * it hands it over.
+			 */
+			msec = 5000;
+			while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
+				msleep(10);
+				msec -= 10;
+				pci_read_config_dword(pdev, offset, &cap);
+			}
+
+			if (cap & EHCI_USBLEGSUP_BIOS) {
+				/* well, possibly buggy BIOS... try to shut
+				 * it down, and hope nothing goes too wrong
+				 */
+				printk(KERN_WARNING "%s %s: BIOS handoff "
 						"failed (BIOS bug ?)\n",
 					pdev->dev.bus_id, "EHCI");
-				pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
-						EHCI_USBLEGSUP_OS);
-				pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						0);
+				pci_write_config_byte(pdev, offset + 2, 0);
 			}
+
+			/* just in case, always disable EHCI SMIs */
+			pci_write_config_dword(pdev,
+					offset + EHCI_USBLEGCTLSTS,
+					0);
+			break;
+		case 0:			/* illegal reserved capability */
+			cap = 0;
+			/* FALLTHROUGH */
+		default:
+			printk(KERN_WARNING "%s %s: unrecognized "
+					"capability %02x\n",
+					pdev->dev.bus_id, "EHCI",
+					cap & 0xff);
+			break;
 		}
+		offset = (cap >> 8) & 0xff;
 	}
+	if (!count)
+		printk(KERN_DEBUG "%s %s: capability loop?\n",
+				pdev->dev.bus_id, "EHCI");
 
 	/*
 	 * halt EHCI & disable its interrupts in any case
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index b607600..7823980 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -672,9 +672,9 @@
 	/* Low-speed transfers get a different queue, and won't hog the bus.
 	 * Also, some devices enumerate better without FSBR; the easiest way
 	 * to do that is to put URBs on the low-speed queue while the device
-	 * is in the DEFAULT state. */
+	 * isn't in the CONFIGURED state. */
 	if (urb->dev->speed == USB_SPEED_LOW ||
-			urb->dev->state == USB_STATE_DEFAULT)
+			urb->dev->state != USB_STATE_CONFIGURED)
 		skelqh = uhci->skel_ls_control_qh;
 	else {
 		skelqh = uhci->skel_fs_control_qh;
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index a91e72c..6f7a684 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1307,7 +1307,7 @@
 	}
 
 	if (err)
-		warn("timeout initializing reports\n");
+		warn("timeout initializing reports");
 }
 
 #define USB_VENDOR_ID_WACOM		0x056a
@@ -1453,6 +1453,9 @@
 #define USB_VENDOR_ID_CHERRY		0x046a
 #define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
 
+#define USB_VENDOR_ID_HP		0x03f0
+#define USB_DEVICE_ID_HP_USBHUB_KB	0x020c
+
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -1566,6 +1569,7 @@
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET},
 	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
+	{ USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
 
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
@@ -1828,9 +1832,6 @@
 	hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
 	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
 
-	/* May be needed for some devices */
-	usb_clear_halt(hid->dev, hid->urbin->pipe);
-
 	return hid;
 
 fail:
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 4dff847..925f5ab 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -35,7 +35,6 @@
 #include <linux/usb.h>
 #include "hid.h"
 #include <linux/hiddev.h>
-#include <linux/devfs_fs_kernel.h>
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
 #define HIDDEV_MINOR_BASE	0
@@ -632,7 +631,7 @@
 
 			else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
 				 (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
-				  uref->usage_index + uref_multi->num_values >= field->report_count))
+				  uref->usage_index + uref_multi->num_values > field->report_count))
 				goto inval;
 			}
 
@@ -832,12 +831,10 @@
 
 int __init hiddev_init(void)
 {
-	devfs_mk_dir("usb/hid");
 	return usb_register(&hiddev_driver);
 }
 
 void hiddev_exit(void)
 {
 	usb_deregister(&hiddev_driver);
-	devfs_remove("usb/hid");
 }
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 3b3c7b4..697c5e5 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -337,6 +337,9 @@
 			 touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
 			 touchkit_irq, touchkit, endpoint->bInterval);
 
+	touchkit->irq->transfer_dma = touchkit->data_dma;
+	touchkit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
 	input_register_device(touchkit->input);
 
 	usb_set_intfdata(intf, touchkit);
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 1bfc105..37d2f0b 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -59,7 +59,7 @@
 #include "map_to_7segment.h"
 #include "yealink.h"
 
-#define DRIVER_VERSION "yld-20050816"
+#define DRIVER_VERSION "yld-20051230"
 #define DRIVER_AUTHOR "Henk Vergonet"
 #define DRIVER_DESC "Yealink phone driver"
 
@@ -786,16 +786,25 @@
  * Linux interface and usb initialisation
  ******************************************************************************/
 
-static const struct yld_device {
-	u16 idVendor;
-	u16 idProduct;
+struct driver_info {
 	char *name;
-} yld_device[] = {
-	{ 0x6993, 0xb001, "Yealink usb-p1k" },
 };
 
-static struct usb_device_id usb_table [] = {
-	{ USB_INTERFACE_INFO(USB_CLASS_HID, 0, 0) },
+static const struct driver_info info_P1K = {
+	.name	= "Yealink usb-p1k",
+};
+
+static const struct usb_device_id usb_table [] = {
+	{
+		.match_flags		= USB_DEVICE_ID_MATCH_DEVICE |
+						USB_DEVICE_ID_MATCH_INT_INFO,
+		.idVendor		= 0x6993,
+		.idProduct		= 0xb001,
+		.bInterfaceClass	= USB_CLASS_HID,
+		.bInterfaceSubClass	= 0,
+		.bInterfaceProtocol	= 0,
+		.driver_info		= (kernel_ulong_t)&info_P1K
+	},
 	{ }
 };
 
@@ -842,33 +851,16 @@
 	usb_cleanup(yld, 0);
 }
 
-static int usb_match(struct usb_device *udev)
-{
-	int i;
-	u16 idVendor = le16_to_cpu(udev->descriptor.idVendor);
-	u16 idProduct = le16_to_cpu(udev->descriptor.idProduct);
-
-	for (i = 0; i < ARRAY_SIZE(yld_device); i++) {
-		if ((idVendor == yld_device[i].idVendor) &&
-		    (idProduct == yld_device[i].idProduct))
-			return i;
-	}
-	return -ENODEV;
-}
-
 static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev (intf);
+	struct driver_info *nfo = (struct driver_info *)id->driver_info;
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct yealink_dev *yld;
 	struct input_dev *input_dev;
 	int ret, pipe, i;
 
-	i = usb_match(udev);
-	if (i < 0)
-		return -ENODEV;
-
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
 	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
@@ -915,7 +907,7 @@
 	pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
 	ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
 	if (ret != USB_PKT_LEN)
-		err("invalid payload size %d, expected %d", ret, USB_PKT_LEN);
+		err("invalid payload size %d, expected %zd", ret, USB_PKT_LEN);
 
 	/* initialise irq urb */
 	usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data,
@@ -948,7 +940,7 @@
 	strlcat(yld->phys,  "/input0", sizeof(yld->phys));
 
 	/* register settings for the input device */
-	input_dev->name = yld_device[i].name;
+	input_dev->name = nfo->name;
 	input_dev->phys = yld->phys;
 	usb_to_input_id(udev, &input_dev->id);
 	input_dev->cdev.dev = &intf->dev;
diff --git a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
index 21232ee..0d3d2cc 100644
--- a/drivers/usb/media/Kconfig
+++ b/drivers/usb/media/Kconfig
@@ -53,6 +53,21 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called dsbr100.
 
+config USB_ET61X251
+	tristate "USB ET61X[12]51 PC Camera Controller support"
+	depends on USB && VIDEO_DEV
+	---help---
+	  Say Y here if you want support for cameras based on Etoms ET61X151
+	  or ET61X251 PC Camera Controllers.
+
+	  See <file:Documentation/usb/et61x251.txt> for more informations.
+
+	  This driver uses the Video For Linux API. You must say Y or M to
+	  "Video For Linux" to use this driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called et61x251.
+
 config USB_IBMCAM
 	tristate "USB IBM (Xirlink) C-it Camera support"
 	depends on USB && VIDEO_DEV
@@ -209,5 +224,3 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called pwc.
-
-
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
index d83adff..3957aa1 100644
--- a/drivers/usb/media/Makefile
+++ b/drivers/usb/media/Makefile
@@ -3,9 +3,11 @@
 #
 
 sn9c102-objs	:= sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o
+et61x251-objs	:= et61x251_core.o et61x251_tas5130d1b.o
 
 obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
 obj-$(CONFIG_USB_DSBR)		+= dsbr100.o
+obj-$(CONFIG_USB_ET61X251)	+= et61x251.o
 obj-$(CONFIG_USB_IBMCAM)	+= ibmcam.o usbvideo.o ultracam.o
 obj-$(CONFIG_USB_KONICAWC)	+= konicawc.o usbvideo.o
 obj-$(CONFIG_USB_OV511)		+= ov511.o
diff --git a/drivers/usb/media/et61x251.h b/drivers/usb/media/et61x251.h
new file mode 100644
index 0000000..652238f
--- /dev/null
+++ b/drivers/usb/media/et61x251.h
@@ -0,0 +1,220 @@
+/***************************************************************************
+ * V4L2 driver for ET61X[12]51 PC Camera Controllers                       *
+ *                                                                         *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#ifndef _ET61X251_H_
+#define _ET61X251_H_
+
+#include <linux/version.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/types.h>
+#include <linux/param.h>
+#include <linux/rwsem.h>
+#include <asm/semaphore.h>
+
+#include "et61x251_sensor.h"
+
+/*****************************************************************************/
+
+#define ET61X251_DEBUG
+#define ET61X251_DEBUG_LEVEL         2
+#define ET61X251_MAX_DEVICES         64
+#define ET61X251_PRESERVE_IMGSCALE   0
+#define ET61X251_FORCE_MUNMAP        0
+#define ET61X251_MAX_FRAMES          32
+#define ET61X251_COMPRESSION_QUALITY 0
+#define ET61X251_URBS                2
+#define ET61X251_ISO_PACKETS         7
+#define ET61X251_ALTERNATE_SETTING   13
+#define ET61X251_URB_TIMEOUT         msecs_to_jiffies(2 * ET61X251_ISO_PACKETS)
+#define ET61X251_CTRL_TIMEOUT        100
+
+/*****************************************************************************/
+
+static const struct usb_device_id et61x251_id_table[] = {
+	{ USB_DEVICE(0x102c, 0x6151), },
+	{ USB_DEVICE(0x102c, 0x6251), },
+	{ USB_DEVICE(0x102c, 0x6253), },
+	{ USB_DEVICE(0x102c, 0x6254), },
+	{ USB_DEVICE(0x102c, 0x6255), },
+	{ USB_DEVICE(0x102c, 0x6256), },
+	{ USB_DEVICE(0x102c, 0x6257), },
+	{ USB_DEVICE(0x102c, 0x6258), },
+	{ USB_DEVICE(0x102c, 0x6259), },
+	{ USB_DEVICE(0x102c, 0x625a), },
+	{ USB_DEVICE(0x102c, 0x625b), },
+	{ USB_DEVICE(0x102c, 0x625c), },
+	{ USB_DEVICE(0x102c, 0x625d), },
+	{ USB_DEVICE(0x102c, 0x625e), },
+	{ USB_DEVICE(0x102c, 0x625f), },
+	{ USB_DEVICE(0x102c, 0x6260), },
+	{ USB_DEVICE(0x102c, 0x6261), },
+	{ USB_DEVICE(0x102c, 0x6262), },
+	{ USB_DEVICE(0x102c, 0x6263), },
+	{ USB_DEVICE(0x102c, 0x6264), },
+	{ USB_DEVICE(0x102c, 0x6265), },
+	{ USB_DEVICE(0x102c, 0x6266), },
+	{ USB_DEVICE(0x102c, 0x6267), },
+	{ USB_DEVICE(0x102c, 0x6268), },
+	{ USB_DEVICE(0x102c, 0x6269), },
+	{ }
+};
+
+ET61X251_SENSOR_TABLE
+
+/*****************************************************************************/
+
+enum et61x251_frame_state {
+	F_UNUSED,
+	F_QUEUED,
+	F_GRABBING,
+	F_DONE,
+	F_ERROR,
+};
+
+struct et61x251_frame_t {
+	void* bufmem;
+	struct v4l2_buffer buf;
+	enum et61x251_frame_state state;
+	struct list_head frame;
+	unsigned long vma_use_count;
+};
+
+enum et61x251_dev_state {
+	DEV_INITIALIZED = 0x01,
+	DEV_DISCONNECTED = 0x02,
+	DEV_MISCONFIGURED = 0x04,
+};
+
+enum et61x251_io_method {
+	IO_NONE,
+	IO_READ,
+	IO_MMAP,
+};
+
+enum et61x251_stream_state {
+	STREAM_OFF,
+	STREAM_INTERRUPT,
+	STREAM_ON,
+};
+
+struct et61x251_sysfs_attr {
+	u8 reg, i2c_reg;
+};
+
+struct et61x251_module_param {
+	u8 force_munmap;
+};
+
+static DECLARE_MUTEX(et61x251_sysfs_lock);
+static DECLARE_RWSEM(et61x251_disconnect);
+
+struct et61x251_device {
+	struct video_device* v4ldev;
+
+	struct et61x251_sensor* sensor;
+
+	struct usb_device* usbdev;
+	struct urb* urb[ET61X251_URBS];
+	void* transfer_buffer[ET61X251_URBS];
+	u8* control_buffer;
+
+	struct et61x251_frame_t *frame_current, frame[ET61X251_MAX_FRAMES];
+	struct list_head inqueue, outqueue;
+	u32 frame_count, nbuffers, nreadbuffers;
+
+	enum et61x251_io_method io;
+	enum et61x251_stream_state stream;
+
+	struct v4l2_jpegcompression compression;
+
+	struct et61x251_sysfs_attr sysfs;
+	struct et61x251_module_param module_param;
+
+	enum et61x251_dev_state state;
+	u8 users;
+
+	struct semaphore dev_sem, fileop_sem;
+	spinlock_t queue_lock;
+	wait_queue_head_t open, wait_frame, wait_stream;
+};
+
+/*****************************************************************************/
+
+void
+et61x251_attach_sensor(struct et61x251_device* cam,
+                       struct et61x251_sensor* sensor)
+{
+	cam->sensor = sensor;
+	cam->sensor->usbdev = cam->usbdev;
+}
+
+/*****************************************************************************/
+
+#undef DBG
+#undef KDBG
+#ifdef ET61X251_DEBUG
+#	define DBG(level, fmt, args...)                                       \
+do {                                                                          \
+	if (debug >= (level)) {                                               \
+		if ((level) == 1)                                             \
+			dev_err(&cam->usbdev->dev, fmt "\n", ## args);        \
+		else if ((level) == 2)                                        \
+			dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
+		else if ((level) >= 3)                                        \
+			dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",      \
+			         __FUNCTION__, __LINE__ , ## args);           \
+	}                                                                     \
+} while (0)
+#	define KDBG(level, fmt, args...)                                      \
+do {                                                                          \
+	if (debug >= (level)) {                                               \
+		if ((level) == 1 || (level) == 2)                             \
+			pr_info("et61x251: " fmt "\n", ## args);              \
+		else if ((level) == 3)                                        \
+			pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \
+			         __LINE__ , ## args);                         \
+	}                                                                     \
+} while (0)
+#	define V4LDBG(level, name, cmd)                                       \
+do {                                                                          \
+	if (debug >= (level))                                                 \
+		v4l_print_ioctl(name, cmd);                                   \
+} while (0)
+#else
+#	define DBG(level, fmt, args...) do {;} while(0)
+#	define KDBG(level, fmt, args...) do {;} while(0)
+#	define V4LDBG(level, name, cmd) do {;} while(0)
+#endif
+
+#undef PDBG
+#define PDBG(fmt, args...)                                                    \
+dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
+
+#undef PDBGG
+#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+
+#endif /* _ET61X251_H_ */
diff --git a/drivers/usb/media/et61x251_core.c b/drivers/usb/media/et61x251_core.c
new file mode 100644
index 0000000..2c0171a
--- /dev/null
+++ b/drivers/usb/media/et61x251_core.c
@@ -0,0 +1,2605 @@
+/***************************************************************************
+ * V4L2 driver for ET61X[12]51 PC Camera Controllers                       *
+ *                                                                         *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/stddef.h>
+#include <linux/compiler.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/stat.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/page-flags.h>
+#include <linux/byteorder/generic.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+
+#include "et61x251.h"
+
+/*****************************************************************************/
+
+#define ET61X251_MODULE_NAME    "V4L2 driver for ET61X[12]51 "                \
+                                "PC Camera Controllers"
+#define ET61X251_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
+#define ET61X251_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
+#define ET61X251_MODULE_LICENSE "GPL"
+#define ET61X251_MODULE_VERSION "1:1.01"
+#define ET61X251_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 1)
+
+/*****************************************************************************/
+
+MODULE_DEVICE_TABLE(usb, et61x251_id_table);
+
+MODULE_AUTHOR(ET61X251_MODULE_AUTHOR " " ET61X251_AUTHOR_EMAIL);
+MODULE_DESCRIPTION(ET61X251_MODULE_NAME);
+MODULE_VERSION(ET61X251_MODULE_VERSION);
+MODULE_LICENSE(ET61X251_MODULE_LICENSE);
+
+static short video_nr[] = {[0 ... ET61X251_MAX_DEVICES-1] = -1};
+module_param_array(video_nr, short, NULL, 0444);
+MODULE_PARM_DESC(video_nr,
+                 "\n<-1|n[,...]> Specify V4L2 minor mode number."
+                 "\n -1 = use next available (default)"
+                 "\n  n = use minor number n (integer >= 0)"
+                 "\nYou can specify up to "
+                 __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way."
+                 "\nFor example:"
+                 "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
+                 "\nthe second registered camera and use auto for the first"
+                 "\none and for every other camera."
+                 "\n");
+
+static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] =
+                               ET61X251_FORCE_MUNMAP};
+module_param_array(force_munmap, bool, NULL, 0444);
+MODULE_PARM_DESC(force_munmap,
+                 "\n<0|1[,...]> Force the application to unmap previously"
+                 "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
+                 "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
+                 "\nthis feature. This parameter is specific for each"
+                 "\ndetected camera."
+                 "\n 0 = do not force memory unmapping"
+                 "\n 1 = force memory unmapping (save memory)"
+                 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+                 "\n");
+
+#ifdef ET61X251_DEBUG
+static unsigned short debug = ET61X251_DEBUG_LEVEL;
+module_param(debug, ushort, 0644);
+MODULE_PARM_DESC(debug,
+                 "\n<n> Debugging information level, from 0 to 3:"
+                 "\n0 = none (use carefully)"
+                 "\n1 = critical errors"
+                 "\n2 = significant informations"
+                 "\n3 = more verbose messages"
+                 "\nLevel 3 is useful for testing only, when only "
+                 "one device is used."
+                 "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"."
+                 "\n");
+#endif
+
+/*****************************************************************************/
+
+static u32
+et61x251_request_buffers(struct et61x251_device* cam, u32 count,
+                         enum et61x251_io_method io)
+{
+	struct v4l2_pix_format* p = &(cam->sensor->pix_format);
+	struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
+	const size_t imagesize = cam->module_param.force_munmap ||
+	                         io == IO_READ ?
+	                         (p->width * p->height * p->priv) / 8 :
+	                         (r->width * r->height * p->priv) / 8;
+	void* buff = NULL;
+	u32 i;
+
+	if (count > ET61X251_MAX_FRAMES)
+		count = ET61X251_MAX_FRAMES;
+
+	cam->nbuffers = count;
+	while (cam->nbuffers > 0) {
+		if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+			break;
+		cam->nbuffers--;
+	}
+
+	for (i = 0; i < cam->nbuffers; i++) {
+		cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
+		cam->frame[i].buf.index = i;
+		cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
+		cam->frame[i].buf.length = imagesize;
+		cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		cam->frame[i].buf.sequence = 0;
+		cam->frame[i].buf.field = V4L2_FIELD_NONE;
+		cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
+		cam->frame[i].buf.flags = 0;
+	}
+
+	return cam->nbuffers;
+}
+
+
+static void et61x251_release_buffers(struct et61x251_device* cam)
+{
+	if (cam->nbuffers) {
+		vfree(cam->frame[0].bufmem);
+		cam->nbuffers = 0;
+	}
+	cam->frame_current = NULL;
+}
+
+
+static void et61x251_empty_framequeues(struct et61x251_device* cam)
+{
+	u32 i;
+
+	INIT_LIST_HEAD(&cam->inqueue);
+	INIT_LIST_HEAD(&cam->outqueue);
+
+	for (i = 0; i < ET61X251_MAX_FRAMES; i++) {
+		cam->frame[i].state = F_UNUSED;
+		cam->frame[i].buf.bytesused = 0;
+	}
+}
+
+
+static void et61x251_requeue_outqueue(struct et61x251_device* cam)
+{
+	struct et61x251_frame_t *i;
+
+	list_for_each_entry(i, &cam->outqueue, frame) {
+		i->state = F_QUEUED;
+		list_add(&i->frame, &cam->inqueue);
+	}
+
+	INIT_LIST_HEAD(&cam->outqueue);
+}
+
+
+static void et61x251_queue_unusedframes(struct et61x251_device* cam)
+{
+	unsigned long lock_flags;
+	u32 i;
+
+	for (i = 0; i < cam->nbuffers; i++)
+		if (cam->frame[i].state == F_UNUSED) {
+			cam->frame[i].state = F_QUEUED;
+			spin_lock_irqsave(&cam->queue_lock, lock_flags);
+			list_add_tail(&cam->frame[i].frame, &cam->inqueue);
+			spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+		}
+}
+
+/*****************************************************************************/
+
+int et61x251_write_reg(struct et61x251_device* cam, u8 value, u16 index)
+{
+	struct usb_device* udev = cam->usbdev;
+	u8* buff = cam->control_buffer;
+	int res;
+
+	*buff = value;
+
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+	                      0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
+	if (res < 0) {
+		DBG(3, "Failed to write a register (value 0x%02X, index "
+		       "0x%02X, error %d)", value, index, res);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int et61x251_read_reg(struct et61x251_device* cam, u16 index)
+{
+	struct usb_device* udev = cam->usbdev;
+	u8* buff = cam->control_buffer;
+	int res;
+
+	res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
+	                      0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
+	if (res < 0)
+		DBG(3, "Failed to read a register (index 0x%02X, error %d)",
+		    index, res);
+
+	return (res >= 0) ? (int)(*buff) : -1;
+}
+
+
+static int
+et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor)
+{
+	int i, r;
+
+	for (i = 1; i <= 8; i++) {
+		if (sensor->interface == ET61X251_I2C_3WIRES) {
+			r = et61x251_read_reg(cam, 0x8e);
+			if (!(r & 0x02) && (r >= 0))
+				return 0;
+		} else {
+			r = et61x251_read_reg(cam, 0x8b);
+			if (!(r & 0x01) && (r >= 0))
+				return 0;
+		}
+		if (r < 0)
+			return -EIO;
+		udelay(8*8); /* minimum for sensors at 400kHz */
+	}
+
+	return -EBUSY;
+}
+
+
+int
+et61x251_i2c_try_read(struct et61x251_device* cam,
+                      struct et61x251_sensor* sensor, u8 address)
+{
+	struct usb_device* udev = cam->usbdev;
+	u8* data = cam->control_buffer;
+	int err = 0, res;
+
+	data[0] = address;
+	data[1] = cam->sensor->i2c_slave_id;
+	data[2] = cam->sensor->rsta | 0x10;
+	data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02);
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+	                      0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT);
+	if (res < 0)
+		err += res;
+
+	err += et61x251_i2c_wait(cam, sensor);
+
+	res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
+	                      0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT);
+	if (res < 0)
+		err += res;
+
+	if (err)
+		DBG(3, "I2C read failed for %s image sensor", sensor->name);
+
+	PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[0]);
+
+	return err ? -1 : (int)data[0];
+}
+
+
+int
+et61x251_i2c_try_write(struct et61x251_device* cam,
+                       struct et61x251_sensor* sensor, u8 address, u8 value)
+{
+	struct usb_device* udev = cam->usbdev;
+	u8* data = cam->control_buffer;
+	int err = 0, res;
+
+	data[0] = address;
+	data[1] = cam->sensor->i2c_slave_id;
+	data[2] = cam->sensor->rsta | 0x12;
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+	                      0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
+	if (res < 0)
+		err += res;
+
+	data[0] = value;
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+	                      0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
+	if (res < 0)
+		err += res;
+
+	err += et61x251_i2c_wait(cam, sensor);
+
+	if (err)
+		DBG(3, "I2C write failed for %s image sensor", sensor->name);
+
+	PDBGG("I2C write: address 0x%02X, value: 0x%02X", address, value);
+
+	return err ? -1 : 0;
+}
+
+
+int
+et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2,
+                       u8 data3, u8 data4, u8 data5, u8 data6, u8 data7,
+                       u8 data8, u8 address)
+{
+	struct usb_device* udev = cam->usbdev;
+	u8* data = cam->control_buffer;
+	int err = 0, res;
+
+	if (!cam->sensor)
+		return -1;
+
+	data[0] = data2;
+	data[1] = data3;
+	data[2] = data4;
+	data[3] = data5;
+	data[4] = data6;
+	data[5] = data7;
+	data[6] = data8;
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+	                      0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT);
+	if (res < 0)
+		err += res;
+
+	data[0] = address;
+	data[1] = cam->sensor->i2c_slave_id;
+	data[2] = cam->sensor->rsta | 0x02 | (n << 4);
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+	                      0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
+	if (res < 0)
+		err += res;
+
+	/* Start writing through the serial interface */
+	data[0] = data1;
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+	                      0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
+	if (res < 0)
+		err += res;
+
+	err += et61x251_i2c_wait(cam, cam->sensor);
+
+	if (err)
+		DBG(3, "I2C raw write failed for %s image sensor",
+		    cam->sensor->name);
+
+	PDBGG("I2C raw write: %u bytes, address = 0x%02X, data1 = 0x%02X, "
+	      "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X,"
+	      " data6 = 0x%02X, data7 = 0x%02X, data8 = 0x%02X", n, address,
+	      data1, data2, data3, data4, data5, data6, data7, data8);
+
+	return err ? -1 : 0;
+
+}
+
+
+int et61x251_i2c_read(struct et61x251_device* cam, u8 address)
+{
+	if (!cam->sensor)
+		return -1;
+
+	return et61x251_i2c_try_read(cam, cam->sensor, address);
+}
+
+
+int et61x251_i2c_write(struct et61x251_device* cam, u8 address, u8 value)
+{
+	if (!cam->sensor)
+		return -1;
+
+	return et61x251_i2c_try_write(cam, cam->sensor, address, value);
+}
+
+/*****************************************************************************/
+
+static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs)
+{
+	struct et61x251_device* cam = urb->context;
+	struct et61x251_frame_t** f;
+	size_t imagesize;
+	u8 i;
+	int err = 0;
+
+	if (urb->status == -ENOENT)
+		return;
+
+	f = &cam->frame_current;
+
+	if (cam->stream == STREAM_INTERRUPT) {
+		cam->stream = STREAM_OFF;
+		if ((*f))
+			(*f)->state = F_QUEUED;
+		DBG(3, "Stream interrupted");
+		wake_up_interruptible(&cam->wait_stream);
+	}
+
+	if (cam->state & DEV_DISCONNECTED)
+		return;
+
+	if (cam->state & DEV_MISCONFIGURED) {
+		wake_up_interruptible(&cam->wait_frame);
+		return;
+	}
+
+	if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
+		goto resubmit_urb;
+
+	if (!(*f))
+		(*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t,
+		                  frame);
+
+	imagesize = (cam->sensor->pix_format.width *
+	             cam->sensor->pix_format.height *
+	             cam->sensor->pix_format.priv) / 8;
+
+	for (i = 0; i < urb->number_of_packets; i++) {
+		unsigned int len, status;
+		void *pos;
+		u8* b1, * b2, sof;
+		const u8 VOID_BYTES = 6;
+		size_t imglen;
+
+		len = urb->iso_frame_desc[i].actual_length;
+		status = urb->iso_frame_desc[i].status;
+		pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
+
+		if (status) {
+			DBG(3, "Error in isochronous frame");
+			(*f)->state = F_ERROR;
+			continue;
+		}
+
+		b1 = pos++;
+		b2 = pos++;
+		sof = ((*b1 & 0x3f) == 63);
+		imglen = ((*b1 & 0xc0) << 2) | *b2;
+
+		PDBGG("Isochrnous frame: length %u, #%u i, image length %zu",
+		      len, i, imglen);
+
+		if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR)
+start_of_frame:
+			if (sof) {
+				(*f)->state = F_GRABBING;
+				(*f)->buf.bytesused = 0;
+				do_gettimeofday(&(*f)->buf.timestamp);
+				pos += 22;
+				DBG(3, "SOF detected: new video frame");
+			}
+
+		if ((*f)->state == F_GRABBING) {
+			if (sof && (*f)->buf.bytesused) {
+				if (cam->sensor->pix_format.pixelformat ==
+				                         V4L2_PIX_FMT_ET61X251)
+					goto end_of_frame;
+				else {
+					DBG(3, "Not expected SOF detected "
+					       "after %lu bytes",
+					   (unsigned long)(*f)->buf.bytesused);
+					(*f)->state = F_ERROR;
+					continue;
+				}
+			}
+
+			if ((*f)->buf.bytesused + imglen > imagesize) {
+				DBG(3, "Video frame size exceeded");
+				(*f)->state = F_ERROR;
+				continue;
+			}
+
+			pos += VOID_BYTES;
+
+			memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, imglen);
+			(*f)->buf.bytesused += imglen;
+
+			if ((*f)->buf.bytesused == imagesize) {
+				u32 b;
+end_of_frame:
+				b = (*f)->buf.bytesused;
+				(*f)->state = F_DONE;
+				(*f)->buf.sequence= ++cam->frame_count;
+				spin_lock(&cam->queue_lock);
+				list_move_tail(&(*f)->frame, &cam->outqueue);
+				if (!list_empty(&cam->inqueue))
+					(*f) = list_entry(cam->inqueue.next,
+					               struct et61x251_frame_t,
+					                  frame);
+				else
+					(*f) = NULL;
+				spin_unlock(&cam->queue_lock);
+				DBG(3, "Video frame captured: : %lu bytes",
+				       (unsigned long)(b));
+
+				if (!(*f))
+					goto resubmit_urb;
+
+				if (sof &&
+				    cam->sensor->pix_format.pixelformat ==
+				                         V4L2_PIX_FMT_ET61X251)
+					goto start_of_frame;
+			}
+		}
+	}
+
+resubmit_urb:
+	urb->dev = cam->usbdev;
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err < 0 && err != -EPERM) {
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "usb_submit_urb() failed");
+	}
+
+	wake_up_interruptible(&cam->wait_frame);
+}
+
+
+static int et61x251_start_transfer(struct et61x251_device* cam)
+{
+	struct usb_device *udev = cam->usbdev;
+	struct urb* urb;
+	const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832,
+	                                       864, 896, 920, 956, 980, 1000,
+	                                       1022};
+	const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING];
+	s8 i, j;
+	int err = 0;
+
+	for (i = 0; i < ET61X251_URBS; i++) {
+		cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz,
+		                                  GFP_KERNEL);
+		if (!cam->transfer_buffer[i]) {
+			err = -ENOMEM;
+			DBG(1, "Not enough memory");
+			goto free_buffers;
+		}
+	}
+
+	for (i = 0; i < ET61X251_URBS; i++) {
+		urb = usb_alloc_urb(ET61X251_ISO_PACKETS, GFP_KERNEL);
+		cam->urb[i] = urb;
+		if (!urb) {
+			err = -ENOMEM;
+			DBG(1, "usb_alloc_urb() failed");
+			goto free_urbs;
+		}
+		urb->dev = udev;
+		urb->context = cam;
+		urb->pipe = usb_rcvisocpipe(udev, 1);
+		urb->transfer_flags = URB_ISO_ASAP;
+		urb->number_of_packets = ET61X251_ISO_PACKETS;
+		urb->complete = et61x251_urb_complete;
+		urb->transfer_buffer = cam->transfer_buffer[i];
+		urb->transfer_buffer_length = psz * ET61X251_ISO_PACKETS;
+		urb->interval = 1;
+		for (j = 0; j < ET61X251_ISO_PACKETS; j++) {
+			urb->iso_frame_desc[j].offset = psz * j;
+			urb->iso_frame_desc[j].length = psz;
+		}
+	}
+
+	err = et61x251_write_reg(cam, 0x01, 0x03);
+	err = et61x251_write_reg(cam, 0x00, 0x03);
+	err = et61x251_write_reg(cam, 0x08, 0x03);
+	if (err) {
+		err = -EIO;
+		DBG(1, "I/O hardware error");
+		goto free_urbs;
+	}
+
+	err = usb_set_interface(udev, 0, ET61X251_ALTERNATE_SETTING);
+	if (err) {
+		DBG(1, "usb_set_interface() failed");
+		goto free_urbs;
+	}
+
+	cam->frame_current = NULL;
+
+	for (i = 0; i < ET61X251_URBS; i++) {
+		err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
+		if (err) {
+			for (j = i-1; j >= 0; j--)
+				usb_kill_urb(cam->urb[j]);
+			DBG(1, "usb_submit_urb() failed, error %d", err);
+			goto free_urbs;
+		}
+	}
+
+	return 0;
+
+free_urbs:
+	for (i = 0; (i < ET61X251_URBS) &&  cam->urb[i]; i++)
+		usb_free_urb(cam->urb[i]);
+
+free_buffers:
+	for (i = 0; (i < ET61X251_URBS) && cam->transfer_buffer[i]; i++)
+		kfree(cam->transfer_buffer[i]);
+
+	return err;
+}
+
+
+static int et61x251_stop_transfer(struct et61x251_device* cam)
+{
+	struct usb_device *udev = cam->usbdev;
+	s8 i;
+	int err = 0;
+
+	if (cam->state & DEV_DISCONNECTED)
+		return 0;
+
+	for (i = ET61X251_URBS-1; i >= 0; i--) {
+		usb_kill_urb(cam->urb[i]);
+		usb_free_urb(cam->urb[i]);
+		kfree(cam->transfer_buffer[i]);
+	}
+
+	err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
+	if (err)
+		DBG(3, "usb_set_interface() failed");
+
+	return err;
+}
+
+
+static int et61x251_stream_interrupt(struct et61x251_device* cam)
+{
+	int err = 0;
+
+	cam->stream = STREAM_INTERRUPT;
+	err = wait_event_timeout(cam->wait_stream,
+	                         (cam->stream == STREAM_OFF) ||
+	                         (cam->state & DEV_DISCONNECTED),
+	                         ET61X251_URB_TIMEOUT);
+	if (cam->state & DEV_DISCONNECTED)
+		return -ENODEV;
+	else if (err) {
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "URB timeout reached. The camera is misconfigured. To "
+		       "use it, close and open /dev/video%d again.",
+		    cam->v4ldev->minor);
+		return err;
+	}
+
+	return 0;
+}
+
+/*****************************************************************************/
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count)
+{
+	char str[5];
+	char* endp;
+	unsigned long val;
+
+	if (len < 4) {
+		strncpy(str, buff, len);
+		str[len+1] = '\0';
+	} else {
+		strncpy(str, buff, 4);
+		str[4] = '\0';
+	}
+
+	val = simple_strtoul(str, &endp, 0);
+
+	*count = 0;
+	if (val <= 0xff)
+		*count = (ssize_t)(endp - str);
+	if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
+		*count += 1;
+
+	return (u8)val;
+}
+
+/*
+   NOTE 1: being inside one of the following methods implies that the v4l
+           device exists for sure (see kobjects and reference counters)
+   NOTE 2: buffers are PAGE_SIZE long
+*/
+
+static ssize_t et61x251_show_reg(struct class_device* cd, char* buf)
+{
+	struct et61x251_device* cam;
+	ssize_t count;
+
+	if (down_interruptible(&et61x251_sysfs_lock))
+		return -ERESTARTSYS;
+
+	cam = video_get_drvdata(to_video_device(cd));
+	if (!cam) {
+		up(&et61x251_sysfs_lock);
+		return -ENODEV;
+	}
+
+	count = sprintf(buf, "%u\n", cam->sysfs.reg);
+
+	up(&et61x251_sysfs_lock);
+
+	return count;
+}
+
+
+static ssize_t
+et61x251_store_reg(struct class_device* cd, const char* buf, size_t len)
+{
+	struct et61x251_device* cam;
+	u8 index;
+	ssize_t count;
+
+	if (down_interruptible(&et61x251_sysfs_lock))
+		return -ERESTARTSYS;
+
+	cam = video_get_drvdata(to_video_device(cd));
+	if (!cam) {
+		up(&et61x251_sysfs_lock);
+		return -ENODEV;
+	}
+
+	index = et61x251_strtou8(buf, len, &count);
+	if (index > 0x8e || !count) {
+		up(&et61x251_sysfs_lock);
+		return -EINVAL;
+	}
+
+	cam->sysfs.reg = index;
+
+	DBG(2, "Moved ET61X[12]51 register index to 0x%02X", cam->sysfs.reg);
+	DBG(3, "Written bytes: %zd", count);
+
+	up(&et61x251_sysfs_lock);
+
+	return count;
+}
+
+
+static ssize_t et61x251_show_val(struct class_device* cd, char* buf)
+{
+	struct et61x251_device* cam;
+	ssize_t count;
+	int val;
+
+	if (down_interruptible(&et61x251_sysfs_lock))
+		return -ERESTARTSYS;
+
+	cam = video_get_drvdata(to_video_device(cd));
+	if (!cam) {
+		up(&et61x251_sysfs_lock);
+		return -ENODEV;
+	}
+
+	if ((val = et61x251_read_reg(cam, cam->sysfs.reg)) < 0) {
+		up(&et61x251_sysfs_lock);
+		return -EIO;
+	}
+
+	count = sprintf(buf, "%d\n", val);
+
+	DBG(3, "Read bytes: %zd", count);
+
+	up(&et61x251_sysfs_lock);
+
+	return count;
+}
+
+
+static ssize_t
+et61x251_store_val(struct class_device* cd, const char* buf, size_t len)
+{
+	struct et61x251_device* cam;
+	u8 value;
+	ssize_t count;
+	int err;
+
+	if (down_interruptible(&et61x251_sysfs_lock))
+		return -ERESTARTSYS;
+
+	cam = video_get_drvdata(to_video_device(cd));
+	if (!cam) {
+		up(&et61x251_sysfs_lock);
+		return -ENODEV;
+	}
+
+	value = et61x251_strtou8(buf, len, &count);
+	if (!count) {
+		up(&et61x251_sysfs_lock);
+		return -EINVAL;
+	}
+
+	err = et61x251_write_reg(cam, value, cam->sysfs.reg);
+	if (err) {
+		up(&et61x251_sysfs_lock);
+		return -EIO;
+	}
+
+	DBG(2, "Written ET61X[12]51 reg. 0x%02X, val. 0x%02X",
+	    cam->sysfs.reg, value);
+	DBG(3, "Written bytes: %zd", count);
+
+	up(&et61x251_sysfs_lock);
+
+	return count;
+}
+
+
+static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf)
+{
+	struct et61x251_device* cam;
+	ssize_t count;
+
+	if (down_interruptible(&et61x251_sysfs_lock))
+		return -ERESTARTSYS;
+
+	cam = video_get_drvdata(to_video_device(cd));
+	if (!cam) {
+		up(&et61x251_sysfs_lock);
+		return -ENODEV;
+	}
+
+	count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
+
+	DBG(3, "Read bytes: %zd", count);
+
+	up(&et61x251_sysfs_lock);
+
+	return count;
+}
+
+
+static ssize_t
+et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
+{
+	struct et61x251_device* cam;
+	u8 index;
+	ssize_t count;
+
+	if (down_interruptible(&et61x251_sysfs_lock))
+		return -ERESTARTSYS;
+
+	cam = video_get_drvdata(to_video_device(cd));
+	if (!cam) {
+		up(&et61x251_sysfs_lock);
+		return -ENODEV;
+	}
+
+	index = et61x251_strtou8(buf, len, &count);
+	if (!count) {
+		up(&et61x251_sysfs_lock);
+		return -EINVAL;
+	}
+
+	cam->sysfs.i2c_reg = index;
+
+	DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
+	DBG(3, "Written bytes: %zd", count);
+
+	up(&et61x251_sysfs_lock);
+
+	return count;
+}
+
+
+static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf)
+{
+	struct et61x251_device* cam;
+	ssize_t count;
+	int val;
+
+	if (down_interruptible(&et61x251_sysfs_lock))
+		return -ERESTARTSYS;
+
+	cam = video_get_drvdata(to_video_device(cd));
+	if (!cam) {
+		up(&et61x251_sysfs_lock);
+		return -ENODEV;
+	}
+
+	if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) {
+		up(&et61x251_sysfs_lock);
+		return -ENOSYS;
+	}
+
+	if ((val = et61x251_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) {
+		up(&et61x251_sysfs_lock);
+		return -EIO;
+	}
+
+	count = sprintf(buf, "%d\n", val);
+
+	DBG(3, "Read bytes: %zd", count);
+
+	up(&et61x251_sysfs_lock);
+
+	return count;
+}
+
+
+static ssize_t
+et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
+{
+	struct et61x251_device* cam;
+	u8 value;
+	ssize_t count;
+	int err;
+
+	if (down_interruptible(&et61x251_sysfs_lock))
+		return -ERESTARTSYS;
+
+	cam = video_get_drvdata(to_video_device(cd));
+	if (!cam) {
+		up(&et61x251_sysfs_lock);
+		return -ENODEV;
+	}
+
+	if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) {
+		up(&et61x251_sysfs_lock);
+		return -ENOSYS;
+	}
+
+	value = et61x251_strtou8(buf, len, &count);
+	if (!count) {
+		up(&et61x251_sysfs_lock);
+		return -EINVAL;
+	}
+
+	err = et61x251_i2c_write(cam, cam->sysfs.i2c_reg, value);
+	if (err) {
+		up(&et61x251_sysfs_lock);
+		return -EIO;
+	}
+
+	DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
+	    cam->sysfs.i2c_reg, value);
+	DBG(3, "Written bytes: %zd", count);
+
+	up(&et61x251_sysfs_lock);
+
+	return count;
+}
+
+
+static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
+                         et61x251_show_reg, et61x251_store_reg);
+static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
+                         et61x251_show_val, et61x251_store_val);
+static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
+                         et61x251_show_i2c_reg, et61x251_store_i2c_reg);
+static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
+                         et61x251_show_i2c_val, et61x251_store_i2c_val);
+
+
+static void et61x251_create_sysfs(struct et61x251_device* cam)
+{
+	struct video_device *v4ldev = cam->v4ldev;
+
+	video_device_create_file(v4ldev, &class_device_attr_reg);
+	video_device_create_file(v4ldev, &class_device_attr_val);
+	if (cam->sensor && cam->sensor->sysfs_ops) {
+		video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
+		video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+	}
+}
+#endif /* CONFIG_VIDEO_ADV_DEBUG */
+
+/*****************************************************************************/
+
+static int
+et61x251_set_pix_format(struct et61x251_device* cam,
+                        struct v4l2_pix_format* pix)
+{
+	int r, err = 0;
+
+	if ((r = et61x251_read_reg(cam, 0x12)) < 0)
+		err += r;
+	if (pix->pixelformat == V4L2_PIX_FMT_ET61X251)
+		err += et61x251_write_reg(cam, r & 0xfd, 0x12);
+	else
+		err += et61x251_write_reg(cam, r | 0x02, 0x12);
+
+	return err ? -EIO : 0;
+}
+
+
+static int
+et61x251_set_compression(struct et61x251_device* cam,
+                         struct v4l2_jpegcompression* compression)
+{
+	int r, err = 0;
+
+	if ((r = et61x251_read_reg(cam, 0x12)) < 0)
+		err += r;
+	if (compression->quality == 0)
+		err += et61x251_write_reg(cam, r & 0xfb, 0x12);
+	else
+		err += et61x251_write_reg(cam, r | 0x04, 0x12);
+
+	return err ? -EIO : 0;
+}
+
+
+static int et61x251_set_scale(struct et61x251_device* cam, u8 scale)
+{
+	int r = 0, err = 0;
+
+	r = et61x251_read_reg(cam, 0x12);
+	if (r < 0)
+		err += r;
+
+	if (scale == 1)
+		err += et61x251_write_reg(cam, r & ~0x01, 0x12);
+	else if (scale == 2)
+		err += et61x251_write_reg(cam, r | 0x01, 0x12);
+
+	if (err)
+		return -EIO;
+
+	PDBGG("Scaling factor: %u", scale);
+
+	return 0;
+}
+
+
+static int
+et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect)
+{
+	struct et61x251_sensor* s = cam->sensor;
+	u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left +
+	                   s->active_pixel.left),
+	    fmw_sy = (u16)(rect->top - s->cropcap.bounds.top +
+	                   s->active_pixel.top),
+	    fmw_length = (u16)(rect->width),
+	    fmw_height = (u16)(rect->height);
+	int err = 0;
+
+	err += et61x251_write_reg(cam, fmw_sx & 0xff, 0x69);
+	err += et61x251_write_reg(cam, fmw_sy & 0xff, 0x6a);
+	err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b);
+	err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c);
+	err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6)
+	                               | ((fmw_length & 0x300) >> 4)
+	                               | ((fmw_height & 0x300) >> 2), 0x6d);
+	if (err)
+		return -EIO;
+
+	PDBGG("fmw_sx, fmw_sy, fmw_length, fmw_height: %u %u %u %u",
+	      fmw_sx, fmw_sy, fmw_length, fmw_height);
+
+	return 0;
+}
+
+
+static int et61x251_init(struct et61x251_device* cam)
+{
+	struct et61x251_sensor* s = cam->sensor;
+	struct v4l2_control ctrl;
+	struct v4l2_queryctrl *qctrl;
+	struct v4l2_rect* rect;
+	u8 i = 0;
+	int err = 0;
+
+	if (!(cam->state & DEV_INITIALIZED)) {
+		init_waitqueue_head(&cam->open);
+		qctrl = s->qctrl;
+		rect = &(s->cropcap.defrect);
+		cam->compression.quality = ET61X251_COMPRESSION_QUALITY;
+	} else { /* use current values */
+		qctrl = s->_qctrl;
+		rect = &(s->_rect);
+	}
+
+	err += et61x251_set_scale(cam, rect->width / s->pix_format.width);
+	err += et61x251_set_crop(cam, rect);
+	if (err)
+		return err;
+
+	if (s->init) {
+		err = s->init(cam);
+		if (err) {
+			DBG(3, "Sensor initialization failed");
+			return err;
+		}
+	}
+
+	err += et61x251_set_compression(cam, &cam->compression);
+	err += et61x251_set_pix_format(cam, &s->pix_format);
+	if (s->set_pix_format)
+		err += s->set_pix_format(cam, &s->pix_format);
+	if (err)
+		return err;
+
+	if (s->pix_format.pixelformat == V4L2_PIX_FMT_ET61X251)
+		DBG(3, "Compressed video format is active, quality %d",
+		    cam->compression.quality);
+	else
+		DBG(3, "Uncompressed video format is active");
+
+	if (s->set_crop)
+		if ((err = s->set_crop(cam, rect))) {
+			DBG(3, "set_crop() failed");
+			return err;
+		}
+
+	if (s->set_ctrl) {
+		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+			if (s->qctrl[i].id != 0 &&
+			    !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
+				ctrl.id = s->qctrl[i].id;
+				ctrl.value = qctrl[i].default_value;
+				err = s->set_ctrl(cam, &ctrl);
+				if (err) {
+					DBG(3, "Set %s control failed",
+					    s->qctrl[i].name);
+					return err;
+				}
+				DBG(3, "Image sensor supports '%s' control",
+				    s->qctrl[i].name);
+			}
+	}
+
+	if (!(cam->state & DEV_INITIALIZED)) {
+		init_MUTEX(&cam->fileop_sem);
+		spin_lock_init(&cam->queue_lock);
+		init_waitqueue_head(&cam->wait_frame);
+		init_waitqueue_head(&cam->wait_stream);
+		cam->nreadbuffers = 2;
+		memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
+		memcpy(&(s->_rect), &(s->cropcap.defrect),
+		       sizeof(struct v4l2_rect));
+		cam->state |= DEV_INITIALIZED;
+	}
+
+	DBG(2, "Initialization succeeded");
+	return 0;
+}
+
+
+static void et61x251_release_resources(struct et61x251_device* cam)
+{
+	down(&et61x251_sysfs_lock);
+
+	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+	video_set_drvdata(cam->v4ldev, NULL);
+	video_unregister_device(cam->v4ldev);
+
+	up(&et61x251_sysfs_lock);
+
+	kfree(cam->control_buffer);
+}
+
+/*****************************************************************************/
+
+static int et61x251_open(struct inode* inode, struct file* filp)
+{
+	struct et61x251_device* cam;
+	int err = 0;
+
+	/*
+	   This is the only safe way to prevent race conditions with
+	   disconnect
+	*/
+	if (!down_read_trylock(&et61x251_disconnect))
+		return -ERESTARTSYS;
+
+	cam = video_get_drvdata(video_devdata(filp));
+
+	if (down_interruptible(&cam->dev_sem)) {
+		up_read(&et61x251_disconnect);
+		return -ERESTARTSYS;
+	}
+
+	if (cam->users) {
+		DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
+		if ((filp->f_flags & O_NONBLOCK) ||
+		    (filp->f_flags & O_NDELAY)) {
+			err = -EWOULDBLOCK;
+			goto out;
+		}
+		up(&cam->dev_sem);
+		err = wait_event_interruptible_exclusive(cam->open,
+		                                  cam->state & DEV_DISCONNECTED
+		                                         || !cam->users);
+		if (err) {
+			up_read(&et61x251_disconnect);
+			return err;
+		}
+		if (cam->state & DEV_DISCONNECTED) {
+			up_read(&et61x251_disconnect);
+			return -ENODEV;
+		}
+		down(&cam->dev_sem);
+	}
+
+
+	if (cam->state & DEV_MISCONFIGURED) {
+		err = et61x251_init(cam);
+		if (err) {
+			DBG(1, "Initialization failed again. "
+			       "I will retry on next open().");
+			goto out;
+		}
+		cam->state &= ~DEV_MISCONFIGURED;
+	}
+
+	if ((err = et61x251_start_transfer(cam)))
+		goto out;
+
+	filp->private_data = cam;
+	cam->users++;
+	cam->io = IO_NONE;
+	cam->stream = STREAM_OFF;
+	cam->nbuffers = 0;
+	cam->frame_count = 0;
+	et61x251_empty_framequeues(cam);
+
+	DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
+
+out:
+	up(&cam->dev_sem);
+	up_read(&et61x251_disconnect);
+	return err;
+}
+
+
+static int et61x251_release(struct inode* inode, struct file* filp)
+{
+	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+
+	down(&cam->dev_sem); /* prevent disconnect() to be called */
+
+	et61x251_stop_transfer(cam);
+
+	et61x251_release_buffers(cam);
+
+	if (cam->state & DEV_DISCONNECTED) {
+		et61x251_release_resources(cam);
+		up(&cam->dev_sem);
+		kfree(cam);
+		return 0;
+	}
+
+	cam->users--;
+	wake_up_interruptible_nr(&cam->open, 1);
+
+	DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
+
+	up(&cam->dev_sem);
+
+	return 0;
+}
+
+
+static ssize_t
+et61x251_read(struct file* filp, char __user * buf,
+              size_t count, loff_t* f_pos)
+{
+	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+	struct et61x251_frame_t* f, * i;
+	unsigned long lock_flags;
+	int err = 0;
+
+	if (down_interruptible(&cam->fileop_sem))
+		return -ERESTARTSYS;
+
+	if (cam->state & DEV_DISCONNECTED) {
+		DBG(1, "Device not present");
+		up(&cam->fileop_sem);
+		return -ENODEV;
+	}
+
+	if (cam->state & DEV_MISCONFIGURED) {
+		DBG(1, "The camera is misconfigured. Close and open it "
+		       "again.");
+		up(&cam->fileop_sem);
+		return -EIO;
+	}
+
+	if (cam->io == IO_MMAP) {
+		DBG(3, "Close and open the device again to choose the read "
+		       "method");
+		up(&cam->fileop_sem);
+		return -EINVAL;
+	}
+
+	if (cam->io == IO_NONE) {
+		if (!et61x251_request_buffers(cam, cam->nreadbuffers,
+		                              IO_READ)) {
+			DBG(1, "read() failed, not enough memory");
+			up(&cam->fileop_sem);
+			return -ENOMEM;
+		}
+		cam->io = IO_READ;
+		cam->stream = STREAM_ON;
+	}
+
+	if (list_empty(&cam->inqueue)) {
+		if (!list_empty(&cam->outqueue))
+			et61x251_empty_framequeues(cam);
+		et61x251_queue_unusedframes(cam);
+	}
+
+	if (!count) {
+		up(&cam->fileop_sem);
+		return 0;
+	}
+
+	if (list_empty(&cam->outqueue)) {
+		if (filp->f_flags & O_NONBLOCK) {
+			up(&cam->fileop_sem);
+			return -EAGAIN;
+		}
+		err = wait_event_interruptible
+		      ( cam->wait_frame,
+		        (!list_empty(&cam->outqueue)) ||
+		        (cam->state & DEV_DISCONNECTED) ||
+			(cam->state & DEV_MISCONFIGURED) );
+		if (err) {
+			up(&cam->fileop_sem);
+			return err;
+		}
+		if (cam->state & DEV_DISCONNECTED) {
+			up(&cam->fileop_sem);
+			return -ENODEV;
+		}
+		if (cam->state & DEV_MISCONFIGURED) {
+			up(&cam->fileop_sem);
+			return -EIO;
+		}
+	}
+
+	f = list_entry(cam->outqueue.prev, struct et61x251_frame_t, frame);
+
+	if (count > f->buf.bytesused)
+		count = f->buf.bytesused;
+
+	if (copy_to_user(buf, f->bufmem, count)) {
+		err = -EFAULT;
+		goto exit;
+	}
+	*f_pos += count;
+
+exit:
+	spin_lock_irqsave(&cam->queue_lock, lock_flags);
+	list_for_each_entry(i, &cam->outqueue, frame)
+		i->state = F_UNUSED;
+	INIT_LIST_HEAD(&cam->outqueue);
+	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+	et61x251_queue_unusedframes(cam);
+
+	PDBGG("Frame #%lu, bytes read: %zu",
+	      (unsigned long)f->buf.index, count);
+
+	up(&cam->fileop_sem);
+
+	return err ? err : count;
+}
+
+
+static unsigned int et61x251_poll(struct file *filp, poll_table *wait)
+{
+	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+	struct et61x251_frame_t* f;
+	unsigned long lock_flags;
+	unsigned int mask = 0;
+
+	if (down_interruptible(&cam->fileop_sem))
+		return POLLERR;
+
+	if (cam->state & DEV_DISCONNECTED) {
+		DBG(1, "Device not present");
+		goto error;
+	}
+
+	if (cam->state & DEV_MISCONFIGURED) {
+		DBG(1, "The camera is misconfigured. Close and open it "
+		       "again.");
+		goto error;
+	}
+
+	if (cam->io == IO_NONE) {
+		if (!et61x251_request_buffers(cam, cam->nreadbuffers,
+		                              IO_READ)) {
+			DBG(1, "poll() failed, not enough memory");
+			goto error;
+		}
+		cam->io = IO_READ;
+		cam->stream = STREAM_ON;
+	}
+
+	if (cam->io == IO_READ) {
+		spin_lock_irqsave(&cam->queue_lock, lock_flags);
+		list_for_each_entry(f, &cam->outqueue, frame)
+			f->state = F_UNUSED;
+		INIT_LIST_HEAD(&cam->outqueue);
+		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+		et61x251_queue_unusedframes(cam);
+	}
+
+	poll_wait(filp, &cam->wait_frame, wait);
+
+	if (!list_empty(&cam->outqueue))
+		mask |= POLLIN | POLLRDNORM;
+
+	up(&cam->fileop_sem);
+
+	return mask;
+
+error:
+	up(&cam->fileop_sem);
+	return POLLERR;
+}
+
+
+static void et61x251_vm_open(struct vm_area_struct* vma)
+{
+	struct et61x251_frame_t* f = vma->vm_private_data;
+	f->vma_use_count++;
+}
+
+
+static void et61x251_vm_close(struct vm_area_struct* vma)
+{
+	/* NOTE: buffers are not freed here */
+	struct et61x251_frame_t* f = vma->vm_private_data;
+	f->vma_use_count--;
+}
+
+
+static struct vm_operations_struct et61x251_vm_ops = {
+	.open = et61x251_vm_open,
+	.close = et61x251_vm_close,
+};
+
+
+static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma)
+{
+	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+	unsigned long size = vma->vm_end - vma->vm_start,
+	              start = vma->vm_start;
+	void *pos;
+	u32 i;
+
+	if (down_interruptible(&cam->fileop_sem))
+		return -ERESTARTSYS;
+
+	if (cam->state & DEV_DISCONNECTED) {
+		DBG(1, "Device not present");
+		up(&cam->fileop_sem);
+		return -ENODEV;
+	}
+
+	if (cam->state & DEV_MISCONFIGURED) {
+		DBG(1, "The camera is misconfigured. Close and open it "
+		       "again.");
+		up(&cam->fileop_sem);
+		return -EIO;
+	}
+
+	if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
+	    size != PAGE_ALIGN(cam->frame[0].buf.length)) {
+		up(&cam->fileop_sem);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < cam->nbuffers; i++) {
+		if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)
+			break;
+	}
+	if (i == cam->nbuffers) {
+		up(&cam->fileop_sem);
+		return -EINVAL;
+	}
+
+	vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_RESERVED;
+
+	pos = cam->frame[i].bufmem;
+	while (size > 0) { /* size is page-aligned */
+		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+			up(&cam->fileop_sem);
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	vma->vm_ops = &et61x251_vm_ops;
+	vma->vm_private_data = &cam->frame[i];
+
+	et61x251_vm_open(vma);
+
+	up(&cam->fileop_sem);
+
+	return 0;
+}
+
+/*****************************************************************************/
+
+static int
+et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_capability cap = {
+		.driver = "et61x251",
+		.version = ET61X251_MODULE_VERSION_CODE,
+		.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+		                V4L2_CAP_STREAMING,
+	};
+
+	strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
+	if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
+		strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
+		        sizeof(cap.bus_info));
+
+	if (copy_to_user(arg, &cap, sizeof(cap)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_input i;
+
+	if (copy_from_user(&i, arg, sizeof(i)))
+		return -EFAULT;
+
+	if (i.index)
+		return -EINVAL;
+
+	memset(&i, 0, sizeof(i));
+	strcpy(i.name, "Camera");
+
+	if (copy_to_user(arg, &i, sizeof(i)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_gs_input(struct et61x251_device* cam, void __user * arg)
+{
+	int index;
+
+	if (copy_from_user(&index, arg, sizeof(index)))
+		return -EFAULT;
+
+	if (index != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_query_ctrl(struct et61x251_device* cam, void __user * arg)
+{
+	struct et61x251_sensor* s = cam->sensor;
+	struct v4l2_queryctrl qc;
+	u8 i;
+
+	if (copy_from_user(&qc, arg, sizeof(qc)))
+		return -EFAULT;
+
+	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+		if (qc.id && qc.id == s->qctrl[i].id) {
+			memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
+			if (copy_to_user(arg, &qc, sizeof(qc)))
+				return -EFAULT;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+
+static int
+et61x251_vidioc_g_ctrl(struct et61x251_device* cam, void __user * arg)
+{
+	struct et61x251_sensor* s = cam->sensor;
+	struct v4l2_control ctrl;
+	int err = 0;
+	u8 i;
+
+	if (!s->get_ctrl && !s->set_ctrl)
+		return -EINVAL;
+
+	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+		return -EFAULT;
+
+	if (!s->get_ctrl) {
+		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+			if (ctrl.id == s->qctrl[i].id) {
+				ctrl.value = s->_qctrl[i].default_value;
+				goto exit;
+			}
+		return -EINVAL;
+	} else
+		err = s->get_ctrl(cam, &ctrl);
+
+exit:
+	if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
+		return -EFAULT;
+
+	return err;
+}
+
+
+static int
+et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg)
+{
+	struct et61x251_sensor* s = cam->sensor;
+	struct v4l2_control ctrl;
+	u8 i;
+	int err = 0;
+
+	if (!s->set_ctrl)
+		return -EINVAL;
+
+	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+		return -EFAULT;
+
+	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+		if (ctrl.id == s->qctrl[i].id) {
+			if (ctrl.value < s->qctrl[i].minimum ||
+			    ctrl.value > s->qctrl[i].maximum)
+				return -ERANGE;
+			ctrl.value -= ctrl.value % s->qctrl[i].step;
+			break;
+		}
+
+	if ((err = s->set_ctrl(cam, &ctrl)))
+		return err;
+
+	s->_qctrl[i].default_value = ctrl.value;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_cropcap(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
+
+	cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	cc->pixelaspect.numerator = 1;
+	cc->pixelaspect.denominator = 1;
+
+	if (copy_to_user(arg, cc, sizeof(*cc)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_g_crop(struct et61x251_device* cam, void __user * arg)
+{
+	struct et61x251_sensor* s = cam->sensor;
+	struct v4l2_crop crop = {
+		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+	};
+
+	memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
+
+	if (copy_to_user(arg, &crop, sizeof(crop)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
+{
+	struct et61x251_sensor* s = cam->sensor;
+	struct v4l2_crop crop;
+	struct v4l2_rect* rect;
+	struct v4l2_rect* bounds = &(s->cropcap.bounds);
+	struct v4l2_pix_format* pix_format = &(s->pix_format);
+	u8 scale;
+	const enum et61x251_stream_state stream = cam->stream;
+	const u32 nbuffers = cam->nbuffers;
+	u32 i;
+	int err = 0;
+
+	if (copy_from_user(&crop, arg, sizeof(crop)))
+		return -EFAULT;
+
+	rect = &(crop.c);
+
+	if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (cam->module_param.force_munmap)
+		for (i = 0; i < cam->nbuffers; i++)
+			if (cam->frame[i].vma_use_count) {
+				DBG(3, "VIDIOC_S_CROP failed. "
+				       "Unmap the buffers first.");
+				return -EINVAL;
+			}
+
+	/* Preserve R,G or B origin */
+	rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
+	rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
+
+	if (rect->width < 4)
+		rect->width = 4;
+	if (rect->height < 4)
+		rect->height = 4;
+	if (rect->width > bounds->width)
+		rect->width = bounds->width;
+	if (rect->height > bounds->height)
+		rect->height = bounds->height;
+	if (rect->left < bounds->left)
+		rect->left = bounds->left;
+	if (rect->top < bounds->top)
+		rect->top = bounds->top;
+	if (rect->left + rect->width > bounds->left + bounds->width)
+		rect->left = bounds->left+bounds->width - rect->width;
+	if (rect->top + rect->height > bounds->top + bounds->height)
+		rect->top = bounds->top+bounds->height - rect->height;
+
+	rect->width &= ~3L;
+	rect->height &= ~3L;
+
+	if (ET61X251_PRESERVE_IMGSCALE) {
+		/* Calculate the actual scaling factor */
+		u32 a, b;
+		a = rect->width * rect->height;
+		b = pix_format->width * pix_format->height;
+		scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1;
+	} else
+		scale = 1;
+
+	if (cam->stream == STREAM_ON)
+		if ((err = et61x251_stream_interrupt(cam)))
+			return err;
+
+	if (copy_to_user(arg, &crop, sizeof(crop))) {
+		cam->stream = stream;
+		return -EFAULT;
+	}
+
+	if (cam->module_param.force_munmap || cam->io == IO_READ)
+		et61x251_release_buffers(cam);
+
+	err = et61x251_set_crop(cam, rect);
+	if (s->set_crop)
+		err += s->set_crop(cam, rect);
+	err += et61x251_set_scale(cam, scale);
+
+	if (err) { /* atomic, no rollback in ioctl() */
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
+		       "use the camera, close and open /dev/video%d again.",
+		    cam->v4ldev->minor);
+		return -EIO;
+	}
+
+	s->pix_format.width = rect->width/scale;
+	s->pix_format.height = rect->height/scale;
+	memcpy(&(s->_rect), rect, sizeof(*rect));
+
+	if ((cam->module_param.force_munmap  || cam->io == IO_READ) &&
+	    nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) {
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
+		       "use the camera, close and open /dev/video%d again.",
+		    cam->v4ldev->minor);
+		return -ENOMEM;
+	}
+
+	if (cam->io == IO_READ)
+		et61x251_empty_framequeues(cam);
+	else if (cam->module_param.force_munmap)
+		et61x251_requeue_outqueue(cam);
+
+	cam->stream = stream;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_fmtdesc fmtd;
+
+	if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
+		return -EFAULT;
+
+	if (fmtd.index == 0) {
+		strcpy(fmtd.description, "bayer rgb");
+		fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
+	} else if (fmtd.index == 1) {
+		strcpy(fmtd.description, "compressed");
+		fmtd.pixelformat = V4L2_PIX_FMT_ET61X251;
+		fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
+	} else
+		return -EINVAL;
+
+	fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
+
+	if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_format format;
+	struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
+
+	if (copy_from_user(&format, arg, sizeof(format)))
+		return -EFAULT;
+
+	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251)
+	                     ? 0 : (pfmt->width * pfmt->priv) / 8;
+	pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
+	pfmt->field = V4L2_FIELD_NONE;
+	memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
+
+	if (copy_to_user(arg, &format, sizeof(format)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
+                          void __user * arg)
+{
+	struct et61x251_sensor* s = cam->sensor;
+	struct v4l2_format format;
+	struct v4l2_pix_format* pix;
+	struct v4l2_pix_format* pfmt = &(s->pix_format);
+	struct v4l2_rect* bounds = &(s->cropcap.bounds);
+	struct v4l2_rect rect;
+	u8 scale;
+	const enum et61x251_stream_state stream = cam->stream;
+	const u32 nbuffers = cam->nbuffers;
+	u32 i;
+	int err = 0;
+
+	if (copy_from_user(&format, arg, sizeof(format)))
+		return -EFAULT;
+
+	pix = &(format.fmt.pix);
+
+	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	memcpy(&rect, &(s->_rect), sizeof(rect));
+
+	{ /* calculate the actual scaling factor */
+		u32 a, b;
+		a = rect.width * rect.height;
+		b = pix->width * pix->height;
+		scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1;
+	}
+
+	rect.width = scale * pix->width;
+	rect.height = scale * pix->height;
+
+	if (rect.width < 4)
+		rect.width = 4;
+	if (rect.height < 4)
+		rect.height = 4;
+	if (rect.width > bounds->left + bounds->width - rect.left)
+		rect.width = bounds->left + bounds->width - rect.left;
+	if (rect.height > bounds->top + bounds->height - rect.top)
+		rect.height = bounds->top + bounds->height - rect.top;
+
+	rect.width &= ~3L;
+	rect.height &= ~3L;
+
+	{ /* adjust the scaling factor */
+		u32 a, b;
+		a = rect.width * rect.height;
+		b = pix->width * pix->height;
+		scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1;
+	}
+
+	pix->width = rect.width / scale;
+	pix->height = rect.height / scale;
+
+	if (pix->pixelformat != V4L2_PIX_FMT_ET61X251 &&
+	    pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+		pix->pixelformat = pfmt->pixelformat;
+	pix->priv = pfmt->priv; /* bpp */
+	pix->colorspace = pfmt->colorspace;
+	pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251)
+	                    ? 0 : (pix->width * pix->priv) / 8;
+	pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
+	pix->field = V4L2_FIELD_NONE;
+
+	if (cmd == VIDIOC_TRY_FMT) {
+		if (copy_to_user(arg, &format, sizeof(format)))
+			return -EFAULT;
+		return 0;
+	}
+
+	if (cam->module_param.force_munmap)
+		for (i = 0; i < cam->nbuffers; i++)
+			if (cam->frame[i].vma_use_count) {
+				DBG(3, "VIDIOC_S_FMT failed. "
+				       "Unmap the buffers first.");
+				return -EINVAL;
+			}
+
+	if (cam->stream == STREAM_ON)
+		if ((err = et61x251_stream_interrupt(cam)))
+			return err;
+
+	if (copy_to_user(arg, &format, sizeof(format))) {
+		cam->stream = stream;
+		return -EFAULT;
+	}
+
+	if (cam->module_param.force_munmap || cam->io == IO_READ)
+		et61x251_release_buffers(cam);
+
+	err += et61x251_set_pix_format(cam, pix);
+	err += et61x251_set_crop(cam, &rect);
+	if (s->set_pix_format)
+		err += s->set_pix_format(cam, pix);
+	if (s->set_crop)
+		err += s->set_crop(cam, &rect);
+	err += et61x251_set_scale(cam, scale);
+
+	if (err) { /* atomic, no rollback in ioctl() */
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
+		       "use the camera, close and open /dev/video%d again.",
+		    cam->v4ldev->minor);
+		return -EIO;
+	}
+
+	memcpy(pfmt, pix, sizeof(*pix));
+	memcpy(&(s->_rect), &rect, sizeof(rect));
+
+	if ((cam->module_param.force_munmap  || cam->io == IO_READ) &&
+	    nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) {
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
+		       "use the camera, close and open /dev/video%d again.",
+		    cam->v4ldev->minor);
+		return -ENOMEM;
+	}
+
+	if (cam->io == IO_READ)
+		et61x251_empty_framequeues(cam);
+	else if (cam->module_param.force_munmap)
+		et61x251_requeue_outqueue(cam);
+
+	cam->stream = stream;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_g_jpegcomp(struct et61x251_device* cam, void __user * arg)
+{
+	if (copy_to_user(arg, &cam->compression,
+	                 sizeof(cam->compression)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_jpegcompression jc;
+	const enum et61x251_stream_state stream = cam->stream;
+	int err = 0;
+
+	if (copy_from_user(&jc, arg, sizeof(jc)))
+		return -EFAULT;
+
+	if (jc.quality != 0 && jc.quality != 1)
+		return -EINVAL;
+
+	if (cam->stream == STREAM_ON)
+		if ((err = et61x251_stream_interrupt(cam)))
+			return err;
+
+	err += et61x251_set_compression(cam, &jc);
+	if (err) { /* atomic, no rollback in ioctl() */
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
+		       "problems. To use the camera, close and open "
+		       "/dev/video%d again.", cam->v4ldev->minor);
+		return -EIO;
+	}
+
+	cam->compression.quality = jc.quality;
+
+	cam->stream = stream;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_reqbufs(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_requestbuffers rb;
+	u32 i;
+	int err;
+
+	if (copy_from_user(&rb, arg, sizeof(rb)))
+		return -EFAULT;
+
+	if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    rb.memory != V4L2_MEMORY_MMAP)
+		return -EINVAL;
+
+	if (cam->io == IO_READ) {
+		DBG(3, "Close and open the device again to choose the mmap "
+		       "I/O method");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < cam->nbuffers; i++)
+		if (cam->frame[i].vma_use_count) {
+			DBG(3, "VIDIOC_REQBUFS failed. "
+			       "Previous buffers are still mapped.");
+			return -EINVAL;
+		}
+
+	if (cam->stream == STREAM_ON)
+		if ((err = et61x251_stream_interrupt(cam)))
+			return err;
+
+	et61x251_empty_framequeues(cam);
+
+	et61x251_release_buffers(cam);
+	if (rb.count)
+		rb.count = et61x251_request_buffers(cam, rb.count, IO_MMAP);
+
+	if (copy_to_user(arg, &rb, sizeof(rb))) {
+		et61x251_release_buffers(cam);
+		cam->io = IO_NONE;
+		return -EFAULT;
+	}
+
+	cam->io = rb.count ? IO_MMAP : IO_NONE;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_querybuf(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_buffer b;
+
+	if (copy_from_user(&b, arg, sizeof(b)))
+		return -EFAULT;
+
+	if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    b.index >= cam->nbuffers || cam->io != IO_MMAP)
+		return -EINVAL;
+
+	memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
+
+	if (cam->frame[b.index].vma_use_count)
+		b.flags |= V4L2_BUF_FLAG_MAPPED;
+
+	if (cam->frame[b.index].state == F_DONE)
+		b.flags |= V4L2_BUF_FLAG_DONE;
+	else if (cam->frame[b.index].state != F_UNUSED)
+		b.flags |= V4L2_BUF_FLAG_QUEUED;
+
+	if (copy_to_user(arg, &b, sizeof(b)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_qbuf(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_buffer b;
+	unsigned long lock_flags;
+
+	if (copy_from_user(&b, arg, sizeof(b)))
+		return -EFAULT;
+
+	if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    b.index >= cam->nbuffers || cam->io != IO_MMAP)
+		return -EINVAL;
+
+	if (cam->frame[b.index].state != F_UNUSED)
+		return -EINVAL;
+
+	cam->frame[b.index].state = F_QUEUED;
+
+	spin_lock_irqsave(&cam->queue_lock, lock_flags);
+	list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
+	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+	PDBGG("Frame #%lu queued", (unsigned long)b.index);
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp,
+                      void __user * arg)
+{
+	struct v4l2_buffer b;
+	struct et61x251_frame_t *f;
+	unsigned long lock_flags;
+	int err = 0;
+
+	if (copy_from_user(&b, arg, sizeof(b)))
+		return -EFAULT;
+
+	if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP)
+		return -EINVAL;
+
+	if (list_empty(&cam->outqueue)) {
+		if (cam->stream == STREAM_OFF)
+			return -EINVAL;
+		if (filp->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		err = wait_event_interruptible
+		      ( cam->wait_frame,
+		        (!list_empty(&cam->outqueue)) ||
+		        (cam->state & DEV_DISCONNECTED) ||
+		        (cam->state & DEV_MISCONFIGURED) );
+		if (err)
+			return err;
+		if (cam->state & DEV_DISCONNECTED)
+			return -ENODEV;
+		if (cam->state & DEV_MISCONFIGURED)
+			return -EIO;
+	}
+
+	spin_lock_irqsave(&cam->queue_lock, lock_flags);
+	f = list_entry(cam->outqueue.next, struct et61x251_frame_t, frame);
+	list_del(cam->outqueue.next);
+	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+	f->state = F_UNUSED;
+
+	memcpy(&b, &f->buf, sizeof(b));
+	if (f->vma_use_count)
+		b.flags |= V4L2_BUF_FLAG_MAPPED;
+
+	if (copy_to_user(arg, &b, sizeof(b)))
+		return -EFAULT;
+
+	PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_streamon(struct et61x251_device* cam, void __user * arg)
+{
+	int type;
+
+	if (copy_from_user(&type, arg, sizeof(type)))
+		return -EFAULT;
+
+	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+		return -EINVAL;
+
+	if (list_empty(&cam->inqueue))
+		return -EINVAL;
+
+	cam->stream = STREAM_ON;
+
+	DBG(3, "Stream on");
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_streamoff(struct et61x251_device* cam, void __user * arg)
+{
+	int type, err;
+
+	if (copy_from_user(&type, arg, sizeof(type)))
+		return -EFAULT;
+
+	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+		return -EINVAL;
+
+	if (cam->stream == STREAM_ON)
+		if ((err = et61x251_stream_interrupt(cam)))
+			return err;
+
+	et61x251_empty_framequeues(cam);
+
+	DBG(3, "Stream off");
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_g_parm(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_streamparm sp;
+
+	if (copy_from_user(&sp, arg, sizeof(sp)))
+		return -EFAULT;
+
+	if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	sp.parm.capture.extendedmode = 0;
+	sp.parm.capture.readbuffers = cam->nreadbuffers;
+
+	if (copy_to_user(arg, &sp, sizeof(sp)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_streamparm sp;
+
+	if (copy_from_user(&sp, arg, sizeof(sp)))
+		return -EFAULT;
+
+	if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	sp.parm.capture.extendedmode = 0;
+
+	if (sp.parm.capture.readbuffers == 0)
+		sp.parm.capture.readbuffers = cam->nreadbuffers;
+
+	if (sp.parm.capture.readbuffers > ET61X251_MAX_FRAMES)
+		sp.parm.capture.readbuffers = ET61X251_MAX_FRAMES;
+
+	if (copy_to_user(arg, &sp, sizeof(sp)))
+		return -EFAULT;
+
+	cam->nreadbuffers = sp.parm.capture.readbuffers;
+
+	return 0;
+}
+
+
+static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
+                               unsigned int cmd, void __user * arg)
+{
+	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+
+	switch (cmd) {
+
+	case VIDIOC_QUERYCAP:
+		return et61x251_vidioc_querycap(cam, arg);
+
+	case VIDIOC_ENUMINPUT:
+		return et61x251_vidioc_enuminput(cam, arg);
+
+	case VIDIOC_G_INPUT:
+	case VIDIOC_S_INPUT:
+		return et61x251_vidioc_gs_input(cam, arg);
+
+	case VIDIOC_QUERYCTRL:
+		return et61x251_vidioc_query_ctrl(cam, arg);
+
+	case VIDIOC_G_CTRL:
+		return et61x251_vidioc_g_ctrl(cam, arg);
+
+	case VIDIOC_S_CTRL_OLD:
+	case VIDIOC_S_CTRL:
+		return et61x251_vidioc_s_ctrl(cam, arg);
+
+	case VIDIOC_CROPCAP_OLD:
+	case VIDIOC_CROPCAP:
+		return et61x251_vidioc_cropcap(cam, arg);
+
+	case VIDIOC_G_CROP:
+		return et61x251_vidioc_g_crop(cam, arg);
+
+	case VIDIOC_S_CROP:
+		return et61x251_vidioc_s_crop(cam, arg);
+
+	case VIDIOC_ENUM_FMT:
+		return et61x251_vidioc_enum_fmt(cam, arg);
+
+	case VIDIOC_G_FMT:
+		return et61x251_vidioc_g_fmt(cam, arg);
+
+	case VIDIOC_TRY_FMT:
+	case VIDIOC_S_FMT:
+		return et61x251_vidioc_try_s_fmt(cam, cmd, arg);
+
+	case VIDIOC_G_JPEGCOMP:
+		return et61x251_vidioc_g_jpegcomp(cam, arg);
+
+	case VIDIOC_S_JPEGCOMP:
+		return et61x251_vidioc_s_jpegcomp(cam, arg);
+
+	case VIDIOC_REQBUFS:
+		return et61x251_vidioc_reqbufs(cam, arg);
+
+	case VIDIOC_QUERYBUF:
+		return et61x251_vidioc_querybuf(cam, arg);
+
+	case VIDIOC_QBUF:
+		return et61x251_vidioc_qbuf(cam, arg);
+
+	case VIDIOC_DQBUF:
+		return et61x251_vidioc_dqbuf(cam, filp, arg);
+
+	case VIDIOC_STREAMON:
+		return et61x251_vidioc_streamon(cam, arg);
+
+	case VIDIOC_STREAMOFF:
+		return et61x251_vidioc_streamoff(cam, arg);
+
+	case VIDIOC_G_PARM:
+		return et61x251_vidioc_g_parm(cam, arg);
+
+	case VIDIOC_S_PARM_OLD:
+	case VIDIOC_S_PARM:
+		return et61x251_vidioc_s_parm(cam, arg);
+
+	case VIDIOC_G_STD:
+	case VIDIOC_S_STD:
+	case VIDIOC_QUERYSTD:
+	case VIDIOC_ENUMSTD:
+	case VIDIOC_QUERYMENU:
+		return -EINVAL;
+
+	default:
+		return -EINVAL;
+
+	}
+}
+
+
+static int et61x251_ioctl(struct inode* inode, struct file* filp,
+                         unsigned int cmd, unsigned long arg)
+{
+	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+	int err = 0;
+
+	if (down_interruptible(&cam->fileop_sem))
+		return -ERESTARTSYS;
+
+	if (cam->state & DEV_DISCONNECTED) {
+		DBG(1, "Device not present");
+		up(&cam->fileop_sem);
+		return -ENODEV;
+	}
+
+	if (cam->state & DEV_MISCONFIGURED) {
+		DBG(1, "The camera is misconfigured. Close and open it "
+		       "again.");
+		up(&cam->fileop_sem);
+		return -EIO;
+	}
+
+	V4LDBG(3, "et61x251", cmd);
+
+	err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
+
+	up(&cam->fileop_sem);
+
+	return err;
+}
+
+
+static struct file_operations et61x251_fops = {
+	.owner = THIS_MODULE,
+	.open =    et61x251_open,
+	.release = et61x251_release,
+	.ioctl =   et61x251_ioctl,
+	.read =    et61x251_read,
+	.poll =    et61x251_poll,
+	.mmap =    et61x251_mmap,
+	.llseek =  no_llseek,
+};
+
+/*****************************************************************************/
+
+/* It exists a single interface only. We do not need to validate anything. */
+static int
+et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct et61x251_device* cam;
+	static unsigned int dev_nr = 0;
+	unsigned int i;
+	int err = 0;
+
+	if (!(cam = kzalloc(sizeof(struct et61x251_device), GFP_KERNEL)))
+		return -ENOMEM;
+
+	cam->usbdev = udev;
+
+	if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
+		DBG(1, "kmalloc() failed");
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	if (!(cam->v4ldev = video_device_alloc())) {
+		DBG(1, "video_device_alloc() failed");
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	init_MUTEX(&cam->dev_sem);
+
+	DBG(2, "ET61X[12]51 PC Camera Controller detected "
+	       "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct);
+
+	for  (i = 0; et61x251_sensor_table[i]; i++) {
+		err = et61x251_sensor_table[i](cam);
+		if (!err)
+			break;
+	}
+
+	if (!err && cam->sensor)
+		DBG(2, "%s image sensor detected", cam->sensor->name);
+	else {
+		DBG(1, "No supported image sensor detected");
+		err = -ENODEV;
+		goto fail;
+	}
+
+	if (et61x251_init(cam)) {
+		DBG(1, "Initialization failed. I will retry on open().");
+		cam->state |= DEV_MISCONFIGURED;
+	}
+
+	strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera");
+	cam->v4ldev->owner = THIS_MODULE;
+	cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
+	cam->v4ldev->hardware = 0;
+	cam->v4ldev->fops = &et61x251_fops;
+	cam->v4ldev->minor = video_nr[dev_nr];
+	cam->v4ldev->release = video_device_release;
+	video_set_drvdata(cam->v4ldev, cam);
+
+	down(&cam->dev_sem);
+
+	err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
+	                            video_nr[dev_nr]);
+	if (err) {
+		DBG(1, "V4L2 device registration failed");
+		if (err == -ENFILE && video_nr[dev_nr] == -1)
+			DBG(1, "Free /dev/videoX node not found");
+		video_nr[dev_nr] = -1;
+		dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
+		up(&cam->dev_sem);
+		goto fail;
+	}
+
+	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+
+	cam->module_param.force_munmap = force_munmap[dev_nr];
+
+	dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	et61x251_create_sysfs(cam);
+	DBG(2, "Optional device control through 'sysfs' interface ready");
+#endif
+
+	usb_set_intfdata(intf, cam);
+
+	up(&cam->dev_sem);
+
+	return 0;
+
+fail:
+	if (cam) {
+		kfree(cam->control_buffer);
+		if (cam->v4ldev)
+			video_device_release(cam->v4ldev);
+		kfree(cam);
+	}
+	return err;
+}
+
+
+static void et61x251_usb_disconnect(struct usb_interface* intf)
+{
+	struct et61x251_device* cam = usb_get_intfdata(intf);
+
+	if (!cam)
+		return;
+
+	down_write(&et61x251_disconnect);
+
+	down(&cam->dev_sem);
+
+	DBG(2, "Disconnecting %s...", cam->v4ldev->name);
+
+	wake_up_interruptible_all(&cam->open);
+
+	if (cam->users) {
+		DBG(2, "Device /dev/video%d is open! Deregistration and "
+		       "memory deallocation are deferred on close.",
+		    cam->v4ldev->minor);
+		cam->state |= DEV_MISCONFIGURED;
+		et61x251_stop_transfer(cam);
+		cam->state |= DEV_DISCONNECTED;
+		wake_up_interruptible(&cam->wait_frame);
+		wake_up_interruptible(&cam->wait_stream);
+	} else {
+		cam->state |= DEV_DISCONNECTED;
+		et61x251_release_resources(cam);
+	}
+
+	up(&cam->dev_sem);
+
+	if (!cam->users)
+		kfree(cam);
+
+	up_write(&et61x251_disconnect);
+}
+
+
+static struct usb_driver et61x251_usb_driver = {
+	.name =       "et61x251",
+	.id_table =   et61x251_id_table,
+	.probe =      et61x251_usb_probe,
+	.disconnect = et61x251_usb_disconnect,
+};
+
+/*****************************************************************************/
+
+static int __init et61x251_module_init(void)
+{
+	int err = 0;
+
+	KDBG(2, ET61X251_MODULE_NAME " v" ET61X251_MODULE_VERSION);
+	KDBG(3, ET61X251_MODULE_AUTHOR);
+
+	if ((err = usb_register(&et61x251_usb_driver)))
+		KDBG(1, "usb_register() failed");
+
+	return err;
+}
+
+
+static void __exit et61x251_module_exit(void)
+{
+	usb_deregister(&et61x251_usb_driver);
+}
+
+
+module_init(et61x251_module_init);
+module_exit(et61x251_module_exit);
diff --git a/drivers/usb/media/et61x251_sensor.h b/drivers/usb/media/et61x251_sensor.h
new file mode 100644
index 0000000..b9df910
--- /dev/null
+++ b/drivers/usb/media/et61x251_sensor.h
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * API for image sensors connected to ET61X[12]51 PC Camera Controllers    *
+ *                                                                         *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#ifndef _ET61X251_SENSOR_H_
+#define _ET61X251_SENSOR_H_
+
+#include <linux/usb.h>
+#include <linux/videodev.h>
+#include <linux/device.h>
+#include <linux/stddef.h>
+#include <linux/errno.h>
+#include <asm/types.h>
+
+struct et61x251_device;
+struct et61x251_sensor;
+
+/*****************************************************************************/
+
+extern int et61x251_probe_tas5130d1b(struct et61x251_device* cam);
+
+#define ET61X251_SENSOR_TABLE                                                 \
+/* Weak detections must go at the end of the list */                          \
+static int (*et61x251_sensor_table[])(struct et61x251_device*) = {            \
+	&et61x251_probe_tas5130d1b,                                           \
+	NULL,                                                                 \
+};
+
+extern void
+et61x251_attach_sensor(struct et61x251_device* cam,
+                       struct et61x251_sensor* sensor);
+
+/*****************************************************************************/
+
+extern int et61x251_write_reg(struct et61x251_device*, u8 value, u16 index);
+extern int et61x251_read_reg(struct et61x251_device*, u16 index);
+extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value);
+extern int et61x251_i2c_read(struct et61x251_device*, u8 address);
+extern int et61x251_i2c_try_write(struct et61x251_device*,
+                                  struct et61x251_sensor*, u8 address,
+                                  u8 value);
+extern int et61x251_i2c_try_read(struct et61x251_device*,
+                                 struct et61x251_sensor*, u8 address);
+extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1,
+                                  u8 data2, u8 data3, u8 data4, u8 data5,
+                                  u8 data6, u8 data7, u8 data8, u8 address);
+
+/*****************************************************************************/
+
+enum et61x251_i2c_sysfs_ops {
+	ET61X251_I2C_READ = 0x01,
+	ET61X251_I2C_WRITE = 0x02,
+};
+
+enum et61x251_i2c_interface {
+	ET61X251_I2C_2WIRES,
+	ET61X251_I2C_3WIRES,
+};
+
+/* Repeat start condition when RSTA is high */
+enum et61x251_i2c_rsta {
+	ET61X251_I2C_RSTA_STOP = 0x00, /* stop then start */
+	ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */
+};
+
+#define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
+
+struct et61x251_sensor {
+	char name[32];
+
+	enum et61x251_i2c_sysfs_ops sysfs_ops;
+
+	enum et61x251_i2c_interface interface;
+	u8 i2c_slave_id;
+	enum et61x251_i2c_rsta rsta;
+	struct v4l2_rect active_pixel; /* left and top define FVSX and FVSY */
+
+	struct v4l2_queryctrl qctrl[ET61X251_MAX_CTRLS];
+	struct v4l2_cropcap cropcap;
+	struct v4l2_pix_format pix_format;
+
+	int (*init)(struct et61x251_device* cam);
+	int (*get_ctrl)(struct et61x251_device* cam,
+	                struct v4l2_control* ctrl);
+	int (*set_ctrl)(struct et61x251_device* cam,
+	                const struct v4l2_control* ctrl);
+	int (*set_crop)(struct et61x251_device* cam,
+	                const struct v4l2_rect* rect);
+	int (*set_pix_format)(struct et61x251_device* cam,
+	                      const struct v4l2_pix_format* pix);
+
+	const struct usb_device* usbdev;
+
+	/* Private */
+	struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS];
+	struct v4l2_rect _rect;
+};
+
+#endif /* _ET61X251_SENSOR_H_ */
diff --git a/drivers/usb/media/et61x251_tas5130d1b.c b/drivers/usb/media/et61x251_tas5130d1b.c
new file mode 100644
index 0000000..65f1ae9
--- /dev/null
+++ b/drivers/usb/media/et61x251_tas5130d1b.c
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51        *
+ * PC Camera Controllers                                                   *
+ *                                                                         *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; 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 "et61x251_sensor.h"
+
+
+static int tas5130d1b_init(struct et61x251_device* cam)
+{
+	int err = 0;
+
+	err += et61x251_write_reg(cam, 0x14, 0x01);
+	err += et61x251_write_reg(cam, 0x1b, 0x02);
+	err += et61x251_write_reg(cam, 0x02, 0x12);
+	err += et61x251_write_reg(cam, 0x0e, 0x60);
+	err += et61x251_write_reg(cam, 0x80, 0x61);
+	err += et61x251_write_reg(cam, 0xf0, 0x62);
+	err += et61x251_write_reg(cam, 0x03, 0x63);
+	err += et61x251_write_reg(cam, 0x14, 0x64);
+	err += et61x251_write_reg(cam, 0xf4, 0x65);
+	err += et61x251_write_reg(cam, 0x01, 0x66);
+	err += et61x251_write_reg(cam, 0x05, 0x67);
+	err += et61x251_write_reg(cam, 0x8f, 0x68);
+	err += et61x251_write_reg(cam, 0x0f, 0x8d);
+	err += et61x251_write_reg(cam, 0x08, 0x8e);
+
+	return err;
+}
+
+
+static int tas5130d1b_set_ctrl(struct et61x251_device* cam,
+                               const struct v4l2_control* ctrl)
+{
+	int err = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		err += et61x251_i2c_raw_write(cam, 2, 0x20,
+		                              0xf6-ctrl->value, 0, 0, 0,
+		                              0, 0, 0, 0);
+		break;
+	case V4L2_CID_EXPOSURE:
+		err += et61x251_i2c_raw_write(cam, 2, 0x40,
+		                              0x47-ctrl->value, 0, 0, 0,
+		                              0, 0, 0, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err ? -EIO : 0;
+}
+
+
+static struct et61x251_sensor tas5130d1b = {
+	.name = "TAS5130D1B",
+	.interface = ET61X251_I2C_3WIRES,
+	.rsta = ET61X251_I2C_RSTA_STOP,
+	.active_pixel = {
+		.left = 106,
+		.top = 13,
+	},
+	.init = &tas5130d1b_init,
+	.qctrl = {
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0xf6,
+			.step = 0x02,
+			.default_value = 0x0d,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_EXPOSURE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "exposure",
+			.minimum = 0x00,
+			.maximum = 0x47,
+			.step = 0x01,
+			.default_value = 0x23,
+			.flags = 0,
+		},
+	},
+	.set_ctrl = &tas5130d1b_set_ctrl,
+	.cropcap = {
+		.bounds = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+		.defrect = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+	},
+	.pix_format = {
+		.width = 640,
+		.height = 480,
+		.pixelformat = V4L2_PIX_FMT_SBGGR8,
+		.priv = 8,
+	},
+};
+
+
+int et61x251_probe_tas5130d1b(struct et61x251_device* cam)
+{
+	/* This sensor has no identifiers, so let's attach it anyway */
+	et61x251_attach_sensor(cam, &tas5130d1b);
+
+	/* Sensor detection is based on USB pid/vid */
+	if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6251)
+		return -ENODEV;
+
+	return 0;
+}
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 8af665b..51e9cc0 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -204,22 +204,10 @@
 
 static struct usb_driver ov511_driver;
 
-static struct ov51x_decomp_ops *ov511_decomp_ops;
-static struct ov51x_decomp_ops *ov511_mmx_decomp_ops;
-static struct ov51x_decomp_ops *ov518_decomp_ops;
-static struct ov51x_decomp_ops *ov518_mmx_decomp_ops;
-
 /* Number of times to retry a failed I2C transaction. Increase this if you
  * are getting "Failed to read sensor ID..." */
 static const int i2c_detect_tries = 5;
 
-/* MMX support is present in kernel and CPU. Checked upon decomp module load. */
-#if defined(__i386__) || defined(__x86_64__)
-#define ov51x_mmx_available (cpu_has_mmx)
-#else
-#define ov51x_mmx_available (0)
-#endif
-
 static struct usb_device_id device_table [] = {
 	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
 	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
@@ -3012,93 +3000,18 @@
  *
  **********************************************************************/
 
-/* Chooses a decompression module, locks it, and sets ov->decomp_ops
- * accordingly. Returns -ENXIO if decompressor is not available, otherwise
- * returns 0 if no other error.
- */
 static int
 request_decompressor(struct usb_ov511 *ov)
 {
-	if (!ov)
-		return -ENODEV;
-
-	if (ov->decomp_ops) {
-		err("ERROR: Decompressor already requested!");
-		return -EINVAL;
-	}
-
-	lock_kernel();
-
-	/* Try to get MMX, and fall back on no-MMX if necessary */
-	if (ov->bclass == BCL_OV511) {
-		if (ov511_mmx_decomp_ops) {
-			PDEBUG(3, "Using OV511 MMX decompressor");
-			ov->decomp_ops = ov511_mmx_decomp_ops;
-		} else if (ov511_decomp_ops) {
-			PDEBUG(3, "Using OV511 decompressor");
-			ov->decomp_ops = ov511_decomp_ops;
-		} else {
-			err("No decompressor available");
-		}
-	} else if (ov->bclass == BCL_OV518) {
-		if (ov518_mmx_decomp_ops) {
-			PDEBUG(3, "Using OV518 MMX decompressor");
-			ov->decomp_ops = ov518_mmx_decomp_ops;
-		} else if (ov518_decomp_ops) {
-			PDEBUG(3, "Using OV518 decompressor");
-			ov->decomp_ops = ov518_decomp_ops;
-		} else {
-			err("No decompressor available");
-		}
+	if (ov->bclass == BCL_OV511 || ov->bclass == BCL_OV518) {
+		err("No decompressor available");
 	} else {
 		err("Unknown bridge");
 	}
 
-	if (!ov->decomp_ops)
-		goto nosys;
-
-	if (!ov->decomp_ops->owner) {
-		ov->decomp_ops = NULL;
-		goto nosys;
-	}
-	
-	if (!try_module_get(ov->decomp_ops->owner))
-		goto nosys;
-
-	unlock_kernel();
-	return 0;
-
- nosys:
-	unlock_kernel();
 	return -ENOSYS;
 }
 
-/* Unlocks decompression module and nulls ov->decomp_ops. Safe to call even
- * if ov->decomp_ops is NULL.
- */
-static void
-release_decompressor(struct usb_ov511 *ov)
-{
-	int released = 0;	/* Did we actually do anything? */
-
-	if (!ov)
-		return;
-
-	lock_kernel();
-
-	if (ov->decomp_ops) {
-		module_put(ov->decomp_ops->owner);
-		released = 1;
-	}
-
-	ov->decomp_ops = NULL;
-
-	unlock_kernel();
-
-	if (released)
-		PDEBUG(3, "Decompressor released");
-}
-
 static void
 decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
 	   unsigned char *pIn0, unsigned char *pOut0)
@@ -3107,31 +3020,6 @@
 		if (request_decompressor(ov))
 			return;
 
-	PDEBUG(4, "Decompressing %d bytes", frame->bytes_recvd);
-
-	if (frame->format == VIDEO_PALETTE_GREY
-	    && ov->decomp_ops->decomp_400) {
-		int ret = ov->decomp_ops->decomp_400(
-			pIn0,
-			pOut0,
-			frame->compbuf,
-			frame->rawwidth,
-			frame->rawheight,
-			frame->bytes_recvd);
-		PDEBUG(4, "DEBUG: decomp_400 returned %d", ret);
-	} else if (frame->format != VIDEO_PALETTE_GREY
-		   && ov->decomp_ops->decomp_420) {
-		int ret = ov->decomp_ops->decomp_420(
-			pIn0,
-			pOut0,
-			frame->compbuf,
-			frame->rawwidth,
-			frame->rawheight,
-			frame->bytes_recvd);
-		PDEBUG(4, "DEBUG: decomp_420 returned %d", ret);
-	} else {
-		err("Decompressor does not support this format");
-	}
 }
 
 /**********************************************************************
@@ -4087,8 +3975,6 @@
 	ov->user--;
 	ov51x_stop_isoc(ov);
 
-	release_decompressor(ov);
-
 	if (ov->led_policy == LED_AUTO)
 		ov51x_led_control(ov, 0);
 
@@ -6021,82 +5907,6 @@
  *
  ***************************************************************************/
 
-/* Returns 0 for success */
-int
-ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, int ov518,
-			     int mmx)
-{
-	if (ver != DECOMP_INTERFACE_VER) {
-		err("Decompression module has incompatible");
-		err("interface version %d", ver);
-		err("Interface version %d is required", DECOMP_INTERFACE_VER);
-		return -EINVAL;
-	}
-
-	if (!ops)
-		return -EFAULT;
-
-	if (mmx && !ov51x_mmx_available) {
-		err("MMX not available on this system or kernel");
-		return -EINVAL;
-	}
-
-	lock_kernel();
-
-	if (ov518) {
-		if (mmx) {
-			if (ov518_mmx_decomp_ops)
-				goto err_in_use;
-			else
-				ov518_mmx_decomp_ops = ops;
-		} else {
-			if (ov518_decomp_ops)
-				goto err_in_use;
-			else
-				ov518_decomp_ops = ops;
-		}
-	} else {
-		if (mmx) {
-			if (ov511_mmx_decomp_ops)
-				goto err_in_use;
-			else
-				ov511_mmx_decomp_ops = ops;
-		} else {
-			if (ov511_decomp_ops)
-				goto err_in_use;
-			else
-				ov511_decomp_ops = ops;
-		}
-	}
-
-	unlock_kernel();
-	return 0;
-
-err_in_use:
-	unlock_kernel();
-	return -EBUSY;
-}
-
-void
-ov511_deregister_decomp_module(int ov518, int mmx)
-{
-	lock_kernel();
-
-	if (ov518) {
-		if (mmx)
-			ov518_mmx_decomp_ops = NULL;
-		else
-			ov518_decomp_ops = NULL;
-	} else {
-		if (mmx)
-			ov511_mmx_decomp_ops = NULL;
-		else
-			ov511_decomp_ops = NULL;
-	}
-
-	unlock_kernel();
-}
-
 static int __init
 usb_ov511_init(void)
 {
@@ -6123,5 +5933,3 @@
 module_init(usb_ov511_init);
 module_exit(usb_ov511_exit);
 
-EXPORT_SYMBOL(ov511_register_decomp_module);
-EXPORT_SYMBOL(ov511_deregister_decomp_module);
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
index 359c4b2..3ebb6e9 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -1152,45 +1152,6 @@
  /* End of Add-Ons                                    */
  /* ************************************************* */
 
-/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
-   ioctl() calls. With 2.4, you have to do tedious copy_from_user()
-   and copy_to_user() calls. With these macros we circumvent this,
-   and let me maintain only one source file. The functionality is
-   exactly the same otherwise.
- */   
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-
-/* define local variable for arg */
-#define ARG_DEF(ARG_type, ARG_name)\
-	ARG_type *ARG_name = arg;
-/* copy arg to local variable */	
-#define ARG_IN(ARG_name) /* nothing */
-/* argument itself (referenced) */
-#define ARGR(ARG_name) (*ARG_name)
-/* argument address */
-#define ARGA(ARG_name) ARG_name
-/* copy local variable to arg */
-#define ARG_OUT(ARG_name) /* nothing */
-
-#else
-
-#define ARG_DEF(ARG_type, ARG_name)\
-	ARG_type ARG_name;
-#define ARG_IN(ARG_name)\
-	if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\
-		ret = -EFAULT;\
-		break;\
-	}
-#define ARGR(ARG_name) ARG_name
-#define ARGA(ARG_name) &ARG_name
-#define ARG_OUT(ARG_name)\
-	if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\
-		ret = -EFAULT;\
-		break;\
-	}
-
-#endif
 
 int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 {
@@ -1220,243 +1181,206 @@
 	
 	case VIDIOCPWCSCQUAL:
 	{	
-		ARG_DEF(int, qual)
+		int *qual = arg;
 
-		ARG_IN(qual)
-		if (ARGR(qual) < 0 || ARGR(qual) > 3)
+		if (*qual < 0 || *qual > 3)
 			ret = -EINVAL;
 		else
-			ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
+			ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
 		if (ret >= 0)
-			pdev->vcompression = ARGR(qual);
+			pdev->vcompression = *qual;
 		break;
 	}
 	
 	case VIDIOCPWCGCQUAL:
 	{
-		ARG_DEF(int, qual)
-		
-		ARGR(qual) = pdev->vcompression;
-		ARG_OUT(qual)
+		int *qual = arg;
+		*qual = pdev->vcompression;
 		break;
 	}
 	
 	case VIDIOCPWCPROBE:
 	{
-		ARG_DEF(struct pwc_probe, probe)
-		
-		strcpy(ARGR(probe).name, pdev->vdev->name);
-		ARGR(probe).type = pdev->type;
-		ARG_OUT(probe)
+		struct pwc_probe *probe = arg;
+		strcpy(probe->name, pdev->vdev->name);
+		probe->type = pdev->type;
 		break;
 	}
 
 	case VIDIOCPWCGSERIAL:
 	{
-		ARG_DEF(struct pwc_serial, serial)
-		
-		strcpy(ARGR(serial).serial, pdev->serial);
-		ARG_OUT(serial)
+		struct pwc_serial *serial = arg;
+		strcpy(serial->serial, pdev->serial);
 		break;
 	}
 
 	case VIDIOCPWCSAGC:
 	{
-		ARG_DEF(int, agc)
-
-		ARG_IN(agc)
-		if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
+		int *agc = arg;
+		if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc))
 			ret = -EINVAL;
 		break;
 	}
 	
 	case VIDIOCPWCGAGC:
 	{
-		ARG_DEF(int, agc)
+		int *agc = arg;
 		
-		if (pwc_get_agc(pdev, ARGA(agc)))
+		if (pwc_get_agc(pdev, agc))
 			ret = -EINVAL;
-		ARG_OUT(agc)
 		break;
 	}
 	
 	case VIDIOCPWCSSHUTTER:
 	{
-		ARG_DEF(int, shutter_speed)
-
-		ARG_IN(shutter_speed)
-		ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
+		int *shutter_speed = arg;
+		ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
 		break;
 	}
 	
         case VIDIOCPWCSAWB:
 	{
-		ARG_DEF(struct pwc_whitebalance, wb)
+		struct pwc_whitebalance *wb = arg;
 		
-		ARG_IN(wb)
-		ret = pwc_set_awb(pdev, ARGR(wb).mode);
-		if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
-			pwc_set_red_gain(pdev, ARGR(wb).manual_red);
-			pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
+		ret = pwc_set_awb(pdev, wb->mode);
+		if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
+			pwc_set_red_gain(pdev, wb->manual_red);
+			pwc_set_blue_gain(pdev, wb->manual_blue);
 		}
 		break;
 	}
 
 	case VIDIOCPWCGAWB:
 	{
-		ARG_DEF(struct pwc_whitebalance, wb)
+		struct pwc_whitebalance *wb = arg;
 
-		memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
-		ARGR(wb).mode = pwc_get_awb(pdev);
-		if (ARGR(wb).mode < 0)
+		memset(wb, 0, sizeof(struct pwc_whitebalance));
+		wb->mode = pwc_get_awb(pdev);
+		if (wb->mode < 0)
 			ret = -EINVAL;
 		else {
-			if (ARGR(wb).mode == PWC_WB_MANUAL) {
-				ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
+			if (wb->mode == PWC_WB_MANUAL) {
+				ret = pwc_get_red_gain(pdev, &wb->manual_red);
 				if (ret < 0)
 					break;
-				ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
+				ret = pwc_get_blue_gain(pdev, &wb->manual_blue);
 				if (ret < 0)
 					break;
 			}
-			if (ARGR(wb).mode == PWC_WB_AUTO) {
-				ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
+			if (wb->mode == PWC_WB_AUTO) {
+				ret = pwc_read_red_gain(pdev, &wb->read_red);
 				if (ret < 0)
 					break;
- 				ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
+ 				ret = pwc_read_blue_gain(pdev, &wb->read_blue);
  				if (ret < 0)
  					break;
 			}
 		}
-		ARG_OUT(wb)
 		break;
 	}
 	
 	case VIDIOCPWCSAWBSPEED:
 	{
-		ARG_DEF(struct pwc_wb_speed, wbs)
+		struct pwc_wb_speed *wbs = arg;
 		
-		if (ARGR(wbs).control_speed > 0) {
-			ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
+		if (wbs->control_speed > 0) {
+			ret = pwc_set_wb_speed(pdev, wbs->control_speed);
 		}
-		if (ARGR(wbs).control_delay > 0) {
-			ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
+		if (wbs->control_delay > 0) {
+			ret = pwc_set_wb_delay(pdev, wbs->control_delay);
 		}
 		break;
 	}
 	
 	case VIDIOCPWCGAWBSPEED:
 	{
-		ARG_DEF(struct pwc_wb_speed, wbs)
+		struct pwc_wb_speed *wbs = arg;
 		
-		ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
+		ret = pwc_get_wb_speed(pdev, &wbs->control_speed);
 		if (ret < 0)
 			break;
-		ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
+		ret = pwc_get_wb_delay(pdev, &wbs->control_delay);
 		if (ret < 0)
 			break;
-		ARG_OUT(wbs)
 		break;
 	}
 
         case VIDIOCPWCSLED:
 	{
-		ARG_DEF(struct pwc_leds, leds)
-
-		ARG_IN(leds)
-		ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
+		struct pwc_leds *leds = arg;
+		ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
 	    	break;
 	}
 
 
 	case VIDIOCPWCGLED:
 	{
-		ARG_DEF(struct pwc_leds, leds)
-		
-		ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
-		ARG_OUT(leds)
+		struct pwc_leds *leds = arg;
+		ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off);
 		break;
 	}
 
 	case VIDIOCPWCSCONTOUR:
 	{
-		ARG_DEF(int, contour)
-
-		ARG_IN(contour)
-		ret = pwc_set_contour(pdev, ARGR(contour));
+		int *contour = arg;
+		ret = pwc_set_contour(pdev, *contour);
 		break;
 	}
 			
 	case VIDIOCPWCGCONTOUR:
 	{
-		ARG_DEF(int, contour)
-		
-		ret = pwc_get_contour(pdev, ARGA(contour));
-		ARG_OUT(contour)
+		int *contour = arg;
+		ret = pwc_get_contour(pdev, contour);
 		break;
 	}
 	
 	case VIDIOCPWCSBACKLIGHT:
 	{
-		ARG_DEF(int, backlight)
-		
-		ARG_IN(backlight)
-		ret = pwc_set_backlight(pdev, ARGR(backlight));
+		int *backlight = arg;
+		ret = pwc_set_backlight(pdev, *backlight);
 		break;
 	}
 
 	case VIDIOCPWCGBACKLIGHT:
 	{
-		ARG_DEF(int, backlight)
-		
-		ret = pwc_get_backlight(pdev, ARGA(backlight));
-		ARG_OUT(backlight)
+		int *backlight = arg;
+		ret = pwc_get_backlight(pdev, backlight);
 		break;
 	}
 	
 	case VIDIOCPWCSFLICKER:
 	{
-		ARG_DEF(int, flicker)
-		
-		ARG_IN(flicker)
-		ret = pwc_set_flicker(pdev, ARGR(flicker));
+		int *flicker = arg;
+		ret = pwc_set_flicker(pdev, *flicker);
 		break;
 	}
 
 	case VIDIOCPWCGFLICKER:
 	{
-		ARG_DEF(int, flicker)
-		
-		ret = pwc_get_flicker(pdev, ARGA(flicker));
-		ARG_OUT(flicker)
+		int *flicker = arg;
+		ret = pwc_get_flicker(pdev, flicker);
 		break;
 	}
 	
 	case VIDIOCPWCSDYNNOISE:
 	{
-		ARG_DEF(int, dynnoise)
-		
-		ARG_IN(dynnoise)
-		ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
+		int *dynnoise = arg;
+		ret = pwc_set_dynamic_noise(pdev, *dynnoise);
 		break;
 	}
 	
 	case VIDIOCPWCGDYNNOISE:
 	{
-		ARG_DEF(int, dynnoise)
-
-		ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
-		ARG_OUT(dynnoise);
+		int *dynnoise = arg;
+		ret = pwc_get_dynamic_noise(pdev, dynnoise);
 		break;
 	}
 
 	case VIDIOCPWCGREALSIZE:
 	{
-		ARG_DEF(struct pwc_imagesize, size)
-		
-		ARGR(size).width = pdev->image.x;
-		ARGR(size).height = pdev->image.y;
-		ARG_OUT(size)
+		struct pwc_imagesize *size = arg;
+		size->width = pdev->image.x;
+		size->height = pdev->image.y;
 		break;
  	}
  	
@@ -1464,10 +1388,9 @@
  	{
  		if (pdev->features & FEATURE_MOTOR_PANTILT)
  		{
-	 		ARG_DEF(int, flags)
+	 		int *flags = arg;
 
- 			ARG_IN(flags)
-			ret = pwc_mpt_reset(pdev, ARGR(flags));
+			ret = pwc_mpt_reset(pdev, *flags);
  			if (ret >= 0)
  			{
  				pdev->pan_angle = 0;
@@ -1485,10 +1408,8 @@
  	{
  		if (pdev->features & FEATURE_MOTOR_PANTILT)
  		{
- 			ARG_DEF(struct pwc_mpt_range, range)
- 			
- 			ARGR(range) = pdev->angle_range;
- 			ARG_OUT(range)
+ 			struct pwc_mpt_range *range = arg;
+ 			*range = pdev->angle_range;
  		}
  		else
  		{	
@@ -1503,21 +1424,19 @@
  		
  		if (pdev->features & FEATURE_MOTOR_PANTILT)
  		{
-	 		ARG_DEF(struct pwc_mpt_angles, angles)
-
-	 		ARG_IN(angles)
+	 		struct pwc_mpt_angles *angles = arg;
 			/* The camera can only set relative angles, so
 			   do some calculations when getting an absolute angle .
 			 */
-			if (ARGR(angles).absolute)
+			if (angles->absolute)
 			{
- 				new_pan  = ARGR(angles).pan; 
- 				new_tilt = ARGR(angles).tilt;
+ 				new_pan  = angles->pan;
+ 				new_tilt = angles->tilt;
  			}
  			else
  			{
- 				new_pan  = pdev->pan_angle  + ARGR(angles).pan;
- 				new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
+ 				new_pan  = pdev->pan_angle  + angles->pan;
+ 				new_tilt = pdev->tilt_angle + angles->tilt;
 			}
 			/* check absolute ranges */
 			if (new_pan  < pdev->angle_range.pan_min  ||
@@ -1560,12 +1479,11 @@
  		
  		if (pdev->features & FEATURE_MOTOR_PANTILT)
  		{
-	 		ARG_DEF(struct pwc_mpt_angles, angles)
+	 		struct pwc_mpt_angles *angles = arg;
 
- 			ARGR(angles).absolute = 1;
- 			ARGR(angles).pan  = pdev->pan_angle;
- 			ARGR(angles).tilt = pdev->tilt_angle;
- 			ARG_OUT(angles)
+ 			angles->absolute = 1;
+ 			angles->pan  = pdev->pan_angle;
+ 			angles->tilt = pdev->tilt_angle;
  		}
  		else
  		{
@@ -1578,10 +1496,8 @@
  	{
  		if (pdev->features & FEATURE_MOTOR_PANTILT)
  		{
- 			ARG_DEF(struct pwc_mpt_status, status)
- 			
- 			ret = pwc_mpt_get_status(pdev, ARGA(status));
- 			ARG_OUT(status)
+ 			struct pwc_mpt_status *status = arg;
+ 			ret = pwc_mpt_get_status(pdev, status);
  		}
  		else
  		{
@@ -1592,24 +1508,22 @@
 
 	case VIDIOCPWCGVIDCMD:
 	{
-		ARG_DEF(struct pwc_video_command, cmd);
+		struct pwc_video_command *cmd = arg;
 		
-                ARGR(cmd).type = pdev->type;
-		ARGR(cmd).release = pdev->release;
-		ARGR(cmd).command_len = pdev->cmd_len;
-		memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
-		ARGR(cmd).bandlength = pdev->vbandlength;
-		ARGR(cmd).frame_size = pdev->frame_size;
-		ARG_OUT(cmd)
+                cmd->type = pdev->type;
+		cmd->release = pdev->release;
+		cmd->command_len = pdev->cmd_len;
+		memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len);
+		cmd->bandlength = pdev->vbandlength;
+		cmd->frame_size = pdev->frame_size;
 		break;
 	}
        /*
 	case VIDIOCPWCGVIDTABLE:
 	{
-		ARG_DEF(struct pwc_table_init_buffer, table);
-		ARGR(table).len = pdev->cmd_len;
-		memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
-		ARG_OUT(table)
+		struct pwc_table_init_buffer *table = arg;
+		table->len = pdev->cmd_len;
+		memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size);
 		break;
 	}
 	*/
diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
index e5cea0e..17d60c1 100644
--- a/drivers/usb/media/sn9c102.h
+++ b/drivers/usb/media/sn9c102.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  * V4L2 driver for SN9C10x PC Camera Controllers                           *
  *                                                                         *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -23,7 +23,8 @@
 
 #include <linux/version.h>
 #include <linux/usb.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
@@ -52,13 +53,6 @@
 
 /*****************************************************************************/
 
-#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C10x PC Camera Controllers"
-#define SN9C102_MODULE_AUTHOR   "(C) 2004-2005 Luca Risolia"
-#define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
-#define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.24a"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 24)
-
 enum sn9c102_bridge {
 	BRIDGE_SN9C101 = 0x01,
 	BRIDGE_SN9C102 = 0x02,
@@ -102,12 +96,13 @@
 	STREAM_ON,
 };
 
+typedef char sn9c103_sof_header_t[18];
 typedef char sn9c102_sof_header_t[12];
 typedef char sn9c102_eof_header_t[4];
 
 struct sn9c102_sysfs_attr {
 	u8 reg, i2c_reg;
-	sn9c102_sof_header_t frame_header;
+	sn9c103_sof_header_t frame_header;
 };
 
 struct sn9c102_module_param {
@@ -118,8 +113,6 @@
 static DECLARE_RWSEM(sn9c102_disconnect);
 
 struct sn9c102_device {
-	struct device dev;
-
 	struct video_device* v4ldev;
 
 	enum sn9c102_bridge bridge;
@@ -140,8 +133,8 @@
 	struct v4l2_jpegcompression compression;
 
 	struct sn9c102_sysfs_attr sysfs;
-	sn9c102_sof_header_t sof_header;
-	u16 reg[32];
+	sn9c103_sof_header_t sof_header;
+	u16 reg[63];
 
 	struct sn9c102_module_param module_param;
 
@@ -160,7 +153,6 @@
                       struct sn9c102_sensor* sensor)
 {
 	cam->sensor = sensor;
-	cam->sensor->dev = &cam->dev;
 	cam->sensor->usbdev = cam->usbdev;
 }
 
@@ -170,19 +162,24 @@
 #undef KDBG
 #ifdef SN9C102_DEBUG
 #	define DBG(level, fmt, args...)                                       \
-{                                                                             \
+do {                                                                          \
 	if (debug >= (level)) {                                               \
 		if ((level) == 1)                                             \
-			dev_err(&cam->dev, fmt "\n", ## args);                \
+			dev_err(&cam->usbdev->dev, fmt "\n", ## args);        \
 		else if ((level) == 2)                                        \
-			dev_info(&cam->dev, fmt "\n", ## args);               \
+			dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
 		else if ((level) >= 3)                                        \
-			dev_info(&cam->dev, "[%s:%d] " fmt "\n",              \
+			dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",      \
 			         __FUNCTION__, __LINE__ , ## args);           \
 	}                                                                     \
-}
+} while (0)
+#	define V4LDBG(level, name, cmd)                                       \
+do {                                                                          \
+	if (debug >= (level))                                                 \
+		v4l_print_ioctl(name, cmd);                                   \
+} while (0)
 #	define KDBG(level, fmt, args...)                                      \
-{                                                                             \
+do {                                                                          \
 	if (debug >= (level)) {                                               \
 		if ((level) == 1 || (level) == 2)                             \
 			pr_info("sn9c102: " fmt "\n", ## args);               \
@@ -190,17 +187,18 @@
 			pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__,  \
 			         __LINE__ , ## args);                         \
 	}                                                                     \
-}
+} while (0)
 #else
-#	define KDBG(level, fmt, args...) do {;} while(0);
-#	define DBG(level, fmt, args...) do {;} while(0);
+#	define DBG(level, fmt, args...) do {;} while(0)
+#	define V4LDBG(level, name, cmd) do {;} while(0)
+#	define KDBG(level, fmt, args...) do {;} while(0)
 #endif
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args);
+dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
 
 #undef PDBGG
-#define PDBGG(fmt, args...) do {;} while(0); /* placeholder */
+#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
 
 #endif /* _SN9C102_H_ */
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index 8d1a1c3..c81397e 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -1,7 +1,7 @@
 /***************************************************************************
  * V4L2 driver for SN9C10x PC Camera Controllers                           *
  *                                                                         *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -45,6 +45,15 @@
 
 /*****************************************************************************/
 
+#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C10x PC Camera Controllers"
+#define SN9C102_MODULE_AUTHOR   "(C) 2004-2006 Luca Risolia"
+#define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
+#define SN9C102_MODULE_LICENSE  "GPL"
+#define SN9C102_MODULE_VERSION  "1:1.26"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 26)
+
+/*****************************************************************************/
+
 MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
 
 MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
@@ -70,10 +79,10 @@
                                SN9C102_FORCE_MUNMAP};
 module_param_array(force_munmap, bool, NULL, 0444);
 MODULE_PARM_DESC(force_munmap,
-                 "\n<0|1[,...]> Force the application to unmap previously "
-                 "\nmapped buffer memory before calling any VIDIOC_S_CROP or "
-                 "\nVIDIOC_S_FMT ioctl's. Not all the applications support "
-                 "\nthis feature. This parameter is specific for each "
+                 "\n<0|1[,...]> Force the application to unmap previously"
+                 "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
+                 "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
+                 "\nthis feature. This parameter is specific for each"
                  "\ndetected camera."
                  "\n 0 = do not force memory unmapping"
                  "\n 1 = force memory unmapping (save memory)"
@@ -102,6 +111,9 @@
 	{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
 };
 
+static sn9c103_sof_header_t sn9c103_sof_header[] = {
+	{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20},
+};
 
 static sn9c102_eof_header_t sn9c102_eof_header[] = {
 	{0x00, 0x00, 0x00, 0x00},
@@ -112,50 +124,6 @@
 
 /*****************************************************************************/
 
-static void* rvmalloc(size_t size)
-{
-	void* mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-
-	mem = vmalloc_32((unsigned long)size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size);
-
-	adr = (unsigned long)mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-
-static void rvfree(void* mem, size_t size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	size = PAGE_ALIGN(size);
-
-	adr = (unsigned long)mem;
-	while (size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	vfree(mem);
-}
-
-
 static u32 
 sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, 
                         enum sn9c102_io_method io)
@@ -174,7 +142,7 @@
 
 	cam->nbuffers = count;
 	while (cam->nbuffers > 0) {
-		if ((buff = rvmalloc(cam->nbuffers * PAGE_ALIGN(imagesize))))
+		if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
 			break;
 		cam->nbuffers--;
 	}
@@ -198,10 +166,10 @@
 static void sn9c102_release_buffers(struct sn9c102_device* cam)
 {
 	if (cam->nbuffers) {
-		rvfree(cam->frame[0].bufmem,
-		       cam->nbuffers * PAGE_ALIGN(cam->frame[0].buf.length));
+		vfree(cam->frame[0].bufmem);
 		cam->nbuffers = 0;
 	}
+	cam->frame_current = NULL;
 }
 
 
@@ -219,6 +187,19 @@
 }
 
 
+static void sn9c102_requeue_outqueue(struct sn9c102_device* cam)
+{
+	struct sn9c102_frame_t *i;
+
+	list_for_each_entry(i, &cam->outqueue, frame) {
+		i->state = F_QUEUED;
+		list_add(&i->frame, &cam->inqueue);
+	}
+
+	INIT_LIST_HEAD(&cam->outqueue);
+}
+
+
 static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
 {
 	unsigned long lock_flags;
@@ -235,19 +216,46 @@
 
 /*****************************************************************************/
 
+int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index)
+{
+	struct usb_device* udev = cam->usbdev;
+	int i, res;
+
+	if (index + sizeof(buff) >= ARRAY_SIZE(cam->reg))
+		return -1;
+
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
+	                      index, 0, buff, sizeof(buff),
+	                      SN9C102_CTRL_TIMEOUT*sizeof(buff));
+	if (res < 0) {
+		DBG(3, "Failed to write registers (index 0x%02X, error %d)",
+		    index, res);
+		return -1;
+	}
+
+	for (i = 0; i < sizeof(buff); i++)
+		cam->reg[index+i] = buff[i];
+
+	return 0;
+}
+
+
 int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
 {
 	struct usb_device* udev = cam->usbdev;
 	u8* buff = cam->control_buffer;
 	int res;
 
+	if (index >= ARRAY_SIZE(cam->reg))
+		return -1;
+
 	*buff = value;
 
 	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
 	                      index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
 	if (res < 0) {
 		DBG(3, "Failed to write a register (value 0x%02X, index "
-		       "0x%02X, error %d)", value, index, res)
+		       "0x%02X, error %d)", value, index, res);
 		return -1;
 	}
 
@@ -268,7 +276,7 @@
 	                      index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
 	if (res < 0)
 		DBG(3, "Failed to read a register (index 0x%02X, error %d)",
-		    index, res)
+		    index, res);
 
 	return (res >= 0) ? (int)(*buff) : -1;
 }
@@ -276,8 +284,8 @@
 
 int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index)
 {
-	if (index > 0x1f)
-		return -EINVAL;
+	if (index >= ARRAY_SIZE(cam->reg))
+		return -1;
 
 	return cam->reg[index];
 }
@@ -367,10 +375,10 @@
 	err += sn9c102_i2c_detect_read_error(cam, sensor);
 
 	PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
-	      data[4])
+	      data[4]);
 
 	if (err) {
-		DBG(3, "I2C read failed for %s image sensor", sensor->name)
+		DBG(3, "I2C read failed for %s image sensor", sensor->name);
 		return -1;
 	}
 
@@ -410,11 +418,11 @@
 	err += sn9c102_i2c_detect_write_error(cam, sensor);
 
 	if (err)
-		DBG(3, "I2C write failed for %s image sensor", sensor->name)
+		DBG(3, "I2C write failed for %s image sensor", sensor->name);
 
 	PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, "
 	      "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X",
-	      n, data0, data1, data2, data3, data4, data5)
+	      n, data0, data1, data2, data3, data4, data5);
 
 	return err ? -1 : 0;
 }
@@ -461,13 +469,27 @@
 static void*
 sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
 {
-	size_t soflen = sizeof(sn9c102_sof_header_t), i;
-	u8 j, n = sizeof(sn9c102_sof_header) / soflen;
+	size_t soflen = 0, i;
+	u8 j, n = 0;
 
-	for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
+	switch (cam->bridge) {
+	case BRIDGE_SN9C101:
+	case BRIDGE_SN9C102:
+		soflen = sizeof(sn9c102_sof_header_t);
+		n = sizeof(sn9c102_sof_header) / soflen;
+		break;
+	case BRIDGE_SN9C103:
+		soflen = sizeof(sn9c103_sof_header_t);
+		n = sizeof(sn9c103_sof_header) / soflen;
+	}
+
+ 	for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
 		for (j = 0; j < n; j++)
-			/* It's enough to compare 7 bytes */
-			if (!memcmp(mem + i, sn9c102_sof_header[j], 7)) {
+			/* The invariable part of the header is 6 bytes long */
+			if ((cam->bridge != BRIDGE_SN9C103 &&
+			    !memcmp(mem + i, sn9c102_sof_header[j], 6)) ||
+			    (cam->bridge == BRIDGE_SN9C103 &&
+			    !memcmp(mem + i, sn9c103_sof_header[j], 6))) {
 				memcpy(cam->sof_header, mem + i, soflen);
 				/* Skip the header */
 				return mem + i + soflen;
@@ -499,8 +521,7 @@
 {
 	struct sn9c102_device* cam = urb->context;
 	struct sn9c102_frame_t** f;
-	size_t imagesize;
-	unsigned long lock_flags;
+	size_t imagesize, soflen;
 	u8 i;
 	int err = 0;
 
@@ -513,7 +534,7 @@
 		cam->stream = STREAM_OFF;
 		if ((*f))
 			(*f)->state = F_QUEUED;
-		DBG(3, "Stream interrupted")
+		DBG(3, "Stream interrupted");
 		wake_up_interruptible(&cam->wait_stream);
 	}
 
@@ -536,6 +557,10 @@
 	             cam->sensor->pix_format.height *
 	             cam->sensor->pix_format.priv) / 8;
 
+	soflen = (cam->bridge) == BRIDGE_SN9C103 ?
+	                          sizeof(sn9c103_sof_header_t) :
+	                          sizeof(sn9c102_sof_header_t);
+
 	for (i = 0; i < urb->number_of_packets; i++) {
 		unsigned int img, len, status;
 		void *pos, *sof, *eof;
@@ -545,19 +570,12 @@
 		pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
 
 		if (status) {
-			DBG(3, "Error in isochronous frame")
+			DBG(3, "Error in isochronous frame");
 			(*f)->state = F_ERROR;
 			continue;
 		}
 
-		PDBGG("Isochrnous frame: length %u, #%u i", len, i)
-
-		/*
-		   NOTE: It is probably correct to assume that SOF and EOF
-		         headers do not occur between two consecutive packets,
-		         but who knows..Whatever is the truth, this assumption
-		         doesn't introduce bugs.
-		*/
+		PDBGG("Isochrnous frame: length %u, #%u i", len, i);
 
 redo:
 		sof = sn9c102_find_sof_header(cam, pos, len);
@@ -575,10 +593,10 @@
 					        imagesize;
 					img = imagesize - (*f)->buf.bytesused;
 					DBG(3, "Expected EOF not found: "
-					       "video frame cut")
+					       "video frame cut");
 					if (eof)
 						DBG(3, "Exceeded limit: +%u "
-						       "bytes", (unsigned)(b))
+						       "bytes", (unsigned)(b));
 				}
 
 				memcpy((*f)->bufmem + (*f)->buf.bytesused, pos,
@@ -595,8 +613,7 @@
 					u32 b = (*f)->buf.bytesused;
 					(*f)->state = F_DONE;
 					(*f)->buf.sequence= ++cam->frame_count;
-					spin_lock_irqsave(&cam->queue_lock,
-					                  lock_flags);
+					spin_lock(&cam->queue_lock);
 					list_move_tail(&(*f)->frame,
 					               &cam->outqueue);
 					if (!list_empty(&cam->inqueue))
@@ -606,13 +623,11 @@
 						        frame );
 					else
 						(*f) = NULL;
-					spin_unlock_irqrestore(&cam->queue_lock
-					                       , lock_flags);
+					spin_unlock(&cam->queue_lock);
 					memcpy(cam->sysfs.frame_header,
-					       cam->sof_header,
-					       sizeof(sn9c102_sof_header_t));
-					DBG(3, "Video frame captured: "
-					       "%lu bytes", (unsigned long)(b))
+					       cam->sof_header, soflen);
+					DBG(3, "Video frame captured: %lu "
+					       "bytes", (unsigned long)(b));
 
 					if (!(*f))
 						goto resubmit_urb;
@@ -621,18 +636,19 @@
 					(*f)->state = F_ERROR;
 					DBG(3, "Not expected EOF after %lu "
 					       "bytes of image data", 
-					  (unsigned long)((*f)->buf.bytesused))
+					    (unsigned long)
+					    ((*f)->buf.bytesused));
 				}
 
 				if (sof) /* (1) */
 					goto start_of_frame;
 
 			} else if (eof) {
-				DBG(3, "EOF without SOF")
+				DBG(3, "EOF without SOF");
 				continue;
 
 			} else {
-				PDBGG("Ignoring pointless isochronous frame")
+				PDBGG("Ignoring pointless isochronous frame");
 				continue;
 			}
 
@@ -642,7 +658,7 @@
 			(*f)->buf.bytesused = 0;
 			len -= (sof - pos);
 			pos = sof;
-			DBG(3, "SOF detected: new video frame")
+			DBG(3, "SOF detected: new video frame");
 			if (len)
 				goto redo;
 
@@ -653,12 +669,13 @@
 			else {
 				if (cam->sensor->pix_format.pixelformat ==
 				    V4L2_PIX_FMT_SN9C10X) {
-					eof = sof-sizeof(sn9c102_sof_header_t);
+					eof = sof - soflen;
 					goto end_of_frame;
 				} else {
 					DBG(3, "SOF before expected EOF after "
 					       "%lu bytes of image data", 
-					  (unsigned long)((*f)->buf.bytesused))
+					    (unsigned long)
+					    ((*f)->buf.bytesused));
 					goto start_of_frame;
 				}
 			}
@@ -670,7 +687,7 @@
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err < 0 && err != -EPERM) {
 		cam->state |= DEV_MISCONFIGURED;
-		DBG(1, "usb_submit_urb() failed")
+		DBG(1, "usb_submit_urb() failed");
 	}
 
 	wake_up_interruptible(&cam->wait_frame);
@@ -681,18 +698,22 @@
 {
 	struct usb_device *udev = cam->usbdev;
 	struct urb* urb;
-	const unsigned int wMaxPacketSize[] = {0, 128, 256, 384, 512,
-	                                       680, 800, 900, 1023};
-	const unsigned int psz = wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
+	const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512,
+	                                               680, 800, 900, 1023};
+	const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512,
+	                                               680, 800, 900, 1003};
+	const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ?
+	                    sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
+	                    sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
 	s8 i, j;
 	int err = 0;
 
 	for (i = 0; i < SN9C102_URBS; i++) {
-		cam->transfer_buffer[i] = kmalloc(SN9C102_ISO_PACKETS * psz,
+		cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
 		                                  GFP_KERNEL);
 		if (!cam->transfer_buffer[i]) {
 			err = -ENOMEM;
-			DBG(1, "Not enough memory")
+			DBG(1, "Not enough memory");
 			goto free_buffers;
 		}
 	}
@@ -702,7 +723,7 @@
 		cam->urb[i] = urb;
 		if (!urb) {
 			err = -ENOMEM;
-			DBG(1, "usb_alloc_urb() failed")
+			DBG(1, "usb_alloc_urb() failed");
 			goto free_urbs;
 		}
 		urb->dev = udev;
@@ -725,14 +746,14 @@
 		err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);
 		if (err) {
 			err = -EIO;
-			DBG(1, "I/O hardware error")
+			DBG(1, "I/O hardware error");
 			goto free_urbs;
 		}
 	}
 
 	err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);
 	if (err) {
-		DBG(1, "usb_set_interface() failed")
+		DBG(1, "usb_set_interface() failed");
 		goto free_urbs;
 	}
 
@@ -743,7 +764,7 @@
 		if (err) {
 			for (j = i-1; j >= 0; j--)
 				usb_kill_urb(cam->urb[j]);
-			DBG(1, "usb_submit_urb() failed, error %d", err)
+			DBG(1, "usb_submit_urb() failed, error %d", err);
 			goto free_urbs;
 		}
 	}
@@ -779,7 +800,7 @@
 
 	err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
 	if (err)
-		DBG(3, "usb_set_interface() failed")
+		DBG(3, "usb_set_interface() failed");
 
 	return err;
 }
@@ -799,7 +820,7 @@
 	else if (err) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "The camera is misconfigured. To use it, close and "
-		       "open /dev/video%d again.", cam->v4ldev->minor)
+		       "open /dev/video%d again.", cam->v4ldev->minor);
 		return err;
 	}
 
@@ -808,6 +829,7 @@
 
 /*****************************************************************************/
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
 static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
 {
 	char str[5];
@@ -885,8 +907,8 @@
 
 	cam->sysfs.reg = index;
 
-	DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg)
-	DBG(3, "Written bytes: %zd", count)
+	DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg);
+	DBG(3, "Written bytes: %zd", count);
 
 	up(&sn9c102_sysfs_lock);
 
@@ -916,7 +938,7 @@
 
 	count = sprintf(buf, "%d\n", val);
 
-	DBG(3, "Read bytes: %zd", count)
+	DBG(3, "Read bytes: %zd", count);
 
 	up(&sn9c102_sysfs_lock);
 
@@ -954,8 +976,8 @@
 	}
 
 	DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X",
-	    cam->sysfs.reg, value)
-	DBG(3, "Written bytes: %zd", count)
+	    cam->sysfs.reg, value);
+	DBG(3, "Written bytes: %zd", count);
 
 	up(&sn9c102_sysfs_lock);
 
@@ -979,7 +1001,7 @@
 
 	count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
 
-	DBG(3, "Read bytes: %zd", count)
+	DBG(3, "Read bytes: %zd", count);
 
 	up(&sn9c102_sysfs_lock);
 
@@ -1011,8 +1033,8 @@
 
 	cam->sysfs.i2c_reg = index;
 
-	DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg)
-	DBG(3, "Written bytes: %zd", count)
+	DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
+	DBG(3, "Written bytes: %zd", count);
 
 	up(&sn9c102_sysfs_lock);
 
@@ -1047,7 +1069,7 @@
 
 	count = sprintf(buf, "%d\n", val);
 
-	DBG(3, "Read bytes: %zd", count)
+	DBG(3, "Read bytes: %zd", count);
 
 	up(&sn9c102_sysfs_lock);
 
@@ -1090,8 +1112,8 @@
 	}
 
 	DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
-	    cam->sysfs.i2c_reg, value)
-	DBG(3, "Written bytes: %zd", count)
+	    cam->sysfs.i2c_reg, value);
+	DBG(3, "Written bytes: %zd", count);
 
 	up(&sn9c102_sysfs_lock);
 
@@ -1193,7 +1215,7 @@
 	count = sizeof(cam->sysfs.frame_header);
 	memcpy(buf, cam->sysfs.frame_header, count);
 
-	DBG(3, "Frame header, read bytes: %zd", count)
+	DBG(3, "Frame header, read bytes: %zd", count);
 
 	return count;
 } 
@@ -1227,11 +1249,12 @@
 		video_device_create_file(v4ldev, &class_device_attr_blue);
 		video_device_create_file(v4ldev, &class_device_attr_red);
 	}
-	if (cam->sensor->sysfs_ops) {
+	if (cam->sensor && cam->sensor->sysfs_ops) {
 		video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
 		video_device_create_file(v4ldev, &class_device_attr_i2c_val);
 	}
 }
+#endif /* CONFIG_VIDEO_ADV_DEBUG */
 
 /*****************************************************************************/
 
@@ -1281,7 +1304,7 @@
 	if (err)
 		return -EIO;
 
-	PDBGG("Scaling factor: %u", scale)
+	PDBGG("Scaling factor: %u", scale);
 
 	return 0;
 }
@@ -1304,7 +1327,7 @@
 		return -EIO;
 
 	PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
-	      "%u %u %u %u", h_start, v_start, h_size, v_size)
+	      "%u %u %u %u", h_start, v_start, h_size, v_size);
 
 	return 0;
 }
@@ -1336,7 +1359,7 @@
 	if (s->init) {
 		err = s->init(cam);
 		if (err) {
-			DBG(3, "Sensor initialization failed")
+			DBG(3, "Sensor initialization failed");
 			return err;
 		}
 	}
@@ -1353,13 +1376,13 @@
 
 	if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
 		DBG(3, "Compressed video format is active, quality %d",
-		    cam->compression.quality)
+		    cam->compression.quality);
 	else
-		DBG(3, "Uncompressed video format is active")
+		DBG(3, "Uncompressed video format is active");
 
 	if (s->set_crop)
 		if ((err = s->set_crop(cam, rect))) {
-			DBG(3, "set_crop() failed")
+			DBG(3, "set_crop() failed");
 			return err;
 		}
 
@@ -1372,11 +1395,11 @@
 				err = s->set_ctrl(cam, &ctrl);
 				if (err) {
 					DBG(3, "Set %s control failed",
-					    s->qctrl[i].name)
+					    s->qctrl[i].name);
 					return err;
 				}
 				DBG(3, "Image sensor supports '%s' control",
-				    s->qctrl[i].name)
+				    s->qctrl[i].name);
 			}
 	}
 
@@ -1392,7 +1415,7 @@
 		cam->state |= DEV_INITIALIZED;
 	}
 
-	DBG(2, "Initialization succeeded")
+	DBG(2, "Initialization succeeded");
 	return 0;
 }
 
@@ -1401,7 +1424,7 @@
 {
 	down(&sn9c102_sysfs_lock);
 
-	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor)
+	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
 	video_set_drvdata(cam->v4ldev, NULL);
 	video_unregister_device(cam->v4ldev);
 
@@ -1432,7 +1455,7 @@
 	}
 
 	if (cam->users) {
-		DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor)
+		DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
 		if ((filp->f_flags & O_NONBLOCK) ||
 		    (filp->f_flags & O_NDELAY)) {
 			err = -EWOULDBLOCK;
@@ -1458,7 +1481,7 @@
 		err = sn9c102_init(cam);
 		if (err) {
 			DBG(1, "Initialization failed again. "
-			       "I will retry on next open().")
+			       "I will retry on next open().");
 			goto out;
 		}
 		cam->state &= ~DEV_MISCONFIGURED;
@@ -1475,7 +1498,7 @@
 	cam->frame_count = 0;
 	sn9c102_empty_framequeues(cam);
 
-	DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor)
+	DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
 
 out:
 	up(&cam->dev_sem);
@@ -1504,7 +1527,7 @@
 	cam->users--;
 	wake_up_interruptible_nr(&cam->open, 1);
 
-	DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor)
+	DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
 
 	up(&cam->dev_sem);
 
@@ -1524,32 +1547,38 @@
 		return -ERESTARTSYS;
 
 	if (cam->state & DEV_DISCONNECTED) {
-		DBG(1, "Device not present")
+		DBG(1, "Device not present");
 		up(&cam->fileop_sem);
 		return -ENODEV;
 	}
 
 	if (cam->state & DEV_MISCONFIGURED) {
-		DBG(1, "The camera is misconfigured. Close and open it again.")
+		DBG(1, "The camera is misconfigured. Close and open it "
+		       "again.");
 		up(&cam->fileop_sem);
 		return -EIO;
 	}
 
 	if (cam->io == IO_MMAP) {
 		DBG(3, "Close and open the device again to choose "
-		       "the read method")
+		       "the read method");
 		up(&cam->fileop_sem);
 		return -EINVAL;
 	}
 
 	if (cam->io == IO_NONE) {
 		if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) {
-			DBG(1, "read() failed, not enough memory")
+			DBG(1, "read() failed, not enough memory");
 			up(&cam->fileop_sem);
 			return -ENOMEM;
 		}
 		cam->io = IO_READ;
 		cam->stream = STREAM_ON;
+	}
+
+	if (list_empty(&cam->inqueue)) {
+		if (!list_empty(&cam->outqueue))
+			sn9c102_empty_framequeues(cam);
 		sn9c102_queue_unusedframes(cam);
 	}
 
@@ -1584,6 +1613,16 @@
 
 	f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
 
+	if (count > f->buf.bytesused)
+		count = f->buf.bytesused;
+
+	if (copy_to_user(buf, f->bufmem, count)) {
+		err = -EFAULT;
+		goto exit;
+	}
+	*f_pos += count;
+
+exit:
 	spin_lock_irqsave(&cam->queue_lock, lock_flags);
 	list_for_each_entry(i, &cam->outqueue, frame)
 		i->state = F_UNUSED;
@@ -1592,16 +1631,8 @@
 
 	sn9c102_queue_unusedframes(cam);
 
-	if (count > f->buf.bytesused)
-		count = f->buf.bytesused;
-
-	if (copy_to_user(buf, f->bufmem, count)) {
-		up(&cam->fileop_sem);
-		return -EFAULT;
-	}
-	*f_pos += count;
-
-	PDBGG("Frame #%lu, bytes read: %zu", (unsigned long)f->buf.index,count)
+	PDBGG("Frame #%lu, bytes read: %zu",
+	      (unsigned long)f->buf.index, count);
 
 	up(&cam->fileop_sem);
 
@@ -1612,33 +1643,42 @@
 static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
 {
 	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+	struct sn9c102_frame_t* f;
+	unsigned long lock_flags;
 	unsigned int mask = 0;
 
 	if (down_interruptible(&cam->fileop_sem))
 		return POLLERR;
 
 	if (cam->state & DEV_DISCONNECTED) {
-		DBG(1, "Device not present")
+		DBG(1, "Device not present");
 		goto error;
 	}
 
 	if (cam->state & DEV_MISCONFIGURED) {
-		DBG(1, "The camera is misconfigured. Close and open it again.")
+		DBG(1, "The camera is misconfigured. Close and open it "
+		       "again.");
 		goto error;
 	}
 
 	if (cam->io == IO_NONE) {
 		if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
 		                             IO_READ)) {
-			DBG(1, "poll() failed, not enough memory")
+			DBG(1, "poll() failed, not enough memory");
 			goto error;
 		}
 		cam->io = IO_READ;
 		cam->stream = STREAM_ON;
 	}
 
-	if (cam->io == IO_READ)
+	if (cam->io == IO_READ) {
+		spin_lock_irqsave(&cam->queue_lock, lock_flags);
+		list_for_each_entry(f, &cam->outqueue, frame)
+			f->state = F_UNUSED;
+		INIT_LIST_HEAD(&cam->outqueue);
+		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
 		sn9c102_queue_unusedframes(cam);
+	}
 
 	poll_wait(filp, &cam->wait_frame, wait);
 
@@ -1680,22 +1720,22 @@
 {
 	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
 	unsigned long size = vma->vm_end - vma->vm_start,
-	              start = vma->vm_start,
-	              pos,
-	              page;
+	              start = vma->vm_start;
+	void *pos;
 	u32 i;
 
 	if (down_interruptible(&cam->fileop_sem))
 		return -ERESTARTSYS;
 
 	if (cam->state & DEV_DISCONNECTED) {
-		DBG(1, "Device not present")
+		DBG(1, "Device not present");
 		up(&cam->fileop_sem);
 		return -ENODEV;
 	}
 
 	if (cam->state & DEV_MISCONFIGURED) {
-		DBG(1, "The camera is misconfigured. Close and open it again.")
+		DBG(1, "The camera is misconfigured. Close and open it "
+		       "again.");
 		up(&cam->fileop_sem);
 		return -EIO;
 	}
@@ -1715,15 +1755,12 @@
 		return -EINVAL;
 	}
 
-	/* VM_IO is eventually going to replace PageReserved altogether */
 	vma->vm_flags |= VM_IO;
-	vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
+	vma->vm_flags |= VM_RESERVED;
 
-	pos = (unsigned long)cam->frame[i].bufmem;
+	pos = cam->frame[i].bufmem;
 	while (size > 0) { /* size is page-aligned */
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE,
-		                    vma->vm_page_prot)) {
+		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
 			up(&cam->fileop_sem);
 			return -EAGAIN;
 		}
@@ -1742,6 +1779,783 @@
 	return 0;
 }
 
+/*****************************************************************************/
+
+static int
+sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_capability cap = {
+		.driver = "sn9c102",
+		.version = SN9C102_MODULE_VERSION_CODE,
+		.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+		                V4L2_CAP_STREAMING,
+	};
+
+	strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
+	if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
+		strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
+		        sizeof(cap.bus_info));
+
+	if (copy_to_user(arg, &cap, sizeof(cap)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_input i;
+
+	if (copy_from_user(&i, arg, sizeof(i)))
+		return -EFAULT;
+
+	if (i.index)
+		return -EINVAL;
+
+	memset(&i, 0, sizeof(i));
+	strcpy(i.name, "Camera");
+
+	if (copy_to_user(arg, &i, sizeof(i)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg)
+{
+	int index;
+
+	if (copy_from_user(&index, arg, sizeof(index)))
+		return -EFAULT;
+
+	if (index != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
+{
+	struct sn9c102_sensor* s = cam->sensor;
+	struct v4l2_queryctrl qc;
+	u8 i;
+
+	if (copy_from_user(&qc, arg, sizeof(qc)))
+		return -EFAULT;
+
+	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+		if (qc.id && qc.id == s->qctrl[i].id) {
+			memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
+			if (copy_to_user(arg, &qc, sizeof(qc)))
+				return -EFAULT;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+
+static int
+sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg)
+{
+	struct sn9c102_sensor* s = cam->sensor;
+	struct v4l2_control ctrl;
+	int err = 0;
+	u8 i;
+
+	if (!s->get_ctrl && !s->set_ctrl)
+		return -EINVAL;
+
+	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+		return -EFAULT;
+
+	if (!s->get_ctrl) {
+		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+			if (ctrl.id && ctrl.id == s->qctrl[i].id) {
+				ctrl.value = s->_qctrl[i].default_value;
+				goto exit;
+			}
+		return -EINVAL;
+	} else
+		err = s->get_ctrl(cam, &ctrl);
+
+exit:
+	if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
+		return -EFAULT;
+
+	return err;
+}
+
+
+static int
+sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
+{
+	struct sn9c102_sensor* s = cam->sensor;
+	struct v4l2_control ctrl;
+	u8 i;
+	int err = 0;
+
+	if (!s->set_ctrl)
+		return -EINVAL;
+
+	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+		return -EFAULT;
+
+	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+		if (ctrl.id == s->qctrl[i].id) {
+			if (ctrl.value < s->qctrl[i].minimum ||
+			    ctrl.value > s->qctrl[i].maximum)
+				return -ERANGE;
+			ctrl.value -= ctrl.value % s->qctrl[i].step;
+			break;
+		}
+
+	if ((err = s->set_ctrl(cam, &ctrl)))
+		return err;
+
+	s->_qctrl[i].default_value = ctrl.value;
+
+	PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
+	      (unsigned long)ctrl.id, (unsigned long)ctrl.value);
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
+
+	cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	cc->pixelaspect.numerator = 1;
+	cc->pixelaspect.denominator = 1;
+
+	if (copy_to_user(arg, cc, sizeof(*cc)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
+{
+	struct sn9c102_sensor* s = cam->sensor;
+	struct v4l2_crop crop = {
+		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+	};
+
+	memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
+
+	if (copy_to_user(arg, &crop, sizeof(crop)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
+{
+	struct sn9c102_sensor* s = cam->sensor;
+	struct v4l2_crop crop;
+	struct v4l2_rect* rect;
+	struct v4l2_rect* bounds = &(s->cropcap.bounds);
+	struct v4l2_pix_format* pix_format = &(s->pix_format);
+	u8 scale;
+	const enum sn9c102_stream_state stream = cam->stream;
+	const u32 nbuffers = cam->nbuffers;
+	u32 i;
+	int err = 0;
+
+	if (copy_from_user(&crop, arg, sizeof(crop)))
+		return -EFAULT;
+
+	rect = &(crop.c);
+
+	if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (cam->module_param.force_munmap)
+		for (i = 0; i < cam->nbuffers; i++)
+			if (cam->frame[i].vma_use_count) {
+				DBG(3, "VIDIOC_S_CROP failed. "
+				       "Unmap the buffers first.");
+				return -EINVAL;
+			}
+
+	/* Preserve R,G or B origin */
+	rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
+	rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
+
+	if (rect->width < 16)
+		rect->width = 16;
+	if (rect->height < 16)
+		rect->height = 16;
+	if (rect->width > bounds->width)
+		rect->width = bounds->width;
+	if (rect->height > bounds->height)
+		rect->height = bounds->height;
+	if (rect->left < bounds->left)
+		rect->left = bounds->left;
+	if (rect->top < bounds->top)
+		rect->top = bounds->top;
+	if (rect->left + rect->width > bounds->left + bounds->width)
+		rect->left = bounds->left+bounds->width - rect->width;
+	if (rect->top + rect->height > bounds->top + bounds->height)
+		rect->top = bounds->top+bounds->height - rect->height;
+
+	rect->width &= ~15L;
+	rect->height &= ~15L;
+
+	if (SN9C102_PRESERVE_IMGSCALE) {
+		/* Calculate the actual scaling factor */
+		u32 a, b;
+		a = rect->width * rect->height;
+		b = pix_format->width * pix_format->height;
+		scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
+	} else
+		scale = 1;
+
+	if (cam->stream == STREAM_ON)
+		if ((err = sn9c102_stream_interrupt(cam)))
+			return err;
+
+	if (copy_to_user(arg, &crop, sizeof(crop))) {
+		cam->stream = stream;
+		return -EFAULT;
+	}
+
+	if (cam->module_param.force_munmap || cam->io == IO_READ)
+		sn9c102_release_buffers(cam);
+
+	err = sn9c102_set_crop(cam, rect);
+	if (s->set_crop)
+		err += s->set_crop(cam, rect);
+	err += sn9c102_set_scale(cam, scale);
+
+	if (err) { /* atomic, no rollback in ioctl() */
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
+		       "use the camera, close and open /dev/video%d again.",
+		    cam->v4ldev->minor);
+		return -EIO;
+	}
+
+	s->pix_format.width = rect->width/scale;
+	s->pix_format.height = rect->height/scale;
+	memcpy(&(s->_rect), rect, sizeof(*rect));
+
+	if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
+	    nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
+		       "use the camera, close and open /dev/video%d again.",
+		    cam->v4ldev->minor);
+		return -ENOMEM;
+	}
+
+	if (cam->io == IO_READ)
+		sn9c102_empty_framequeues(cam);
+	else if (cam->module_param.force_munmap)
+		sn9c102_requeue_outqueue(cam);
+
+	cam->stream = stream;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_fmtdesc fmtd;
+
+	if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
+		return -EFAULT;
+
+	if (fmtd.index == 0) {
+		strcpy(fmtd.description, "bayer rgb");
+		fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
+	} else if (fmtd.index == 1) {
+		strcpy(fmtd.description, "compressed");
+		fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
+		fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
+	} else
+		return -EINVAL;
+
+	fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
+
+	if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_format format;
+	struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
+
+	if (copy_from_user(&format, arg, sizeof(format)))
+		return -EFAULT;
+
+	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)
+	                     ? 0 : (pfmt->width * pfmt->priv) / 8;
+	pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
+	pfmt->field = V4L2_FIELD_NONE;
+	memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
+
+	if (copy_to_user(arg, &format, sizeof(format)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
+                         void __user * arg)
+{
+	struct sn9c102_sensor* s = cam->sensor;
+	struct v4l2_format format;
+	struct v4l2_pix_format* pix;
+	struct v4l2_pix_format* pfmt = &(s->pix_format);
+	struct v4l2_rect* bounds = &(s->cropcap.bounds);
+	struct v4l2_rect rect;
+	u8 scale;
+	const enum sn9c102_stream_state stream = cam->stream;
+	const u32 nbuffers = cam->nbuffers;
+	u32 i;
+	int err = 0;
+
+	if (copy_from_user(&format, arg, sizeof(format)))
+		return -EFAULT;
+
+	pix = &(format.fmt.pix);
+
+	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	memcpy(&rect, &(s->_rect), sizeof(rect));
+
+	{ /* calculate the actual scaling factor */
+		u32 a, b;
+		a = rect.width * rect.height;
+		b = pix->width * pix->height;
+		scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
+	}
+
+	rect.width = scale * pix->width;
+	rect.height = scale * pix->height;
+
+	if (rect.width < 16)
+		rect.width = 16;
+	if (rect.height < 16)
+		rect.height = 16;
+	if (rect.width > bounds->left + bounds->width - rect.left)
+		rect.width = bounds->left + bounds->width - rect.left;
+	if (rect.height > bounds->top + bounds->height - rect.top)
+		rect.height = bounds->top + bounds->height - rect.top;
+
+	rect.width &= ~15L;
+	rect.height &= ~15L;
+
+	{ /* adjust the scaling factor */
+		u32 a, b;
+		a = rect.width * rect.height;
+		b = pix->width * pix->height;
+		scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
+	}
+
+	pix->width = rect.width / scale;
+	pix->height = rect.height / scale;
+
+	if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
+	    pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+		pix->pixelformat = pfmt->pixelformat;
+	pix->priv = pfmt->priv; /* bpp */
+	pix->colorspace = pfmt->colorspace;
+	pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+	                    ? 0 : (pix->width * pix->priv) / 8;
+	pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
+	pix->field = V4L2_FIELD_NONE;
+
+	if (cmd == VIDIOC_TRY_FMT) {
+		if (copy_to_user(arg, &format, sizeof(format)))
+			return -EFAULT;
+		return 0;
+	}
+
+	if (cam->module_param.force_munmap)
+		for (i = 0; i < cam->nbuffers; i++)
+			if (cam->frame[i].vma_use_count) {
+				DBG(3, "VIDIOC_S_FMT failed. Unmap the "
+				       "buffers first.");
+				return -EINVAL;
+			}
+
+	if (cam->stream == STREAM_ON)
+		if ((err = sn9c102_stream_interrupt(cam)))
+			return err;
+
+	if (copy_to_user(arg, &format, sizeof(format))) {
+		cam->stream = stream;
+		return -EFAULT;
+	}
+
+	if (cam->module_param.force_munmap  || cam->io == IO_READ)
+		sn9c102_release_buffers(cam);
+
+	err += sn9c102_set_pix_format(cam, pix);
+	err += sn9c102_set_crop(cam, &rect);
+	if (s->set_pix_format)
+		err += s->set_pix_format(cam, pix);
+	if (s->set_crop)
+		err += s->set_crop(cam, &rect);
+	err += sn9c102_set_scale(cam, scale);
+
+	if (err) { /* atomic, no rollback in ioctl() */
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
+		       "use the camera, close and open /dev/video%d again.",
+		    cam->v4ldev->minor);
+		return -EIO;
+	}
+
+	memcpy(pfmt, pix, sizeof(*pix));
+	memcpy(&(s->_rect), &rect, sizeof(rect));
+
+	if ((cam->module_param.force_munmap  || cam->io == IO_READ) &&
+	    nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
+		       "use the camera, close and open /dev/video%d again.",
+		    cam->v4ldev->minor);
+		return -ENOMEM;
+	}
+
+	if (cam->io == IO_READ)
+		sn9c102_empty_framequeues(cam);
+	else if (cam->module_param.force_munmap)
+		sn9c102_requeue_outqueue(cam);
+
+	cam->stream = stream;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
+{
+	if (copy_to_user(arg, &cam->compression,
+	                 sizeof(cam->compression)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_jpegcompression jc;
+	const enum sn9c102_stream_state stream = cam->stream;
+	int err = 0;
+
+	if (copy_from_user(&jc, arg, sizeof(jc)))
+		return -EFAULT;
+
+	if (jc.quality != 0 && jc.quality != 1)
+		return -EINVAL;
+
+	if (cam->stream == STREAM_ON)
+		if ((err = sn9c102_stream_interrupt(cam)))
+			return err;
+
+	err += sn9c102_set_compression(cam, &jc);
+	if (err) { /* atomic, no rollback in ioctl() */
+		cam->state |= DEV_MISCONFIGURED;
+		DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
+		       "problems. To use the camera, close and open "
+		       "/dev/video%d again.", cam->v4ldev->minor);
+		return -EIO;
+	}
+
+	cam->compression.quality = jc.quality;
+
+	cam->stream = stream;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_requestbuffers rb;
+	u32 i;
+	int err;
+
+	if (copy_from_user(&rb, arg, sizeof(rb)))
+		return -EFAULT;
+
+	if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    rb.memory != V4L2_MEMORY_MMAP)
+		return -EINVAL;
+
+	if (cam->io == IO_READ) {
+		DBG(3, "Close and open the device again to choose the mmap "
+		       "I/O method");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < cam->nbuffers; i++)
+		if (cam->frame[i].vma_use_count) {
+			DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
+			       "still mapped.");
+			return -EINVAL;
+		}
+
+	if (cam->stream == STREAM_ON)
+		if ((err = sn9c102_stream_interrupt(cam)))
+			return err;
+
+	sn9c102_empty_framequeues(cam);
+
+	sn9c102_release_buffers(cam);
+	if (rb.count)
+		rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
+
+	if (copy_to_user(arg, &rb, sizeof(rb))) {
+		sn9c102_release_buffers(cam);
+		cam->io = IO_NONE;
+		return -EFAULT;
+	}
+
+	cam->io = rb.count ? IO_MMAP : IO_NONE;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_buffer b;
+
+	if (copy_from_user(&b, arg, sizeof(b)))
+		return -EFAULT;
+
+	if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    b.index >= cam->nbuffers || cam->io != IO_MMAP)
+		return -EINVAL;
+
+	memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
+
+	if (cam->frame[b.index].vma_use_count)
+		b.flags |= V4L2_BUF_FLAG_MAPPED;
+
+	if (cam->frame[b.index].state == F_DONE)
+		b.flags |= V4L2_BUF_FLAG_DONE;
+	else if (cam->frame[b.index].state != F_UNUSED)
+		b.flags |= V4L2_BUF_FLAG_QUEUED;
+
+	if (copy_to_user(arg, &b, sizeof(b)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_buffer b;
+	unsigned long lock_flags;
+
+	if (copy_from_user(&b, arg, sizeof(b)))
+		return -EFAULT;
+
+	if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    b.index >= cam->nbuffers || cam->io != IO_MMAP)
+		return -EINVAL;
+
+	if (cam->frame[b.index].state != F_UNUSED)
+		return -EINVAL;
+
+	cam->frame[b.index].state = F_QUEUED;
+
+	spin_lock_irqsave(&cam->queue_lock, lock_flags);
+	list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
+	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+	PDBGG("Frame #%lu queued", (unsigned long)b.index);
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
+                     void __user * arg)
+{
+	struct v4l2_buffer b;
+	struct sn9c102_frame_t *f;
+	unsigned long lock_flags;
+	int err = 0;
+
+	if (copy_from_user(&b, arg, sizeof(b)))
+		return -EFAULT;
+
+	if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+		return -EINVAL;
+
+	if (list_empty(&cam->outqueue)) {
+		if (cam->stream == STREAM_OFF)
+			return -EINVAL;
+		if (filp->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		err = wait_event_interruptible
+		      ( cam->wait_frame,
+		        (!list_empty(&cam->outqueue)) ||
+		        (cam->state & DEV_DISCONNECTED) ||
+		        (cam->state & DEV_MISCONFIGURED) );
+		if (err)
+			return err;
+		if (cam->state & DEV_DISCONNECTED)
+			return -ENODEV;
+		if (cam->state & DEV_MISCONFIGURED)
+			return -EIO;
+	}
+
+	spin_lock_irqsave(&cam->queue_lock, lock_flags);
+	f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame);
+	list_del(cam->outqueue.next);
+	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+	f->state = F_UNUSED;
+
+	memcpy(&b, &f->buf, sizeof(b));
+	if (f->vma_use_count)
+		b.flags |= V4L2_BUF_FLAG_MAPPED;
+
+	if (copy_to_user(arg, &b, sizeof(b)))
+		return -EFAULT;
+
+	PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
+{
+	int type;
+
+	if (copy_from_user(&type, arg, sizeof(type)))
+		return -EFAULT;
+
+	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+		return -EINVAL;
+
+	if (list_empty(&cam->inqueue))
+		return -EINVAL;
+
+	cam->stream = STREAM_ON;
+
+	DBG(3, "Stream on");
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg)
+{
+	int type, err;
+
+	if (copy_from_user(&type, arg, sizeof(type)))
+		return -EFAULT;
+
+	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+		return -EINVAL;
+
+	if (cam->stream == STREAM_ON)
+		if ((err = sn9c102_stream_interrupt(cam)))
+			return err;
+
+	sn9c102_empty_framequeues(cam);
+
+	DBG(3, "Stream off");
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_streamparm sp;
+
+	if (copy_from_user(&sp, arg, sizeof(sp)))
+		return -EFAULT;
+
+	if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	sp.parm.capture.extendedmode = 0;
+	sp.parm.capture.readbuffers = cam->nreadbuffers;
+
+	if (copy_to_user(arg, &sp, sizeof(sp)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_streamparm sp;
+
+	if (copy_from_user(&sp, arg, sizeof(sp)))
+		return -EFAULT;
+
+	if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	sp.parm.capture.extendedmode = 0;
+
+	if (sp.parm.capture.readbuffers == 0)
+		sp.parm.capture.readbuffers = cam->nreadbuffers;
+
+	if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
+		sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
+
+	if (copy_to_user(arg, &sp, sizeof(sp)))
+		return -EFAULT;
+
+	cam->nreadbuffers = sp.parm.capture.readbuffers;
+
+	return 0;
+}
+
 
 static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
                               unsigned int cmd, void __user * arg)
@@ -1751,729 +2565,75 @@
 	switch (cmd) {
 
 	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability cap = {
-			.driver = "sn9c102",
-			.version = SN9C102_MODULE_VERSION_CODE,
-			.capabilities = V4L2_CAP_VIDEO_CAPTURE | 
-			                V4L2_CAP_READWRITE |
-			                V4L2_CAP_STREAMING,
-		};
-
-		strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
-		if (usb_make_path(cam->usbdev, cap.bus_info,
-		    sizeof(cap.bus_info)) < 0)
-			strlcpy(cap.bus_info, cam->dev.bus_id,
-			        sizeof(cap.bus_info));
-
-		if (copy_to_user(arg, &cap, sizeof(cap)))
-			return -EFAULT;
-
-		return 0;
-	}
+		return sn9c102_vidioc_querycap(cam, arg);
 
 	case VIDIOC_ENUMINPUT:
-	{
-		struct v4l2_input i;
-
-		if (copy_from_user(&i, arg, sizeof(i)))
-			return -EFAULT;
-
-		if (i.index)
-			return -EINVAL;
-
-		memset(&i, 0, sizeof(i));
-		strcpy(i.name, "USB");
-
-		if (copy_to_user(arg, &i, sizeof(i)))
-			return -EFAULT;
-
-		return 0;
-	}
+		return sn9c102_vidioc_enuminput(cam, arg);
 
 	case VIDIOC_G_INPUT:
 	case VIDIOC_S_INPUT:
-	{
-		int index;
-
-		if (copy_from_user(&index, arg, sizeof(index)))
-			return -EFAULT;
-
-		if (index != 0)
-			return -EINVAL;
-
-		return 0;
-	}
+		return sn9c102_vidioc_gs_input(cam, arg);
 
 	case VIDIOC_QUERYCTRL:
-	{
-		struct sn9c102_sensor* s = cam->sensor;
-		struct v4l2_queryctrl qc;
-		u8 i;
-
-		if (copy_from_user(&qc, arg, sizeof(qc)))
-			return -EFAULT;
-
-		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
-			if (qc.id && qc.id == s->qctrl[i].id) {
-				memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
-				if (copy_to_user(arg, &qc, sizeof(qc)))
-					return -EFAULT;
-				return 0;
-			}
-
-		return -EINVAL;
-	}
+		return sn9c102_vidioc_query_ctrl(cam, arg);
 
 	case VIDIOC_G_CTRL:
-	{
-		struct sn9c102_sensor* s = cam->sensor;
-		struct v4l2_control ctrl;
-		int err = 0;
-
-		if (!s->get_ctrl)
-			return -EINVAL;
-
-		if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
-			return -EFAULT;
-
-		err = s->get_ctrl(cam, &ctrl);
-
-		if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
-			return -EFAULT;
-
-		return err;
-	}
+		return sn9c102_vidioc_g_ctrl(cam, arg);
 
 	case VIDIOC_S_CTRL_OLD:
 	case VIDIOC_S_CTRL:
-	{
-		struct sn9c102_sensor* s = cam->sensor;
-		struct v4l2_control ctrl;
-		u8 i;
-		int err = 0;
+		return sn9c102_vidioc_s_ctrl(cam, arg);
 
-		if (!s->set_ctrl)
-			return -EINVAL;
-
-		if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
-			return -EFAULT;
-
-		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
-			if (ctrl.id == s->qctrl[i].id) {
-				if (ctrl.value < s->qctrl[i].minimum ||
-				    ctrl.value > s->qctrl[i].maximum)
-					return -ERANGE;
-				ctrl.value -= ctrl.value % s->qctrl[i].step;
-				break;
-			}
-
-		if ((err = s->set_ctrl(cam, &ctrl)))
-			return err;
-
-		s->_qctrl[i].default_value = ctrl.value;
-
-		PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
-		      (unsigned long)ctrl.id, (unsigned long)ctrl.value)
-
-		return 0;
-	}
-
+	case VIDIOC_CROPCAP_OLD:
 	case VIDIOC_CROPCAP:
-	{
-		struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
-
-		cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		cc->pixelaspect.numerator = 1;
-		cc->pixelaspect.denominator = 1;
-
-		if (copy_to_user(arg, cc, sizeof(*cc)))
-			return -EFAULT;
-
-		return 0;
-	}
+		return sn9c102_vidioc_cropcap(cam, arg);
 
 	case VIDIOC_G_CROP:
-	{
-		struct sn9c102_sensor* s = cam->sensor;
-		struct v4l2_crop crop = {
-			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-		};
-
-		memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
-
-		if (copy_to_user(arg, &crop, sizeof(crop)))
-			return -EFAULT;
-
-		return 0;
-	}
+		return sn9c102_vidioc_g_crop(cam, arg);
 
 	case VIDIOC_S_CROP:
-	{
-		struct sn9c102_sensor* s = cam->sensor;
-		struct v4l2_crop crop;
-		struct v4l2_rect* rect;
-		struct v4l2_rect* bounds = &(s->cropcap.bounds);
-		struct v4l2_pix_format* pix_format = &(s->pix_format);
-		u8 scale;
-		const enum sn9c102_stream_state stream = cam->stream;
-		const u32 nbuffers = cam->nbuffers;
-		u32 i;
-		int err = 0;
-
-		if (copy_from_user(&crop, arg, sizeof(crop)))
-			return -EFAULT;
-
-		rect = &(crop.c);
-
-		if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			return -EINVAL;
-
-		if (cam->module_param.force_munmap)
-			for (i = 0; i < cam->nbuffers; i++)
-				if (cam->frame[i].vma_use_count) {
-					DBG(3, "VIDIOC_S_CROP failed. "
-					       "Unmap the buffers first.")
-					return -EINVAL;
-				}
-
-		/* Preserve R,G or B origin */
-		rect->left = (s->_rect.left & 1L) ?
-		             rect->left | 1L : rect->left & ~1L;
-		rect->top = (s->_rect.top & 1L) ?
-		            rect->top | 1L : rect->top & ~1L;
-
-		if (rect->width < 16)
-			rect->width = 16;
-		if (rect->height < 16)
-			rect->height = 16;
-		if (rect->width > bounds->width)
-			rect->width = bounds->width;
-		if (rect->height > bounds->height)
-			rect->height = bounds->height;
-		if (rect->left < bounds->left)
-			rect->left = bounds->left;
-		if (rect->top < bounds->top)
-			rect->top = bounds->top;
-		if (rect->left + rect->width > bounds->left + bounds->width)
-			rect->left = bounds->left+bounds->width - rect->width;
-		if (rect->top + rect->height > bounds->top + bounds->height)
-			rect->top = bounds->top+bounds->height - rect->height;
-
-		rect->width &= ~15L;
-		rect->height &= ~15L;
-
-		if (SN9C102_PRESERVE_IMGSCALE) {
-			/* Calculate the actual scaling factor */
-			u32 a, b;
-			a = rect->width * rect->height;
-			b = pix_format->width * pix_format->height;
-			scale = b ? (u8)((a / b) < 4 ? 1 :
-		                        ((a / b) < 16 ? 2 : 4)) : 1;
-		} else
-			scale = 1;
-
-		if (cam->stream == STREAM_ON)
-			if ((err = sn9c102_stream_interrupt(cam)))
-				return err;
-
-		if (copy_to_user(arg, &crop, sizeof(crop))) {
-			cam->stream = stream;
-			return -EFAULT;
-		}
-
-		if (cam->module_param.force_munmap || cam->io == IO_READ)
-			sn9c102_release_buffers(cam);
-
-		err = sn9c102_set_crop(cam, rect);
-		if (s->set_crop)
-			err += s->set_crop(cam, rect);
-		err += sn9c102_set_scale(cam, scale);
-
-		if (err) { /* atomic, no rollback in ioctl() */
-			cam->state |= DEV_MISCONFIGURED;
-			DBG(1, "VIDIOC_S_CROP failed because of hardware "
-			       "problems. To use the camera, close and open "
-			       "/dev/video%d again.", cam->v4ldev->minor)
-			return -EIO;
-		}
-
-		s->pix_format.width = rect->width/scale;
-		s->pix_format.height = rect->height/scale;
-		memcpy(&(s->_rect), rect, sizeof(*rect));
-
-		if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
-		    nbuffers != sn9c102_request_buffers(cam, nbuffers,
-		                                        cam->io)) {
-			cam->state |= DEV_MISCONFIGURED;
-			DBG(1, "VIDIOC_S_CROP failed because of not enough "
-			       "memory. To use the camera, close and open "
-			       "/dev/video%d again.", cam->v4ldev->minor)
-			return -ENOMEM;
-		}
-
-		cam->stream = stream;
-
-		return 0;
-	}
+		return sn9c102_vidioc_s_crop(cam, arg);
 
 	case VIDIOC_ENUM_FMT:
-	{
-		struct v4l2_fmtdesc fmtd;
-
-		if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
-			return -EFAULT;
-
-		if (fmtd.index == 0) {
-			strcpy(fmtd.description, "bayer rgb");
-			fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
-		} else if (fmtd.index == 1) {
-			strcpy(fmtd.description, "compressed");
-			fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
-			fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
-		} else
-			return -EINVAL;
-
-		fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
-
-		if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
-			return -EFAULT;
-
-		return 0;
-	}
+		return sn9c102_vidioc_enum_fmt(cam, arg);
 
 	case VIDIOC_G_FMT:
-	{
-		struct v4l2_format format;
-		struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
-
-		if (copy_from_user(&format, arg, sizeof(format)))
-			return -EFAULT;
-
-		if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			return -EINVAL;
-
-		pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)
-		                     ? 0 : (pfmt->width * pfmt->priv) / 8;
-		pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
-		pfmt->field = V4L2_FIELD_NONE;
-		memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
-
-		if (copy_to_user(arg, &format, sizeof(format)))
-			return -EFAULT;
-
-		return 0;
-	}
+		return sn9c102_vidioc_g_fmt(cam, arg);
 
 	case VIDIOC_TRY_FMT:
 	case VIDIOC_S_FMT:
-	{
-		struct sn9c102_sensor* s = cam->sensor;
-		struct v4l2_format format;
-		struct v4l2_pix_format* pix;
-		struct v4l2_pix_format* pfmt = &(s->pix_format);
-		struct v4l2_rect* bounds = &(s->cropcap.bounds);
-		struct v4l2_rect rect;
-		u8 scale;
-		const enum sn9c102_stream_state stream = cam->stream;
-		const u32 nbuffers = cam->nbuffers;
-		u32 i;
-		int err = 0;
-
-		if (copy_from_user(&format, arg, sizeof(format)))
-			return -EFAULT;
-
-		pix = &(format.fmt.pix);
-
-		if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			return -EINVAL;
-
-		memcpy(&rect, &(s->_rect), sizeof(rect));
-
-		{ /* calculate the actual scaling factor */
-			u32 a, b;
-			a = rect.width * rect.height;
-			b = pix->width * pix->height;
-			scale = b ? (u8)((a / b) < 4 ? 1 :
-		                        ((a / b) < 16 ? 2 : 4)) : 1;
-		}
-
-		rect.width = scale * pix->width;
-		rect.height = scale * pix->height;
-
-		if (rect.width < 16)
-			rect.width = 16;
-		if (rect.height < 16)
-			rect.height = 16;
-		if (rect.width > bounds->left + bounds->width - rect.left)
-			rect.width = bounds->left + bounds->width - rect.left;
-		if (rect.height > bounds->top + bounds->height - rect.top)
-			rect.height = bounds->top + bounds->height - rect.top;
-
-		rect.width &= ~15L;
-		rect.height &= ~15L;
-
-		{ /* adjust the scaling factor */
-			u32 a, b;
-			a = rect.width * rect.height;
-			b = pix->width * pix->height;
-			scale = b ? (u8)((a / b) < 4 ? 1 :
-		                        ((a / b) < 16 ? 2 : 4)) : 1;
-		}
-
-		pix->width = rect.width / scale;
-		pix->height = rect.height / scale;
-
-		if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
-		    pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
-			pix->pixelformat = pfmt->pixelformat;
-		pix->priv = pfmt->priv; /* bpp */
-		pix->colorspace = pfmt->colorspace;
-		pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		                    ? 0 : (pix->width * pix->priv) / 8;
-		pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
-		pix->field = V4L2_FIELD_NONE;
-
-		if (cmd == VIDIOC_TRY_FMT) {
-			if (copy_to_user(arg, &format, sizeof(format)))
-				return -EFAULT;
-			return 0;
-		}
-
-		if (cam->module_param.force_munmap)
-			for (i = 0; i < cam->nbuffers; i++)
-				if (cam->frame[i].vma_use_count) {
-					DBG(3, "VIDIOC_S_FMT failed. "
-					       "Unmap the buffers first.")
-					return -EINVAL;
-				}
-
-		if (cam->stream == STREAM_ON)
-			if ((err = sn9c102_stream_interrupt(cam)))
-				return err;
-
-		if (copy_to_user(arg, &format, sizeof(format))) {
-			cam->stream = stream;
-			return -EFAULT;
-		}
-
-		if (cam->module_param.force_munmap  || cam->io == IO_READ)
-			sn9c102_release_buffers(cam);
-
-		err += sn9c102_set_pix_format(cam, pix);
-		err += sn9c102_set_crop(cam, &rect);
-		if (s->set_pix_format)
-			err += s->set_pix_format(cam, pix);
-		if (s->set_crop)
-			err += s->set_crop(cam, &rect);
-		err += sn9c102_set_scale(cam, scale);
-
-		if (err) { /* atomic, no rollback in ioctl() */
-			cam->state |= DEV_MISCONFIGURED;
-			DBG(1, "VIDIOC_S_FMT failed because of hardware "
-			       "problems. To use the camera, close and open "
-			       "/dev/video%d again.", cam->v4ldev->minor)
-			return -EIO;
-		}
-
-		memcpy(pfmt, pix, sizeof(*pix));
-		memcpy(&(s->_rect), &rect, sizeof(rect));
-
-		if ((cam->module_param.force_munmap  || cam->io == IO_READ) &&
-		    nbuffers != sn9c102_request_buffers(cam, nbuffers,
-		                                        cam->io)) {
-			cam->state |= DEV_MISCONFIGURED;
-			DBG(1, "VIDIOC_S_FMT failed because of not enough "
-			       "memory. To use the camera, close and open "
-			       "/dev/video%d again.", cam->v4ldev->minor)
-			return -ENOMEM;
-		}
-
-		cam->stream = stream;
-
-		return 0;
-	}
+		return sn9c102_vidioc_try_s_fmt(cam, cmd, arg);
 
 	case VIDIOC_G_JPEGCOMP:
-	{
-		if (copy_to_user(arg, &cam->compression,
-		                 sizeof(cam->compression)))
-			return -EFAULT;
-
-		return 0;
-	}
+		return sn9c102_vidioc_g_jpegcomp(cam, arg);
 
 	case VIDIOC_S_JPEGCOMP:
-	{
-		struct v4l2_jpegcompression jc;
-		const enum sn9c102_stream_state stream = cam->stream;
-		int err = 0;
-
-		if (copy_from_user(&jc, arg, sizeof(jc)))
-			return -EFAULT;
-
-		if (jc.quality != 0 && jc.quality != 1)
-			return -EINVAL;
-
-		if (cam->stream == STREAM_ON)
-			if ((err = sn9c102_stream_interrupt(cam)))
-				return err;
-
-		err += sn9c102_set_compression(cam, &jc);
-		if (err) { /* atomic, no rollback in ioctl() */
-			cam->state |= DEV_MISCONFIGURED;
-			DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
-			       "problems. To use the camera, close and open "
-			       "/dev/video%d again.", cam->v4ldev->minor)
-			return -EIO;
-		}
-
-		cam->compression.quality = jc.quality;
-
-		cam->stream = stream;
-
-		return 0;
-	}
+		return sn9c102_vidioc_s_jpegcomp(cam, arg);
 
 	case VIDIOC_REQBUFS:
-	{
-		struct v4l2_requestbuffers rb;
-		u32 i;
-		int err;
-
-		if (copy_from_user(&rb, arg, sizeof(rb)))
-			return -EFAULT;
-
-		if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-		    rb.memory != V4L2_MEMORY_MMAP)
-			return -EINVAL;
-
-		if (cam->io == IO_READ) {
-			DBG(3, "Close and open the device again to choose "
-			       "the mmap I/O method")
-			return -EINVAL;
-		}
-
-		for (i = 0; i < cam->nbuffers; i++)
-			if (cam->frame[i].vma_use_count) {
-				DBG(3, "VIDIOC_REQBUFS failed. "
-				       "Previous buffers are still mapped.")
-				return -EINVAL;
-			}
-
-		if (cam->stream == STREAM_ON)
-			if ((err = sn9c102_stream_interrupt(cam)))
-				return err;
-
-		sn9c102_empty_framequeues(cam);
-
-		sn9c102_release_buffers(cam);
-		if (rb.count)
-			rb.count = sn9c102_request_buffers(cam, rb.count,
-			                                   IO_MMAP);
-
-		if (copy_to_user(arg, &rb, sizeof(rb))) {
-			sn9c102_release_buffers(cam);
-			cam->io = IO_NONE;
-			return -EFAULT;
-		}
-
-		cam->io = rb.count ? IO_MMAP : IO_NONE;
-
-		return 0;
-	}
+		return sn9c102_vidioc_reqbufs(cam, arg);
 
 	case VIDIOC_QUERYBUF:
-	{
-		struct v4l2_buffer b;
-
-		if (copy_from_user(&b, arg, sizeof(b)))
-			return -EFAULT;
-
-		if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-		    b.index >= cam->nbuffers || cam->io != IO_MMAP)
-			return -EINVAL;
-
-		memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
-
-		if (cam->frame[b.index].vma_use_count)
-			b.flags |= V4L2_BUF_FLAG_MAPPED;
-
-		if (cam->frame[b.index].state == F_DONE)
-			b.flags |= V4L2_BUF_FLAG_DONE;
-		else if (cam->frame[b.index].state != F_UNUSED)
-			b.flags |= V4L2_BUF_FLAG_QUEUED;
-
-		if (copy_to_user(arg, &b, sizeof(b)))
-			return -EFAULT;
-
-		return 0;
-	}
+		return sn9c102_vidioc_querybuf(cam, arg);
 
 	case VIDIOC_QBUF:
-	{
-		struct v4l2_buffer b;
-		unsigned long lock_flags;
-
-		if (copy_from_user(&b, arg, sizeof(b)))
-			return -EFAULT;
-
-		if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-		    b.index >= cam->nbuffers || cam->io != IO_MMAP)
-			return -EINVAL;
-
-		if (cam->frame[b.index].state != F_UNUSED)
-			return -EINVAL;
-
-		cam->frame[b.index].state = F_QUEUED;
-
-		spin_lock_irqsave(&cam->queue_lock, lock_flags);
-		list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
-		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
-		PDBGG("Frame #%lu queued", (unsigned long)b.index)
-
-		return 0;
-	}
+		return sn9c102_vidioc_qbuf(cam, arg);
 
 	case VIDIOC_DQBUF:
-	{
-		struct v4l2_buffer b;
-		struct sn9c102_frame_t *f;
-		unsigned long lock_flags;
-		int err = 0;
-
-		if (copy_from_user(&b, arg, sizeof(b)))
-			return -EFAULT;
-
-		if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP)
-			return -EINVAL;
-
-		if (list_empty(&cam->outqueue)) {
-			if (cam->stream == STREAM_OFF)
-				return -EINVAL;
-			if (filp->f_flags & O_NONBLOCK)
-				return -EAGAIN;
-			err = wait_event_interruptible
-			      ( cam->wait_frame, 
-			        (!list_empty(&cam->outqueue)) ||
-			        (cam->state & DEV_DISCONNECTED) ||
-			        (cam->state & DEV_MISCONFIGURED) );
-			if (err)
-				return err;
-			if (cam->state & DEV_DISCONNECTED)
-				return -ENODEV;
-			if (cam->state & DEV_MISCONFIGURED)
-				return -EIO;
-		}
-
-		spin_lock_irqsave(&cam->queue_lock, lock_flags);
-		f = list_entry(cam->outqueue.next, struct sn9c102_frame_t,
-		               frame);
-		list_del(cam->outqueue.next);
-		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
-		f->state = F_UNUSED;
-
-		memcpy(&b, &f->buf, sizeof(b));
-		if (f->vma_use_count)
-			b.flags |= V4L2_BUF_FLAG_MAPPED;
-
-		if (copy_to_user(arg, &b, sizeof(b)))
-			return -EFAULT;
-
-		PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index)
-
-		return 0;
-	}
+		return sn9c102_vidioc_dqbuf(cam, filp, arg);
 
 	case VIDIOC_STREAMON:
-	{
-		int type;
-
-		if (copy_from_user(&type, arg, sizeof(type)))
-			return -EFAULT;
-
-		if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-			return -EINVAL;
-
-		if (list_empty(&cam->inqueue))
-			return -EINVAL;
-
-		cam->stream = STREAM_ON;
-
-		DBG(3, "Stream on")
-
-		return 0;
-	}
+		return sn9c102_vidioc_streamon(cam, arg);
 
 	case VIDIOC_STREAMOFF:
-	{
-		int type, err;
-
-		if (copy_from_user(&type, arg, sizeof(type)))
-			return -EFAULT;
-
-		if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-			return -EINVAL;
-
-		if (cam->stream == STREAM_ON)
-			if ((err = sn9c102_stream_interrupt(cam)))
-				return err;
-
-		sn9c102_empty_framequeues(cam);
-
-		DBG(3, "Stream off")
-
-		return 0;
-	}
+		return sn9c102_vidioc_streamoff(cam, arg);
 
 	case VIDIOC_G_PARM:
-	{
-		struct v4l2_streamparm sp;
-
-		if (copy_from_user(&sp, arg, sizeof(sp)))
-			return -EFAULT;
-
-		if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			return -EINVAL;
-
-		sp.parm.capture.extendedmode = 0;
-		sp.parm.capture.readbuffers = cam->nreadbuffers;
-
-		if (copy_to_user(arg, &sp, sizeof(sp)))
-			return -EFAULT;
-
-		return 0;
-	}
+		return sn9c102_vidioc_g_parm(cam, arg);
 
 	case VIDIOC_S_PARM_OLD:
 	case VIDIOC_S_PARM:
-	{
-		struct v4l2_streamparm sp;
-
-		if (copy_from_user(&sp, arg, sizeof(sp)))
-			return -EFAULT;
-
-		if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			return -EINVAL;
-
-		sp.parm.capture.extendedmode = 0;
-
-		if (sp.parm.capture.readbuffers == 0)
-			sp.parm.capture.readbuffers = cam->nreadbuffers;
-
-		if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
-			sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
-
-		if (copy_to_user(arg, &sp, sizeof(sp)))
-			return -EFAULT;
-
-		cam->nreadbuffers = sp.parm.capture.readbuffers;
-
-		return 0;
-	}
+		return sn9c102_vidioc_s_parm(cam, arg);
 
 	case VIDIOC_G_STD:
 	case VIDIOC_S_STD:
@@ -2499,17 +2659,20 @@
 		return -ERESTARTSYS;
 
 	if (cam->state & DEV_DISCONNECTED) {
-		DBG(1, "Device not present")
+		DBG(1, "Device not present");
 		up(&cam->fileop_sem);
 		return -ENODEV;
 	}
 
 	if (cam->state & DEV_MISCONFIGURED) {
-		DBG(1, "The camera is misconfigured. Close and open it again.")
+		DBG(1, "The camera is misconfigured. Close and open it "
+		       "again.");
 		up(&cam->fileop_sem);
 		return -EIO;
 	}
 
+	V4LDBG(3, "sn9c102", cmd);
+
 	err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
 
 	up(&cam->fileop_sem);
@@ -2517,9 +2680,10 @@
 	return err;
 }
 
+/*****************************************************************************/
 
 static struct file_operations sn9c102_fops = {
-	.owner =   THIS_MODULE,
+	.owner = THIS_MODULE,
 	.open =    sn9c102_open,
 	.release = sn9c102_release,
 	.ioctl =   sn9c102_ioctl,
@@ -2538,36 +2702,22 @@
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct sn9c102_device* cam;
 	static unsigned int dev_nr = 0;
-	unsigned int i, n;
+	unsigned int i;
 	int err = 0, r;
 
-	n = ARRAY_SIZE(sn9c102_id_table);
-	for (i = 0; i < n-1; i++)
-		if (le16_to_cpu(udev->descriptor.idVendor) == 
-		    sn9c102_id_table[i].idVendor &&
-		    le16_to_cpu(udev->descriptor.idProduct) ==
-		    sn9c102_id_table[i].idProduct)
-			break;
-	if (i == n-1)
-		return -ENODEV;
-
-	if (!(cam = kmalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))
+	if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))
 		return -ENOMEM;
-	memset(cam, 0, sizeof(*cam));
 
 	cam->usbdev = udev;
 
-	memcpy(&cam->dev, &udev->dev, sizeof(struct device));
-
-	if (!(cam->control_buffer = kmalloc(8, GFP_KERNEL))) {
-		DBG(1, "kmalloc() failed")
+	if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
+		DBG(1, "kmalloc() failed");
 		err = -ENOMEM;
 		goto fail;
 	}
-	memset(cam->control_buffer, 0, 8);
 
 	if (!(cam->v4ldev = video_device_alloc())) {
-		DBG(1, "video_device_alloc() failed")
+		DBG(1, "video_device_alloc() failed");
 		err = -ENOMEM;
 		goto fail;
 	}
@@ -2577,25 +2727,22 @@
 	r = sn9c102_read_reg(cam, 0x00);
 	if (r < 0 || r != 0x10) {
 		DBG(1, "Sorry, this is not a SN9C10x based camera "
-		       "(vid/pid 0x%04X/0x%04X)",
-		    sn9c102_id_table[i].idVendor,sn9c102_id_table[i].idProduct)
+		       "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
 		err = -ENODEV;
 		goto fail;
 	}
 
-	cam->bridge = (sn9c102_id_table[i].idProduct & 0xffc0) == 0x6080 ?
+	cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ?
 	              BRIDGE_SN9C103 : BRIDGE_SN9C102;
 	switch (cam->bridge) {
 	case BRIDGE_SN9C101:
 	case BRIDGE_SN9C102:
 		DBG(2, "SN9C10[12] PC Camera Controller detected "
-		       "(vid/pid 0x%04X/0x%04X)", sn9c102_id_table[i].idVendor,
-		    sn9c102_id_table[i].idProduct)
+		       "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
 		break;
 	case BRIDGE_SN9C103:
 		DBG(2, "SN9C103 PC Camera Controller detected "
-		       "(vid/pid 0x%04X/0x%04X)", sn9c102_id_table[i].idVendor,
-		    sn9c102_id_table[i].idProduct)
+		       "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
 		break;
 	}
 
@@ -2606,24 +2753,24 @@
 	}
 
 	if (!err && cam->sensor) {
-		DBG(2, "%s image sensor detected", cam->sensor->name)
+		DBG(2, "%s image sensor detected", cam->sensor->name);
 		DBG(3, "Support for %s maintained by %s",
-		    cam->sensor->name, cam->sensor->maintainer)
+		    cam->sensor->name, cam->sensor->maintainer);
 	} else {
-		DBG(1, "No supported image sensor detected")
+		DBG(1, "No supported image sensor detected");
 		err = -ENODEV;
 		goto fail;
 	}
 
 	if (sn9c102_init(cam)) {
-		DBG(1, "Initialization failed. I will retry on open().")
+		DBG(1, "Initialization failed. I will retry on open().");
 		cam->state |= DEV_MISCONFIGURED;
 	}
 
 	strcpy(cam->v4ldev->name, "SN9C10x PC Camera");
 	cam->v4ldev->owner = THIS_MODULE;
 	cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
-	cam->v4ldev->hardware = VID_HARDWARE_SN9C102;
+	cam->v4ldev->hardware = 0;
 	cam->v4ldev->fops = &sn9c102_fops;
 	cam->v4ldev->minor = video_nr[dev_nr];
 	cam->v4ldev->release = video_device_release;
@@ -2634,23 +2781,25 @@
 	err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
 	                            video_nr[dev_nr]);
 	if (err) {
-		DBG(1, "V4L2 device registration failed")
+		DBG(1, "V4L2 device registration failed");
 		if (err == -ENFILE && video_nr[dev_nr] == -1)
-			DBG(1, "Free /dev/videoX node not found")
+			DBG(1, "Free /dev/videoX node not found");
 		video_nr[dev_nr] = -1;
 		dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
 		up(&cam->dev_sem);
 		goto fail;
 	}
 
-	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor)
+	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
 
 	cam->module_param.force_munmap = force_munmap[dev_nr];
 
 	dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
 	sn9c102_create_sysfs(cam);
-	DBG(2, "Optional device control through 'sysfs' interface ready")
+	DBG(2, "Optional device control through 'sysfs' interface ready");
+#endif
 
 	usb_set_intfdata(intf, cam);
 
@@ -2680,14 +2829,14 @@
 
 	down(&cam->dev_sem); 
 
-	DBG(2, "Disconnecting %s...", cam->v4ldev->name)
+	DBG(2, "Disconnecting %s...", cam->v4ldev->name);
 
 	wake_up_interruptible_all(&cam->open);
 
 	if (cam->users) {
 		DBG(2, "Device /dev/video%d is open! Deregistration and "
 		       "memory deallocation are deferred on close.",
-		    cam->v4ldev->minor)
+		    cam->v4ldev->minor);
 		cam->state |= DEV_MISCONFIGURED;
 		sn9c102_stop_transfer(cam);
 		cam->state |= DEV_DISCONNECTED;
@@ -2720,11 +2869,11 @@
 {
 	int err = 0;
 
-	KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION)
-	KDBG(3, SN9C102_MODULE_AUTHOR)
+	KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION);
+	KDBG(3, SN9C102_MODULE_AUTHOR);
 
 	if ((err = usb_register(&sn9c102_usb_driver)))
-		KDBG(1, "usb_register() failed")
+		KDBG(1, "usb_register() failed");
 
 	return err;
 }
diff --git a/drivers/usb/media/sn9c102_hv7131d.c b/drivers/usb/media/sn9c102_hv7131d.c
index 18070d5..46c12ec 100644
--- a/drivers/usb/media/sn9c102_hv7131d.c
+++ b/drivers/usb/media/sn9c102_hv7131d.c
@@ -2,7 +2,7 @@
  * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera     *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
diff --git a/drivers/usb/media/sn9c102_mi0343.c b/drivers/usb/media/sn9c102_mi0343.c
index 86676ab..d9aa7a6 100644
--- a/drivers/usb/media/sn9c102_mi0343.c
+++ b/drivers/usb/media/sn9c102_mi0343.c
@@ -2,7 +2,7 @@
  * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera     *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
diff --git a/drivers/usb/media/sn9c102_ov7630.c b/drivers/usb/media/sn9c102_ov7630.c
index d27c5ae..4a36519 100644
--- a/drivers/usb/media/sn9c102_ov7630.c
+++ b/drivers/usb/media/sn9c102_ov7630.c
@@ -2,7 +2,7 @@
  * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera      *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2005 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2005-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -375,8 +375,10 @@
 
 	sn9c102_attach_sensor(cam, &ov7630);
 
-	if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f &&
-	    le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c)
+	if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c &&
+	    le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602d &&
+	    le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f &&
+	    le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x60b0)
 		return -ENODEV;
 
 	err += sn9c102_write_reg(cam, 0x01, 0x01);
diff --git a/drivers/usb/media/sn9c102_pas106b.c b/drivers/usb/media/sn9c102_pas106b.c
index 48e3ec3..b1dee78 100644
--- a/drivers/usb/media/sn9c102_pas106b.c
+++ b/drivers/usb/media/sn9c102_pas106b.c
@@ -2,7 +2,7 @@
  * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera     *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h
index a45166c..7d953b2 100644
--- a/drivers/usb/media/sn9c102_sensor.h
+++ b/drivers/usb/media/sn9c102_sensor.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  * API for image sensors connected to the SN9C10x PC Camera Controllers    *
  *                                                                         *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -92,7 +92,18 @@
 sn9c102_attach_sensor(struct sn9c102_device* cam,
                       struct sn9c102_sensor* sensor);
 
-/* Each SN9C10X camera has proper PID/VID identifiers. Add them here in case.*/
+/*
+   Each SN9C10x camera has proper PID/VID identifiers.
+   SN9C103 supports multiple interfaces, but we only handle the video class
+   interface.
+*/
+#define SN9C102_USB_DEVICE(vend, prod, intclass)                              \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
+	               USB_DEVICE_ID_MATCH_INT_CLASS,                         \
+	.idVendor = (vend),                                                   \
+	.idProduct = (prod),                                                  \
+	.bInterfaceClass = (intclass)
+
 #define SN9C102_ID_TABLE                                                      \
 static const struct usb_device_id sn9c102_id_table[] = {                      \
 	{ USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */                     \
@@ -107,33 +118,34 @@
 	{ USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */                        \
 	{ USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */                         \
 	{ USB_DEVICE(0x0c45, 0x602d), },                                      \
+	{ USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */                         \
 	{ USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */                          \
-	{ USB_DEVICE(0x0c45, 0x6080), },                                      \
-	{ USB_DEVICE(0x0c45, 0x6082), }, /* MI0343 and MI0360 */              \
-	{ USB_DEVICE(0x0c45, 0x6083), }, /* HV7131[D|E1] */                   \
-	{ USB_DEVICE(0x0c45, 0x6088), },                                      \
-	{ USB_DEVICE(0x0c45, 0x608a), },                                      \
-	{ USB_DEVICE(0x0c45, 0x608b), },                                      \
-	{ USB_DEVICE(0x0c45, 0x608c), }, /* HV7131x */                        \
-	{ USB_DEVICE(0x0c45, 0x608e), }, /* CIS-VF10 */                       \
-	{ USB_DEVICE(0x0c45, 0x608f), }, /* OV7630 */                         \
-	{ USB_DEVICE(0x0c45, 0x60a0), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60a2), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60a3), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60a8), }, /* PAS106B */                        \
-	{ USB_DEVICE(0x0c45, 0x60aa), }, /* TAS5130D1B */                     \
-	{ USB_DEVICE(0x0c45, 0x60ab), }, /* TAS5110C1B */                     \
-	{ USB_DEVICE(0x0c45, 0x60ac), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60ae), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60af), }, /* PAS202BCB */                      \
-	{ USB_DEVICE(0x0c45, 0x60b0), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60b2), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60b3), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60b8), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60ba), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60bb), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60bc), },                                      \
-	{ USB_DEVICE(0x0c45, 0x60be), },                                      \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */  \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */     \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131x */          \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */         \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */           \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */          \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */       \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */       \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */       \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), },                        \
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), },                        \
 	{ }                                                                   \
 };
 
@@ -177,16 +189,18 @@
 extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
 
 /* I/O on registers in the bridge. Could be used by the sensor methods too */
+extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index);
 extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
 extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
 
 /*
    NOTE: there are no exported debugging functions. To uniform the output you
    must use the dev_info()/dev_warn()/dev_err() macros defined in device.h,
-   already included here, the argument being the struct device 'dev' of the
-   sensor structure. Do NOT use these macros before the sensor is attached or
-   the kernel will crash! However, you should not need to notify the user about
-   common errors or other messages, since this is done by the master module.
+   already included here, the argument being the struct device '&usbdev->dev'
+   of the sensor structure. Do NOT use these macros before the sensor is
+   attached or the kernel will crash! However, you should not need to notify
+   the user about common errors or other messages, since this is done by the
+   master module.
 */
 
 /*****************************************************************************/
@@ -345,13 +359,6 @@
 	   error code without rolling back.
 	*/
 
-	const struct device* dev;
-	/*
-	   This is the argument for dev_err(), dev_info() and dev_warn(). It
-	   is used for debugging purposes. You must not access the struct
-	   before the sensor is attached.
-	*/
-
 	const struct usb_device* usbdev;
 	/*
 	   Points to the usb_device struct after the sensor is attached.
diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c
index 8775999..32ddf23 100644
--- a/drivers/usb/media/sn9c102_tas5110c1b.c
+++ b/drivers/usb/media/sn9c102_tas5110c1b.c
@@ -2,7 +2,7 @@
  * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera  *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c
index 927eafd..a0728f0 100644
--- a/drivers/usb/media/sn9c102_tas5130d1b.c
+++ b/drivers/usb/media/sn9c102_tas5130d1b.c
@@ -2,7 +2,7 @@
  * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera  *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index bff9434..9937fc6 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -62,7 +62,6 @@
 MODULE_SUPPORTED_DEVICE("Video");
 
 static int ovmod_load = W9968CF_OVMOD_LOAD;
-static int vppmod_load = W9968CF_VPPMOD_LOAD;
 static unsigned short simcams = W9968CF_SIMCAMS;
 static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/
 static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = 
@@ -107,7 +106,6 @@
 
 #ifdef CONFIG_KMOD
 module_param(ovmod_load, bool, 0644);
-module_param(vppmod_load, bool, 0444);
 #endif
 module_param(simcams, ushort, 0644);
 module_param_array(video_nr, short, &param_nv[0], 0444);
@@ -150,18 +148,6 @@
                  "\ninto memory."
                  "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"."
                  "\n");
-MODULE_PARM_DESC(vppmod_load, 
-                 "\n<0|1> Automatic 'w9968cf-vpp' module loading."
-                 "\n0 disabled, 1 enabled."
-                 "\nIf enabled, every time an application attempts to open a"
-                 "\ncamera, 'insmod' searches for the video post-processing"
-                 "\nmodule in the system and loads it automatically (if"
-                 "\npresent). The optional 'w9968cf-vpp' module adds extra"
-                 "\n image manipulation functions to the 'w9968cf' module,like"
-                 "\nsoftware up-scaling,colour conversions and video decoding"
-                 "\nfor very high frame rates."
-                 "\nDefault value is "__MODULE_STRING(W9968CF_VPPMOD_LOAD)"."
-                 "\n");
 #endif
 MODULE_PARM_DESC(simcams, 
                  "\n<n> Number of cameras allowed to stream simultaneously."
@@ -492,10 +478,6 @@
 static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**);
 static void w9968cf_release_resources(struct w9968cf_device*);
 
-/* Intermodule communication */
-static int w9968cf_vppmod_detect(struct w9968cf_device*);
-static void w9968cf_vppmod_release(struct w9968cf_device*);
-
 
 
 /****************************************************************************
@@ -2737,9 +2719,7 @@
 	cam->streaming = 0;
 	cam->misconfigured = 0;
 
-	if (!w9968cf_vpp)
-		if ((err = w9968cf_vppmod_detect(cam)))
-			goto out;
+	w9968cf_adjust_configuration(cam);
 
 	if ((err = w9968cf_allocate_memory(cam)))
 		goto deallocate_memory;
@@ -2766,7 +2746,6 @@
 
 deallocate_memory:
 	w9968cf_deallocate_memory(cam);
-out:
 	DBG(2, "Failed to open the video device")
 	up(&cam->dev_sem);
 	up_read(&w9968cf_disconnect);
@@ -2784,8 +2763,6 @@
 
 	w9968cf_stop_transfer(cam);
 
-	w9968cf_vppmod_release(cam);
-
 	if (cam->disconnected) {
 		w9968cf_release_resources(cam);
 		up(&cam->dev_sem);
@@ -3681,106 +3658,6 @@
  * Module init, exit and intermodule communication                          *
  ****************************************************************************/
 
-static int w9968cf_vppmod_detect(struct w9968cf_device* cam)
-{
-	if (!w9968cf_vpp)
-		if (vppmod_load)
-			request_module("w9968cf-vpp");
-
-	down(&w9968cf_vppmod_lock);
-
-	if (!w9968cf_vpp) {
-		DBG(4, "Video post-processing module not detected")
-		w9968cf_adjust_configuration(cam);
-		goto out;
-	}
-
-	if (!try_module_get(w9968cf_vpp->owner)) {
-		DBG(1, "Couldn't increment the reference count of "
-		       "the video post-processing module")
-		up(&w9968cf_vppmod_lock);
-		return -ENOSYS;
-	}
-
-	w9968cf_vpp->busy++;
-
-	DBG(5, "Video post-processing module detected")
-
-out:
-	up(&w9968cf_vppmod_lock);
-	return 0;
-}
-
-
-static void w9968cf_vppmod_release(struct w9968cf_device* cam)
-{
-	down(&w9968cf_vppmod_lock);
-
-	if (w9968cf_vpp && w9968cf_vpp->busy) {
-		module_put(w9968cf_vpp->owner);
-		w9968cf_vpp->busy--;
-		wake_up(&w9968cf_vppmod_wait);
-		DBG(5, "Video post-processing module released")
-	}
-
-	up(&w9968cf_vppmod_lock);
-}
-
-
-int w9968cf_vppmod_register(struct w9968cf_vpp_t* vpp)
-{
-	down(&w9968cf_vppmod_lock);
-
-	if (w9968cf_vpp) {
-		KDBG(1, "Video post-processing module already registered")
-		up(&w9968cf_vppmod_lock);
-		return -EINVAL;
-	}
-
-	w9968cf_vpp = vpp;
-	w9968cf_vpp->busy = 0;
-
-	KDBG(2, "Video post-processing module registered")
-	up(&w9968cf_vppmod_lock);
-	return 0;
-}
-
-
-int w9968cf_vppmod_deregister(struct w9968cf_vpp_t* vpp)
-{
-	down(&w9968cf_vppmod_lock);
-
-	if (!w9968cf_vpp) {
-		up(&w9968cf_vppmod_lock);
-		return -EINVAL;
-	}
-
-	if (w9968cf_vpp != vpp) {
-		KDBG(1, "Only the owner can unregister the video "
-		        "post-processing module")
-		up(&w9968cf_vppmod_lock);
-		return -EINVAL;
-	}
-
-	if (w9968cf_vpp->busy) {
-		KDBG(2, "Video post-processing module busy. Wait for it to be "
-		        "released...")
-		up(&w9968cf_vppmod_lock);
-		wait_event(w9968cf_vppmod_wait, !w9968cf_vpp->busy);
-		w9968cf_vpp = NULL;
-		goto out;
-	}
-
-	w9968cf_vpp = NULL;
-
-	up(&w9968cf_vppmod_lock);
-
-out:
-	KDBG(2, "Video post-processing module unregistered")
-	return 0;
-}
-
-
 static int __init w9968cf_module_init(void)
 {
 	int err;
@@ -3810,6 +3687,3 @@
 module_init(w9968cf_module_init);
 module_exit(w9968cf_module_exit);
 
-
-EXPORT_SYMBOL(w9968cf_vppmod_register);
-EXPORT_SYMBOL(w9968cf_vppmod_deregister);
diff --git a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h
index 8acbfe2..47a6ff7 100644
--- a/drivers/usb/media/w9968cf.h
+++ b/drivers/usb/media/w9968cf.h
@@ -195,7 +195,6 @@
 };
 
 static struct w9968cf_vpp_t* w9968cf_vpp;
-static DECLARE_MUTEX(w9968cf_vppmod_lock);
 static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait);
 
 static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */
diff --git a/drivers/usb/media/w9968cf_vpp.h b/drivers/usb/media/w9968cf_vpp.h
index 3f5317d..f3b91b7 100644
--- a/drivers/usb/media/w9968cf_vpp.h
+++ b/drivers/usb/media/w9968cf_vpp.h
@@ -37,7 +37,4 @@
 	u8 busy; /* read-only flag: module is/is not in use */
 };
 
-extern int w9968cf_vppmod_register(struct w9968cf_vpp_t*);
-extern int w9968cf_vppmod_deregister(struct w9968cf_vpp_t*);
-
 #endif /* _W9968CF_VPP_H_ */
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 449b250..ad2f4cc 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -2093,6 +2093,8 @@
 static struct usb_device_id auerswald_ids [] = {
 	{ USB_DEVICE (ID_AUERSWALD, 0x00C0) },          /* COMpact 2104 USB */
 	{ USB_DEVICE (ID_AUERSWALD, 0x00DB) },          /* COMpact 4410/2206 USB */
+	{ USB_DEVICE (ID_AUERSWALD, 0x00DC) }, /* COMpact 4406 DSL */
+	{ USB_DEVICE (ID_AUERSWALD, 0x00DD) }, /* COMpact 2204 USB */
 	{ USB_DEVICE (ID_AUERSWALD, 0x00F1) },          /* Comfort 2000 System Telephone */
 	{ USB_DEVICE (ID_AUERSWALD, 0x00F2) },          /* Comfort 1200 System Telephone */
         { }			                        /* Terminating entry */
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 981d8a5..331d4ae 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -593,7 +593,7 @@
 
 /*
  * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
+ * and to have the device registered with the driver core
  */
 static struct usb_class_driver ld_usb_class = {
 	.name =		"ldusb%d",
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 5411816..3094970 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -916,6 +916,10 @@
 	// Linksys USB200M Rev 2
 	USB_DEVICE (0x13b1, 0x0018),
 	.driver_info = (unsigned long) &ax88772_info,
+}, {
+	// 0Q0 cable ethernet
+	USB_DEVICE (0x1557, 0x7720),
+	.driver_info = (unsigned long) &ax88772_info,
 },
 	{ },		// END
 };
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index da46b35..dc7a069 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -32,7 +32,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.05"
+#define DRIVER_VERSION "v0.06"
 #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
 
 /*
@@ -55,11 +55,15 @@
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
-	{ USB_DEVICE(0x10C4, 0xEA60) },	/* Silicon Labs factory default */
-	{ USB_DEVICE(0x10C4, 0x80CA) },	/* Degree Controls Inc */
-	{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
 	{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
-	{ USB_DEVICE(0x10AB, 0x10C5) },	/* Siemens MC60 Cable */
+	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
+	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
+	{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
+	{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
+	{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
+	{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
+	{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
+	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
 	{ } /* Terminating Entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 10bc1bf..f2b4ca8 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -476,10 +476,16 @@
 	{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) },
 	{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
 	{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
 	{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 00d45f8..ca40f16 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -31,9 +31,14 @@
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
 
+
 /* www.irtrans.de device */
 #define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
 
+
+/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */
+#define FTDI_TTUSB_PID 0xFF20 /* Product Id */
+
 /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
 /* they use the ftdi chipset for the USB interface and the vendor id is the same */
 #define FTDI_XF_632_PID 0xFC08	/* 632: 16x2 Character Display */
@@ -51,6 +56,12 @@
 #define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */
 
 /*
+ * PCDJ use ftdi based dj-controllers.  The following PID is for their DAC-2 device
+ * http://www.pcdjhardware.com/DAC2.asp (PID sent by Wouter Paesen)
+ * (the VID is the standard ftdi vid (FTDI_VID) */
+#define FTDI_PCDJ_DAC2_PID 0xFA88
+
+/*
  * The following are the values for the Matrix Orbital LCD displays,
  * which are the FT232BM ( similar to the 8U232AM )
  */
@@ -215,8 +226,10 @@
  * Definitions for ATIK Instruments astronomical USB based cameras
  * Check it at http://www.atik-instruments.com/
  */
-#define FTDI_ATIK_ATK16_PID	0xDF30	/* ATIK ATK-16 Camera */
-#define FTDI_ATIK_ATK16HR_PID	0xDF31	/* ATIK ATK-16HR Camera */
+#define FTDI_ATIK_ATK16_PID	0xDF30	/* ATIK ATK-16 Grayscale Camera */
+#define FTDI_ATIK_ATK16C_PID	0xDF32	/* ATIK ATK-16C Colour Camera */
+#define FTDI_ATIK_ATK16HR_PID	0xDF31	/* ATIK ATK-16HR Grayscale Camera */
+#define FTDI_ATIK_ATK16HRC_PID	0xDF33	/* ATIK ATK-16HRC Colour Camera */
 
 /*
  * Protego product ids
@@ -365,6 +378,12 @@
 #define POSIFLEX_VID		0x0d3a  /* Vendor ID */
 #define POSIFLEX_PP7000_PID	0x0300  /* PP-7000II thermal printer */
 
+/*
+ * Westrex International devices submitted by Cory Lee
+ */
+#define FTDI_WESTREX_MODEL_777_PID	0xDC00	/* Model 777 */
+#define FTDI_WESTREX_MODEL_8900F_PID	0xDC01	/* Model 8900F */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 0eb883f..e8e575e 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -73,7 +73,9 @@
 	{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
 	{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) },
 	{ USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
-	{ USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) },
+	{ USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) },
+	{ USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID ) },
+	{ USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 21d434d..1807087 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -64,3 +64,10 @@
 /* Nokia CA-42 Cable */
 #define NOKIA_CA42_VENDOR_ID	0x078b
 #define NOKIA_CA42_PRODUCT_ID	0x1234
+
+/* CA-42 CLONE Cable www.ca-42.com chipset: Prolific Technology Inc */
+#define CA_42_CA42_VENDOR_ID	0x10b5
+#define CA_42_CA42_PRODUCT_ID	0xac70
+
+#define SAGEM_VENDOR_ID		0x079b
+#define SAGEM_PRODUCT_ID	0x0027
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 5b06f92..ab173b3 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -45,6 +45,12 @@
 #include "debug.h"
 #include "transport.h"
 
+#define RIO_MSC 0x08
+#define RIOP_INIT "RIOP\x00\x01\x08"
+#define RIOP_INIT_LEN 7
+#define RIO_SEND_LEN 40
+#define RIO_RECV_LEN 0x200
+
 /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
  * mode */
 int usb_stor_euscsi_init(struct us_data *us)
@@ -91,3 +97,70 @@
 
 	return (res ? -1 : 0);
 }
+
+/* Place the Rio Karma into mass storage mode.
+ *
+ * The initialization begins by sending 40 bytes starting
+ * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte
+ * packet with the high four bits set and everything else null.
+ *
+ * Next, we send RIOP\x80\x00\x08\x00.  Each time, a 512 byte response
+ * must be read, but we must loop until byte 5 in the response is 0x08,
+ * indicating success.  */
+int rio_karma_init(struct us_data *us)
+{
+	int result, partial;
+	char *recv;
+	unsigned long timeout;
+
+	// us->iobuf is big enough to hold cmd but not receive
+	if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL)))
+		goto die_nomem;
+
+	US_DEBUGP("Initializing Karma...\n");
+
+	memset(us->iobuf, 0, RIO_SEND_LEN);
+	memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN);
+
+	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		us->iobuf, RIO_SEND_LEN, &partial);
+	if (result != USB_STOR_XFER_GOOD)
+		goto die;
+
+	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+		recv, RIO_RECV_LEN, &partial);
+	if (result != USB_STOR_XFER_GOOD)
+		goto die;
+
+	us->iobuf[4] = 0x80;
+	us->iobuf[5] = 0;
+	timeout = jiffies + msecs_to_jiffies(3000);
+	for (;;) {
+		US_DEBUGP("Sending init command\n");
+		result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+			us->iobuf, RIO_SEND_LEN, &partial);
+		if (result != USB_STOR_XFER_GOOD)
+			goto die;
+
+		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+			recv, RIO_RECV_LEN, &partial);
+		if (result != USB_STOR_XFER_GOOD)
+			goto die;
+
+		if (recv[5] == RIO_MSC)
+			break;
+		if (time_after(jiffies, timeout))
+			goto die;
+		msleep(10);
+	}
+	US_DEBUGP("Karma initialized.\n");
+	kfree(recv);
+	return 0;
+
+die:
+	kfree(recv);
+die_nomem:
+	US_DEBUGP("Could not initialize karma.\n");
+	return USB_STOR_TRANSPORT_FAILED;
+}
+
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index 4c1b2bd..f9907a5 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -48,3 +48,4 @@
 /* This function is required to activate all four slots on the UCR-61S2B
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
+int rio_karma_init(struct us_data *us);
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
index b28151d..b1ec4a7 100644
--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -116,7 +116,7 @@
 static int usu_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
-	int type;
+	unsigned long type;
 	int rc;
 	unsigned long flags;
 
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index dc301e5..ee958f9 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -145,6 +145,11 @@
 		US_SC_DEVICE, US_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
+UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
+		"Rio",
+		"Rio Karma",
+		US_SC_SCSI, US_PR_BULK, rio_karma_init, 0),
+
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
 		"Kyocera",
@@ -424,11 +429,11 @@
 		US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
 
 /* This entry is needed because the device reports Sub=ff */
-UNUSUAL_DEV(  0x054c, 0x0010, 0x0500, 0x0500, 
-               "Sony",
-               "DSC-T1", 
-               US_SC_8070, US_PR_DEVICE, NULL,
-               US_FL_SINGLE_LUN ),
+UNUSUAL_DEV(  0x054c, 0x0010, 0x0500, 0x0600,
+		"Sony",
+		"DSC-T1/T5",
+		US_SC_8070, US_PR_DEVICE, NULL,
+		US_FL_SINGLE_LUN ),
 
 
 /* Reported by wim@geeks.nl */
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 5d02f16..4de9fb5 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -234,7 +234,7 @@
 
 /* 
  * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
+ * and to have the device registered with the driver core
  */
 static struct usb_class_driver skel_class = {
 	.name =		"skel%d",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3e153d3..e64ed16 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -525,11 +525,6 @@
 	  This is the amount of memory reserved for the framebuffer,
 	  which can be any value between 1MB and 8MB.
 
-config BUS_I2C
-	bool
-	depends on (FB = y) && VISWS
-	default y
-
 config FB_SUN3
 	bool "Sun3 framebuffer support"
 	depends on (FB = y) && (SUN3 || SUN3X) && BROKEN
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index b218717..6761b68 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -116,9 +116,10 @@
 	int ret = 0;
 
 	memset(&var->transp, 0, sizeof(var->transp));
-	memset(&var->red, 0, sizeof(var->red));
-	memset(&var->green, 0, sizeof(var->green));
-	memset(&var->blue, 0, sizeof(var->blue));
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
 
 	switch (var->bits_per_pixel) {
 	case 1:
@@ -133,34 +134,20 @@
 		var->blue.offset	= 0;
 		break;
 	case 16:
-		var->red.length		= 5;
-		var->green.length	= 6;
-		var->blue.length	= 5;
-		if (fb->panel->cntl & CNTL_BGR) {
-			var->red.offset		= 11;
-			var->green.offset	= 5;
-			var->blue.offset	= 0;
-		} else {
-			var->red.offset		= 0;
-			var->green.offset	= 5;
-			var->blue.offset	= 11;
-		}
+		var->red.length = 5;
+		var->blue.length = 5;
+		/*
+		 * Green length can be 5 or 6 depending whether
+		 * we're operating in RGB555 or RGB565 mode.
+		 */
+		if (var->green.length != 5 && var->green.length != 6)
+			var->green.length = 6;
 		break;
 	case 32:
 		if (fb->panel->cntl & CNTL_LCDTFT) {
 			var->red.length		= 8;
 			var->green.length	= 8;
 			var->blue.length	= 8;
-
-			if (fb->panel->cntl & CNTL_BGR) {
-				var->red.offset		= 16;
-				var->green.offset	= 8;
-				var->blue.offset	= 0;
-			} else {
-				var->red.offset		= 0;
-				var->green.offset	= 8;
-				var->blue.offset	= 16;
-			}
 			break;
 		}
 	default:
@@ -168,6 +155,23 @@
 		break;
 	}
 
+	/*
+	 * >= 16bpp displays have separate colour component bitfields
+	 * encoded in the pixel data.  Calculate their position from
+	 * the bitfield length defined above.
+	 */
+	if (ret == 0 && var->bits_per_pixel >= 16) {
+		if (fb->panel->cntl & CNTL_BGR) {
+			var->blue.offset = 0;
+			var->green.offset = var->blue.offset + var->blue.length;
+			var->red.offset = var->green.offset + var->green.length;
+		} else {
+			var->red.offset = 0;
+			var->green.offset = var->red.offset + var->red.length;
+			var->blue.offset = var->green.offset + var->green.length;
+		}
+	}
+
 	return ret;
 }
 
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 996d543..9d996f2 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -50,3 +50,11 @@
 	  If you have a Sharp Zaurus SL-C7xx, say y to enable the
 	  backlight driver.
 
+config BACKLIGHT_HP680
+	tristate "HP Jornada 680 Backlight Driver"
+	depends on BACKLIGHT_DEVICE && SH_HP6XX
+	default y
+	help
+	  If you have a HP Jornada 680, say y to enable the
+	  backlight driver.
+
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 4af321f..744210c 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -3,4 +3,5 @@
 obj-$(CONFIG_LCD_CLASS_DEVICE)     += lcd.o
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_CORGI)	+= corgi_bl.o
+obj-$(CONFIG_BACKLIGHT_HP680)	+= hp680_bl.o
 obj-$(CONFIG_SHARP_LOCOMO)	+= locomolcd.o
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 9d5015e..bd39bbd 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -13,7 +13,6 @@
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/fb.h>
-#include <asm/bug.h>
 
 static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
 {
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
new file mode 100644
index 0000000..95da4c9
--- /dev/null
+++ b/drivers/video/backlight/hp680_bl.c
@@ -0,0 +1,189 @@
+/*
+ *  Backlight Driver for HP Jornada 680
+ *
+ *  Copyright (c) 2005 Andriy Skulysh
+ *
+ *  Based on Sharp's Corgi Backlight Driver
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+
+#include <asm/cpu/dac.h>
+#include <asm/hp6xx/hp6xx.h>
+#include <asm/hd64461/hd64461.h>
+
+#define HP680_MAX_INTENSITY 255
+#define HP680_DEFAULT_INTENSITY 10
+
+static int hp680bl_powermode = FB_BLANK_UNBLANK;
+static int current_intensity = 0;
+static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+
+static void hp680bl_send_intensity(int intensity)
+{
+	unsigned long flags;
+
+	if (hp680bl_powermode != FB_BLANK_UNBLANK)
+		intensity = 0;
+
+	spin_lock_irqsave(&bl_lock, flags);
+	sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+	spin_unlock_irqrestore(&bl_lock, flags);
+}
+
+static void hp680bl_blank(int blank)
+{
+	u16 v;
+
+	switch(blank) {
+
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+		if (hp680bl_powermode == FB_BLANK_UNBLANK) {
+			hp680bl_send_intensity(0);
+			hp680bl_powermode = blank;
+			sh_dac_disable(DAC_LCD_BRIGHTNESS);
+			v = inw(HD64461_GPBDR);
+			v |= HD64461_GPBDR_LCDOFF;
+			outw(v, HD64461_GPBDR);
+		}
+		break;
+	case FB_BLANK_UNBLANK:
+		if (hp680bl_powermode != FB_BLANK_UNBLANK) {
+			sh_dac_enable(DAC_LCD_BRIGHTNESS);
+			v = inw(HD64461_GPBDR);
+			v &= ~HD64461_GPBDR_LCDOFF;
+			outw(v, HD64461_GPBDR);
+			hp680bl_powermode = blank;
+			hp680bl_send_intensity(current_intensity);
+		}
+		break;
+	}
+}
+
+#ifdef CONFIG_PM
+static int hp680bl_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+	if (level == SUSPEND_POWER_DOWN)
+		hp680bl_blank(FB_BLANK_POWERDOWN);
+	return 0;
+}
+
+static int hp680bl_resume(struct device *dev, u32 level)
+{
+	if (level == RESUME_POWER_ON)
+		hp680bl_blank(FB_BLANK_UNBLANK);
+	return 0;
+}
+#else
+#define hp680bl_suspend	NULL
+#define hp680bl_resume	NULL
+#endif
+
+
+static int hp680bl_set_power(struct backlight_device *bd, int state)
+{
+	hp680bl_blank(state);
+	return 0;
+}
+
+static int hp680bl_get_power(struct backlight_device *bd)
+{
+	return hp680bl_powermode;
+}
+
+static int hp680bl_set_intensity(struct backlight_device *bd, int intensity)
+{
+	if (intensity > HP680_MAX_INTENSITY)
+		intensity = HP680_MAX_INTENSITY;
+	hp680bl_send_intensity(intensity);
+	current_intensity = intensity;
+	return 0;
+}
+
+static int hp680bl_get_intensity(struct backlight_device *bd)
+{
+	return current_intensity;
+}
+
+static struct backlight_properties hp680bl_data = {
+	.owner		= THIS_MODULE,
+	.get_power      = hp680bl_get_power,
+	.set_power      = hp680bl_set_power,
+	.max_brightness = HP680_MAX_INTENSITY,
+	.get_brightness = hp680bl_get_intensity,
+	.set_brightness = hp680bl_set_intensity,
+};
+
+static struct backlight_device *hp680_backlight_device;
+
+static int __init hp680bl_probe(struct device *dev)
+{
+	hp680_backlight_device = backlight_device_register ("hp680-bl",
+		NULL, &hp680bl_data);
+	if (IS_ERR (hp680_backlight_device))
+		return PTR_ERR (hp680_backlight_device);
+
+	hp680bl_set_intensity(NULL, HP680_DEFAULT_INTENSITY);
+
+	return 0;
+}
+
+static int hp680bl_remove(struct device *dev)
+{
+	backlight_device_unregister(hp680_backlight_device);
+
+	return 0;
+}
+
+static struct device_driver hp680bl_driver = {
+	.name		= "hp680-bl",
+	.bus		= &platform_bus_type,
+	.probe		= hp680bl_probe,
+	.remove		= hp680bl_remove,
+	.suspend	= hp680bl_suspend,
+	.resume		= hp680bl_resume,
+};
+
+static struct platform_device hp680bl_device = {
+	.name	= "hp680-bl",
+	.id	= -1,
+};
+
+static int __init hp680bl_init(void)
+{
+	int ret;
+
+	ret=driver_register(&hp680bl_driver);
+	if (!ret) {
+		ret = platform_device_register(&hp680bl_device);
+		if (ret)
+			driver_unregister(&hp680bl_driver);
+	}
+	return ret;
+}
+
+static void __exit hp680bl_exit(void)
+{
+	platform_device_unregister(&hp680bl_device);
+ 	driver_unregister(&hp680bl_driver);
+}
+
+module_init(hp680bl_init);
+module_exit(hp680bl_exit);
+
+MODULE_AUTHOR("Andriy Skulysh <askulysh@image.kiev.ua>");
+MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 68c6906..9e32485 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -13,7 +13,6 @@
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/fb.h>
-#include <asm/bug.h>
 
 static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
 {
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index a7bcd17..0339f56 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -30,10 +30,11 @@
 
 #define STI_DRIVERVERSION "Version 0.9a"
 
-struct sti_struct *default_sti;
+struct sti_struct *default_sti __read_mostly;
 
-static int num_sti_roms;			  /* # of STI ROMS found */
-static struct sti_struct *sti_roms[MAX_STI_ROMS]; /* ptr to each sti_struct */
+/* number of STI ROMS found and their ptrs to each struct */
+static int num_sti_roms __read_mostly;
+static struct sti_struct *sti_roms[MAX_STI_ROMS] __read_mostly;
 
 
 /* The colour indices used by STI are
@@ -266,7 +267,7 @@
 
 
 
-static char default_sti_path[21];
+static char default_sti_path[21] __read_mostly;
 
 #ifndef MODULE
 static int __init sti_setup(char *str)
@@ -414,10 +415,10 @@
 	if (!sti->sti_mem_request)
 		sti->sti_mem_request = 256; /* STI default */
 
-	glob_cfg = kmalloc(sizeof(*sti->glob_cfg), GFP_KERNEL);
-	glob_cfg_ext = kmalloc(sizeof(*glob_cfg_ext), GFP_KERNEL);
-	save_addr = kmalloc(save_addr_size, GFP_KERNEL);
-	sti_mem_addr = kmalloc(sti->sti_mem_request, GFP_KERNEL);
+	glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL);
+	glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL);
+	save_addr = kzalloc(save_addr_size, GFP_KERNEL);
+	sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL);
 
 	if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) {
 		kfree(glob_cfg);
@@ -427,11 +428,6 @@
 		return -ENOMEM;
 	}
 
-	memset(glob_cfg, 0, sizeof(*glob_cfg));
-	memset(glob_cfg_ext, 0, sizeof(*glob_cfg_ext));
-	memset(save_addr, 0, save_addr_size);
-	memset(sti_mem_addr, 0, sti->sti_mem_request);
-
 	glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
 	glob_cfg->save_addr = STI_PTR(save_addr);
 	for (i=0; i<8; i++) {
@@ -502,9 +498,9 @@
 
 #ifdef CONFIG_FB
 struct sti_cooked_font * __init
-sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
+sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
 {
-	struct font_desc *fbfont;
+	const struct font_desc *fbfont;
 	unsigned int size, bpc;
 	void *dest;
 	struct sti_rom_font *nf;
@@ -525,10 +521,9 @@
 	size = bpc * 256;
 	size += sizeof(struct sti_rom_font);
 
-	nf = kmalloc(size, GFP_KERNEL);
+	nf = kzalloc(size, GFP_KERNEL);
 	if (!nf)
 		return NULL;
-	memset(nf, 0, size);
 
 	nf->first_char = 0;
 	nf->last_char = 255;
@@ -544,7 +539,7 @@
 	dest += sizeof(struct sti_rom_font);
 	memcpy(dest, fbfont->data, bpc*256);
 
-	cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+	cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
 	if (!cooked_font) {
 		kfree(nf);
 		return NULL;
@@ -559,7 +554,7 @@
 }
 #else
 struct sti_cooked_font * __init
-sti_select_fbfont(struct sti_cooked_rom *cooked_rom, char *fbfont_name)
+sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
 {
 	return NULL;
 }
@@ -617,7 +612,7 @@
 	struct sti_rom_font *raw_font, *font_start;
 	struct sti_cooked_font *cooked_font;
 	
-	cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+	cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
 	if (!cooked_font)
 		return 0;
 
@@ -631,7 +626,7 @@
 	while (raw_font->next_font) {
 		raw_font = ((void *)font_start) + (raw_font->next_font);
 
-		cooked_font->next_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+		cooked_font->next_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
 		if (!cooked_font->next_font)
 			return 1;
 
@@ -668,10 +663,9 @@
 	unsigned char *n, *p, *q;
 	int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font);
 	
-	n = kmalloc (4*size, GFP_KERNEL);
+	n = kzalloc (4*size, GFP_KERNEL);
 	if (!n)
 		return NULL;
-	memset (n, 0, 4*size);
 	p = n + 3;
 	q = (unsigned char *)f->raw;
 	while (size--) {
@@ -816,13 +810,12 @@
 		return NULL;
 	}
 	
-	sti = kmalloc(sizeof(*sti), GFP_KERNEL);
+	sti = kzalloc(sizeof(*sti), GFP_KERNEL);
 	if (!sti) {
 		printk(KERN_ERR "Not enough memory !\n");
 		return NULL;
 	}
 
-	memset(sti, 0, sizeof(*sti));
 	spin_lock_init(&sti->lock);
 
 test_rom:
@@ -1035,7 +1028,7 @@
  * sti_init_roms() - detects all STI ROMs and stores them in sti_roms[]
  */
 
-static int sticore_initialized;
+static int sticore_initialized __read_mostly;
 
 static void __init sti_init_roms(void)
 {
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 2b97246..0ae0a97 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -1665,7 +1665,6 @@
 		}
 #endif
 	output("CyblaFB version %s initializing\n", VERSION);
-	return pci_module_init(&cyblafb_pci_driver);
 	return pci_register_driver(&cyblafb_pci_driver);
 }
 
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index d2dede6..996c7b5 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1550,6 +1550,7 @@
 	return retval;
 }
 
+#ifndef MODULE
 /**
  *	video_setup - process command line options
  *	@options: string of options
@@ -1593,6 +1594,7 @@
 	return 0;
 }
 __setup("video=", video_setup);
+#endif
 
     /*
      *  Visible symbols for modules
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index bd410e0..e3c8b5f 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -191,11 +191,11 @@
         u8 *edid = NULL;
         int i;
 
-	DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn);
-	if (conn < 4) {
+	DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1);
+	if (conn < par->ddc_num) {
 		for (i = 0; i < 3; i++) {
 			/* Do the real work */
-			edid = i810_do_probe_i2c_edid(&par->chan[conn-1]);
+			edid = i810_do_probe_i2c_edid(&par->chan[conn]);
 			if (edid)
 				break;
 		}
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index 6c187d5..579195c 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -280,6 +280,7 @@
 	u32 blit_bpp;
 	u32 ovract;
 	u32 cur_state;
+	u32 ddc_num;
 	int mtrr_reg;
 	u16 bltcntl;
 	u8 interlace;
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 266d0ab..d8467c0 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -149,6 +149,7 @@
 static int sync       __devinitdata;
 static int extvga     __devinitdata;
 static int dcolor     __devinitdata;
+static int ddc3       __devinitdata = 2;
 
 /*------------------------------------------------------------*/
 
@@ -1763,6 +1764,8 @@
 	if (sync) 
 		par->dev_flags |= ALWAYS_SYNC;
 
+	par->ddc_num = ddc3;
+
 	if (bpp < 8)
 		bpp = 8;
 	
@@ -1885,7 +1888,7 @@
 	int found = 0;
 #ifdef CONFIG_FB_I810_I2C
 	int i;
-	int err;
+	int err = 1;
 	struct i810fb_par *par = info->par;
 #endif
 
@@ -1895,8 +1898,8 @@
 #ifdef CONFIG_FB_I810_I2C
 	i810_create_i2c_busses(par);
 
-	for (i = 0; i < 4; i++) {
-		err = i810_probe_i2c_connector(info, &par->edid, i+1);
+	for (i = 0; i < par->ddc_num + 1; i++) {
+		err = i810_probe_i2c_connector(info, &par->edid, i);
 		if (!err)
 			break;
 	}
@@ -1983,6 +1986,8 @@
 			vsync2 = simple_strtoul(this_opt+7, NULL, 0);
 		else if (!strncmp(this_opt, "dcolor", 6))
 			dcolor = 1;
+		else if (!strncmp(this_opt, "ddc3", 4))
+			ddc3 = 3;
 		else
 			mode_option = this_opt;
 	}
@@ -2190,6 +2195,8 @@
 module_param(dcolor, bool, 0);
 MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
 		 " (default = 0 = TrueColor)");
+module_param(ddc3, bool, 0);
+MODULE_PARM_DESC(ddc3, "Probe DDC bus 3 (default = 0 = no)");
 module_param(mode_option, charp, 0);
 MODULE_PARM_DESC(mode_option, "Specify initial video mode");
 
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index dbcb896..a7c4e5e 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -138,6 +138,8 @@
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index f3927b6..f5361cd 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 
-#include <asm/bug.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 25148de..eeeac92 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 
-#include <asm/bug.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index 3d02308..2f4ce43 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -8,6 +8,7 @@
 	conv.o \
 	vfs_super.o \
 	vfs_inode.o \
+	vfs_addr.o \
 	vfs_file.o \
 	vfs_dir.o \
 	vfs_dentry.o \
diff --git a/fs/9p/conv.c b/fs/9p/conv.c
index 32a9f99..bf1f100 100644
--- a/fs/9p/conv.c
+++ b/fs/9p/conv.c
@@ -116,13 +116,19 @@
 	}
 }
 
-static void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
+static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
 {
+	char *ret;
+
+	ret = NULL;
 	if (buf_check_size(buf, slen + 2)) {
 		buf_put_int16(buf, slen);
+		ret = buf->p;
 		memcpy(buf->p, s, slen);
 		buf->p += slen;
 	}
+
+	return ret;
 }
 
 static inline void buf_put_string(struct cbuf *buf, const char *s)
@@ -430,15 +436,19 @@
 static void
 v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
 {
-	if (data) {
-		str->len = strlen(data);
-		str->str = bufp->p;
-	} else {
-		str->len = 0;
-		str->str = NULL;
-	}
+	int len;
+	char *s;
 
-	buf_put_stringn(bufp, data, str->len);
+	if (data)
+		len = strlen(data);
+	else
+		len = 0;
+
+	s = buf_put_stringn(bufp, data, len);
+	if (str) {
+		str->len = len;
+		str->str = s;
+	}
 }
 
 static int
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index 945cb36..ea1134e 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -471,10 +471,13 @@
 		}
 
 		spin_lock(&m->lock);
-		req =
-		    list_entry(m->unsent_req_list.next, struct v9fs_req,
+again:
+		req = list_entry(m->unsent_req_list.next, struct v9fs_req,
 			       req_list);
 		list_move_tail(&req->req_list, &m->req_list);
+		if (req->err == ERREQFLUSH)
+			goto again;
+
 		m->wbuf = req->tcall->sdata;
 		m->wsize = req->tcall->size;
 		m->wpos = 0;
@@ -525,7 +528,7 @@
 	struct v9fs_str *ename;
 
 	tag = req->tag;
-	if (req->rcall->id == RERROR && !req->err) {
+	if (!req->err && req->rcall->id == RERROR) {
 		ecode = req->rcall->params.rerror.errno;
 		ename = &req->rcall->params.rerror.error;
 
@@ -551,7 +554,10 @@
 			req->err = -EIO;
 	}
 
-	if (req->cb && req->err != ERREQFLUSH) {
+	if (req->err == ERREQFLUSH)
+		return;
+
+	if (req->cb) {
 		dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n",
 			req->tcall, req->rcall);
 
@@ -812,6 +818,7 @@
 	struct v9fs_mux_rpc *r;
 
 	if (err == ERREQFLUSH) {
+		kfree(rc);
 		dprintk(DEBUG_MUX, "err req flush\n");
 		return;
 	}
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index c78502a..69cf290 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -39,6 +39,7 @@
  */
 
 extern struct file_system_type v9fs_fs_type;
+extern struct address_space_operations v9fs_addr_operations;
 extern struct file_operations v9fs_file_operations;
 extern struct file_operations v9fs_dir_operations;
 extern struct dentry_operations v9fs_dentry_operations;
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
new file mode 100644
index 0000000..8100fb5
--- /dev/null
+++ b/fs/9p/vfs_addr.c
@@ -0,0 +1,109 @@
+/*
+ *  linux/fs/9p/vfs_addr.c
+ *
+ * This file contians vfs address (mmap) ops for 9P2000.
+ *
+ *  Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU 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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/version.h>
+#include <linux/pagemap.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "fid.h"
+
+/**
+ * v9fs_vfs_readpage - read an entire page in from 9P
+ *
+ * @file: file being read
+ * @page: structure to page
+ *
+ */
+
+static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+{
+	char *buffer = NULL;
+	int retval = -EIO;
+	loff_t offset = page_offset(page);
+	int count = PAGE_CACHE_SIZE;
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+	int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
+	struct v9fs_fid *v9f = filp->private_data;
+	struct v9fs_fcall *fcall = NULL;
+	int fid = v9f->fid;
+	int total = 0;
+	int result = 0;
+
+	buffer = kmap(page);
+	do {
+		if (count < rsize)
+			rsize = count;
+
+		result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall);
+
+		if (result < 0) {
+			printk(KERN_ERR "v9fs_t_read returned %d\n",
+			       result);
+
+			kfree(fcall);
+			goto UnmapAndUnlock;
+		} else
+			offset += result;
+
+		memcpy(buffer, fcall->params.rread.data, result);
+
+		count -= result;
+		buffer += result;
+		total += result;
+
+		kfree(fcall);
+
+		if (result < rsize)
+			break;
+	} while (count);
+
+	memset(buffer, 0, count);
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	retval = 0;
+
+UnmapAndUnlock:
+	kunmap(page);
+	unlock_page(page);
+	return retval;
+}
+
+struct address_space_operations v9fs_addr_operations = {
+      .readpage = v9fs_vfs_readpage,
+};
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 6852f0e..c7e14d9 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -289,6 +289,9 @@
 		total += result;
 	} while (count);
 
+	if(inode->i_mapping->nrpages)
+		invalidate_inode_pages2(inode->i_mapping);
+
 	return total;
 }
 
@@ -299,4 +302,5 @@
 	.open = v9fs_file_open,
 	.release = v9fs_dir_release,
 	.lock = v9fs_file_lock,
+	.mmap = generic_file_mmap,
 };
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index a17b288..63e5b03 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -177,6 +177,7 @@
 		inode->i_blocks = 0;
 		inode->i_rdev = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		inode->i_mapping->a_ops = &v9fs_addr_operations;
 
 		switch (mode & S_IFMT) {
 		case S_IFIFO:
@@ -885,8 +886,8 @@
 	}
 
 	/* copy extension buffer into buffer */
-	if (fcall->params.rstat.stat.extension.len < buflen)
-		buflen = fcall->params.rstat.stat.extension.len;
+	if (fcall->params.rstat.stat.extension.len+1 < buflen)
+		buflen = fcall->params.rstat.stat.extension.len + 1;
 
 	memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
 	buffer[buflen-1] = 0;
@@ -950,7 +951,7 @@
 	if (!link)
 		link = ERR_PTR(-ENOMEM);
 	else {
-		len = v9fs_readlink(dentry, link, strlen(link));
+		len = v9fs_readlink(dentry, link, PATH_MAX);
 
 		if (len < 0) {
 			__putname(link);
diff --git a/fs/Kconfig b/fs/Kconfig
index ef78e3a..e9749b0 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -883,8 +883,6 @@
 	  Both sysfs and configfs can and should exist together on the
 	  same system. One is not a replacement for the other.
 
-	  If unsure, say N.
-
 endmenu
 
 menu "Miscellaneous filesystems"
@@ -1327,7 +1325,7 @@
 
 config UFS_FS_WRITE
 	bool "UFS file system write support (DANGEROUS)"
-	depends on UFS_FS && EXPERIMENTAL
+	depends on UFS_FS && EXPERIMENTAL && BROKEN
 	help
 	  Say Y here if you want to try writing to UFS partitions. This is
 	  experimental, so you should back up your UFS partitions beforehand.
diff --git a/fs/bio.c b/fs/bio.c
index bbc442b..1f3bb50 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -411,6 +411,7 @@
 
 /**
  *	bio_add_pc_page	-	attempt to add page to bio
+ *	@q: the target queue
  *	@bio: destination bio
  *	@page: page to add
  *	@len: vec entry length
diff --git a/fs/buffer.c b/fs/buffer.c
index 3dc712f..62cfd17 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1022,6 +1022,7 @@
 
 		bh->b_state = 0;
 		atomic_set(&bh->b_count, 0);
+		bh->b_private = NULL;
 		bh->b_size = size;
 
 		/* Link the buffer to its page */
@@ -2866,22 +2867,22 @@
 		else if (test_set_buffer_locked(bh))
 			continue;
 
-		get_bh(bh);
 		if (rw == WRITE || rw == SWRITE) {
 			if (test_clear_buffer_dirty(bh)) {
 				bh->b_end_io = end_buffer_write_sync;
+				get_bh(bh);
 				submit_bh(WRITE, bh);
 				continue;
 			}
 		} else {
 			if (!buffer_uptodate(bh)) {
 				bh->b_end_io = end_buffer_read_sync;
+				get_bh(bh);
 				submit_bh(rw, bh);
 				continue;
 			}
 		}
 		unlock_buffer(bh);
-		put_bh(bh);
 	}
 }
 
@@ -3050,6 +3051,66 @@
 }
 
 /*
+ * Migration function for pages with buffers. This function can only be used
+ * if the underlying filesystem guarantees that no other references to "page"
+ * exist.
+ */
+#ifdef CONFIG_MIGRATION
+int buffer_migrate_page(struct page *newpage, struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+	struct buffer_head *bh, *head;
+
+	if (!mapping)
+		return -EAGAIN;
+
+	if (!page_has_buffers(page))
+		return migrate_page(newpage, page);
+
+	head = page_buffers(page);
+
+	if (migrate_page_remove_references(newpage, page, 3))
+		return -EAGAIN;
+
+	bh = head;
+	do {
+		get_bh(bh);
+		lock_buffer(bh);
+		bh = bh->b_this_page;
+
+	} while (bh != head);
+
+	ClearPagePrivate(page);
+	set_page_private(newpage, page_private(page));
+	set_page_private(page, 0);
+	put_page(page);
+	get_page(newpage);
+
+	bh = head;
+	do {
+		set_bh_page(bh, newpage, bh_offset(bh));
+		bh = bh->b_this_page;
+
+	} while (bh != head);
+
+	SetPagePrivate(newpage);
+
+	migrate_page_copy(newpage, page);
+
+	bh = head;
+	do {
+		unlock_buffer(bh);
+ 		put_bh(bh);
+		bh = bh->b_this_page;
+
+	} while (bh != head);
+
+	return 0;
+}
+EXPORT_SYMBOL(buffer_migrate_page);
+#endif
+
+/*
  * Buffer-head allocation
  */
 static kmem_cache_t *bh_cachep;
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 943ef9b..d335015 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,11 @@
+Version 1.40
+------------
+Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
+of readpages by eliminating one extra memcpy. Allow update of file size
+from remote server even if file is open for write as long as mount is
+directio.  Recognize share mode security and send NTLM encrypted password
+on tree connect if share mode negotiated.
+
 Version 1.39
 ------------
 Defer close of a file handle slightly if pending writes depend on that handle
@@ -7,6 +15,8 @@
 CIFS Unix Extensions.  Fix setfacl/getfacl on bigendian. Timeout negative
 dentries so files that the client sees as deleted but that later get created
 on the server will be recognized.  Add client side permission check on setattr.
+Timeout stuck requests better (where server has never responded or sent corrupt
+responses)
 
 Version 1.38
 ------------
diff --git a/fs/cifs/README b/fs/cifs/README
index e5d09a2..b0070d1 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -436,7 +436,17 @@
 		SFU does).  In the future the bottom 9 bits of the mode
 		mode also will be emulated using queries of the security
 		descriptor (ACL).
-		
+sec		Security mode.  Allowed values are:
+			none	attempt to connection as a null user (no name)
+			krb5    Use Kerberos version 5 authentication
+			krb5i   Use Kerberos authentication and packet signing
+			ntlm    Use NTLM password hashing (default)
+			ntlmi   Use NTLM password hashing with signing (if
+				/proc/fs/cifs/PacketSigningEnabled on or if
+				server requires signing also can be the default) 
+			ntlmv2  Use NTLMv2 password hashing      
+			ntlmv2i Use NTLMv2 password hashing with packet signing
+
 The mount.cifs mount helper also accepts a few mount options before -o
 including:
 
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 22a444a..f4124a3 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -219,6 +219,10 @@
 
         if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
 		read_lock(&GlobalSMBSeslock);
+#ifdef CONFIG_CIFS_STATS2
+		atomic_set(&totBufAllocCount, 0);
+		atomic_set(&totSmBufAllocCount, 0);
+#endif /* CONFIG_CIFS_STATS2 */
 		list_for_each(tmp, &GlobalTreeConnectionList) {
 			tcon = list_entry(tmp, struct cifsTconInfo,
 					cifsConnectionList);
@@ -276,6 +280,14 @@
 			smBufAllocCount.counter,cifs_min_small);
 	length += item_length;
 	buf += item_length;
+#ifdef CONFIG_CIFS_STATS2
+        item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
+				atomic_read(&totBufAllocCount),
+		                atomic_read(&totSmBufAllocCount));
+	length += item_length;
+	buf += item_length;
+#endif /* CONFIG_CIFS_STATS2 */
+
 	item_length = 
 		sprintf(buf,"Operations (MIDs): %d\n",
 			midCount.counter);
@@ -389,8 +401,8 @@
 static write_proc_t ntlmv2_enabled_write;
 static read_proc_t packet_signing_enabled_read;
 static write_proc_t packet_signing_enabled_write;
-static read_proc_t quotaEnabled_read;
-static write_proc_t quotaEnabled_write;
+static read_proc_t experimEnabled_read;
+static write_proc_t experimEnabled_write;
 static read_proc_t linuxExtensionsEnabled_read;
 static write_proc_t linuxExtensionsEnabled_write;
 
@@ -430,9 +442,9 @@
 		pde->write_proc = oplockEnabled_write;
 
 	pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
-				quotaEnabled_read, NULL);
+				experimEnabled_read, NULL);
 	if (pde)
-		pde->write_proc = quotaEnabled_write;
+		pde->write_proc = experimEnabled_write;
 
 	pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
 				linuxExtensionsEnabled_read, NULL);
@@ -574,14 +586,13 @@
 }
 
 static int
-quotaEnabled_read(char *page, char **start, off_t off,
+experimEnabled_read(char *page, char **start, off_t off,
                    int count, int *eof, void *data)
 {
         int len;
 
         len = sprintf(page, "%d\n", experimEnabled);
-/* could also check if quotas are enabled in kernel
-	as a whole first */
+
         len -= off;
         *start = page + off;
 
@@ -596,21 +607,23 @@
         return len;
 }
 static int
-quotaEnabled_write(struct file *file, const char __user *buffer,
+experimEnabled_write(struct file *file, const char __user *buffer,
                     unsigned long count, void *data)
 {
-        char c;
-        int rc;
+	char c;
+	int rc;
 
-        rc = get_user(c, buffer);
-        if (rc)
-                return rc;
-        if (c == '0' || c == 'n' || c == 'N')
-                experimEnabled = 0;
-        else if (c == '1' || c == 'y' || c == 'Y')
-                experimEnabled = 1;
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		experimEnabled = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		experimEnabled = 1;
+	else if (c == '2')
+		experimEnabled = 2;
 
-        return count;
+	return count;
 }
 
 static int
@@ -620,8 +633,6 @@
         int len;
 
         len = sprintf(page, "%d\n", linuxExtEnabled);
-/* could also check if quotas are enabled in kernel
-	as a whole first */
         len -= off;
         *start = page + off;
 
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index f799f6f..ad58eb0 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -24,9 +24,10 @@
 #define CIFS_MOUNT_DIRECT_IO    8 /* do not write nor read through page cache */
 #define CIFS_MOUNT_NO_XATTR  0x10 /* if set - disable xattr support */
 #define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
-#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
-#define CIFS_MOUNT_UNX_EMUL    0x80 /* Network compat with SFUnix emulation */
+#define CIFS_MOUNT_POSIX_PATHS	0x40 /* Negotiate posix pathnames if possible. */
+#define CIFS_MOUNT_UNX_EMUL	0x80 /* Network compat with SFUnix emulation */
 #define CIFS_MOUNT_NO_BRL	0x100 /* No sending byte range locks to srv */
+#define CIFS_MOUNT_CIFS_ACL	0x200 /* send ACL requests to non-POSIX srv */
 
 struct cifs_sb_info {
 	struct cifsTconInfo *tcon;	/* primary mount */
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
new file mode 100644
index 0000000..d0776ac
--- /dev/null
+++ b/fs/cifs/cifsacl.h
@@ -0,0 +1,38 @@
+/*
+ *   fs/cifs/cifsacl.h
+ *
+ *   Copyright (c) International Business Machines  Corp., 2005
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _CIFSACL_H
+#define _CIFSACL_H
+
+struct cifs_sid {
+	__u8 revision; /* revision level */
+	__u8 num_subauths;
+	__u8 authority[6];
+	__u32 sub_auth[4];
+	/* next sub_auth if any ... */
+} __attribute__((packed));
+
+/* everyone */
+extern const struct cifs_sid sid_everyone;
+/* group users */
+extern const struct cifs_sid sid_user;
+
+#endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index fe2bb7c..a2c2485 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsencrypt.c
  *
- *   Copyright (C) International Business Machines  Corp., 2003
+ *   Copyright (C) International Business Machines  Corp., 2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -82,6 +82,59 @@
 	return rc;
 }
 
+static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
+				const char * key, char * signature)
+{
+        struct  MD5Context context;
+
+        if((iov == NULL) || (signature == NULL))
+                return -EINVAL;
+
+        MD5Init(&context);
+        MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+
+/*        MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
+
+        MD5Final(signature,&context);
+
+	return -EOPNOTSUPP;
+/*        return 0; */
+}
+
+
+int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
+		   __u32 * pexpected_response_sequence_number)
+{
+	int rc = 0;
+	char smb_signature[20];
+	struct smb_hdr * cifs_pdu = iov[0].iov_base;
+
+	if((cifs_pdu == NULL) || (server == NULL))
+		return -EINVAL;
+
+	if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
+		return rc;
+
+        spin_lock(&GlobalMid_Lock);
+        cifs_pdu->Signature.Sequence.SequenceNumber = 
+				cpu_to_le32(server->sequence_number);
+        cifs_pdu->Signature.Sequence.Reserved = 0;
+
+        *pexpected_response_sequence_number = server->sequence_number++;
+        server->sequence_number++;
+        spin_unlock(&GlobalMid_Lock);
+
+        rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key,
+				      smb_signature);
+        if(rc)
+                memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
+        else
+                memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
+
+        return rc;
+
+}
+
 int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
 	__u32 expected_sequence_number)
 {
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index e10213b..79eeccd 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -513,6 +513,17 @@
 	return written;
 }
 
+static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
+{
+	/* origin == SEEK_END => we must revalidate the cached file length */
+	if (origin == 2) {
+		int retval = cifs_revalidate(file->f_dentry);
+		if (retval < 0)
+			return (loff_t)retval;
+	}
+	return remote_llseek(file, offset, origin);
+}
+
 static struct file_system_type cifs_fs_type = {
 	.owner = THIS_MODULE,
 	.name = "cifs",
@@ -586,6 +597,7 @@
 	.flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
 	.sendfile = generic_file_sendfile,
+	.llseek = cifs_llseek,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl	= cifs_ioctl,
 #endif /* CONFIG_CIFS_POSIX */
@@ -609,7 +621,7 @@
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl  = cifs_ioctl,
 #endif /* CONFIG_CIFS_POSIX */
-
+	.llseek = cifs_llseek,
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 	.dir_notify = cifs_dir_notify,
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -627,6 +639,7 @@
 	.flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
 	.sendfile = generic_file_sendfile,
+	.llseek = cifs_llseek,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl	= cifs_ioctl,
 #endif /* CONFIG_CIFS_POSIX */
@@ -649,7 +662,7 @@
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl  = cifs_ioctl,
 #endif /* CONFIG_CIFS_POSIX */
-
+	.llseek = cifs_llseek,
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 	.dir_notify = cifs_dir_notify,
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -733,7 +746,7 @@
 		kmem_cache_destroy(cifs_req_cachep);
 		return -ENOMEM;
 	}
-	/* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and
+	/* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
 	almost all handle based requests (but not write response, nor is it
 	sufficient for path based requests).  A smaller size would have
 	been more efficient (compacting multiple slab items on one 4k page) 
@@ -742,7 +755,8 @@
 	efficient to alloc 1 per page off the slab compared to 17K (5page) 
 	alloc of large cifs buffers even when page debugging is on */
 	cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
-			MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+			MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN, 
+			NULL, NULL);
 	if (cifs_sm_req_cachep == NULL) {
 		mempool_destroy(cifs_req_poolp);
 		kmem_cache_destroy(cifs_req_cachep);
@@ -954,6 +968,12 @@
 	atomic_set(&tconInfoReconnectCount, 0);
 
 	atomic_set(&bufAllocCount, 0);
+	atomic_set(&smBufAllocCount, 0);
+#ifdef CONFIG_CIFS_STATS2
+	atomic_set(&totBufAllocCount, 0);
+	atomic_set(&totSmBufAllocCount, 0);
+#endif /* CONFIG_CIFS_STATS2 */
+
 	atomic_set(&midCount, 0);
 	GlobalCurrentXid = 0;
 	GlobalTotalActiveXid = 0;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 9ec40e0..821a8eb 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -99,5 +99,5 @@
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
 		       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.39"
+#define CIFS_VERSION   "1.40"
 #endif				/* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1ba08f8..7bed276 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -233,6 +233,8 @@
 	atomic_t num_hardlinks;
 	atomic_t num_symlinks;
 	atomic_t num_locks;
+	atomic_t num_acl_get;
+	atomic_t num_acl_set;
 #ifdef CONFIG_CIFS_STATS2
 	unsigned long long time_writes;
 	unsigned long long time_reads;
@@ -285,6 +287,7 @@
 	unsigned endOfSearch:1;
 	unsigned emptyDir:1;
 	unsigned unicode:1;
+	unsigned smallBuf:1; /* so we know which buf_release function to call */
 };
 
 struct cifsFileInfo {
@@ -420,7 +423,12 @@
 #define   MID_RESPONSE_RECEIVED 4
 #define   MID_RETRY_NEEDED      8 /* session closed while this request out */
 #define   MID_NO_RESP_NEEDED 0x10
-#define   MID_SMALL_BUFFER   0x20 /* 112 byte response buffer instead of 4K */
+
+/* Types of response buffer returned from SendReceive2 */
+#define   CIFS_NO_BUFFER        0    /* Response buffer not returned */
+#define   CIFS_SMALL_BUFFER     1
+#define   CIFS_LARGE_BUFFER     2
+#define   CIFS_IOVEC            4    /* array of response buffers */
 
 /*
  *****************************************************************
@@ -505,8 +513,12 @@
 GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
 
 /* Various Debug counters to remove someday (BB) */
-GLOBAL_EXTERN atomic_t bufAllocCount;
-GLOBAL_EXTERN atomic_t smBufAllocCount;      
+GLOBAL_EXTERN atomic_t bufAllocCount;    /* current number allocated  */
+#ifdef CONFIG_CIFS_STATS2
+GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */
+GLOBAL_EXTERN atomic_t totSmBufAllocCount;
+#endif
+GLOBAL_EXTERN atomic_t smBufAllocCount;
 GLOBAL_EXTERN atomic_t midCount;
 
 /* Misc globals */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 33e1859..cc24710 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifspdu.h
  *
- *   Copyright (c) International Business Machines  Corp., 2002
+ *   Copyright (c) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -80,7 +80,11 @@
 #define NT_TRANSACT_GET_USER_QUOTA    0x07
 #define NT_TRANSACT_SET_USER_QUOTA    0x08
 
-#define MAX_CIFS_HDR_SIZE 256	/* is future chained NTCreateXReadX bigger? */
+#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
+/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
+/* among the requests (NTCreateX response is bigger with wct of 34) */
+#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
+#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */
 
 /* internal cifs vfs structures */
 /*****************************************************************
@@ -524,7 +528,7 @@
 		/* STRING PrimaryDomain */
 		/* STRING NativeOS */
 		/* STRING NativeLanMan */
-	} __attribute__((packed)) old_req;		/* pre-NTLM (LANMAN2.1) request format */
+	} __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) req format */
 
 	struct {		/* default (NTLM) response format */
 		struct smb_hdr hdr;	/* wct = 3 */
@@ -536,7 +540,7 @@
 		unsigned char NativeOS[1];	/* followed by */
 /*	unsigned char * NativeLanMan; */
 /*      unsigned char * PrimaryDomain; */
-	} __attribute__((packed)) old_resp;		/* pre-NTLM (LANMAN2.1) response format */
+	} __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */
 } __attribute__((packed)) SESSION_SETUP_ANDX;
 
 #define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
@@ -1003,10 +1007,49 @@
 
 /* empty wct response to setattr */
 
-/***************************************************/
-/* NT Transact structure defintions follow         */
-/* Currently only ioctl and notify are implemented */
-/***************************************************/
+/*******************************************************/
+/* NT Transact structure defintions follow             */
+/* Currently only ioctl, acl (get security descriptor) */  
+/* and notify are implemented                          */
+/*******************************************************/
+typedef struct smb_com_ntransact_req {
+        struct smb_hdr hdr; /* wct >= 19 */
+        __u8 MaxSetupCount;
+        __u16 Reserved;
+        __le32 TotalParameterCount;
+        __le32 TotalDataCount;
+        __le32 MaxParameterCount;
+        __le32 MaxDataCount;
+        __le32 ParameterCount;
+        __le32 ParameterOffset;
+        __le32 DataCount;
+        __le32 DataOffset;
+        __u8 SetupCount; /* four setup words follow subcommand */
+        /* SNIA spec incorrectly included spurious pad here */
+        __le16 SubCommand; /* 2 = IOCTL/FSCTL */
+	/* SetupCount words follow then */ 
+        __le16 ByteCount;
+        __u8 Pad[3];
+        __u8 Parms[0];
+} __attribute__((packed)) NTRANSACT_REQ;
+
+typedef struct smb_com_ntransact_rsp {
+	struct smb_hdr hdr;     /* wct = 18 */
+	__u8 Reserved[3];
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 ParameterDisplacement;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__le32 DataDisplacement;
+	__u8 SetupCount;   /* 0 */
+	__u16 ByteCount;
+        /* __u8 Pad[3]; */
+	/* parms and data follow */
+} __attribute__((packed)) NTRANSACT_RSP;
+
 typedef struct smb_com_transaction_ioctl_req {
 	struct smb_hdr hdr;	/* wct = 23 */
 	__u8 MaxSetupCount;
@@ -1021,11 +1064,11 @@
 	__le32 DataOffset;
 	__u8 SetupCount; /* four setup words follow subcommand */
 	/* SNIA spec incorrectly included spurious pad here */
-	__le16 SubCommand;/* 2 = IOCTL/FSCTL */
+	__le16 SubCommand; /* 2 = IOCTL/FSCTL */
 	__le32 FunctionCode;
 	__u16 Fid;
-	__u8 IsFsctl;    /* 1 = File System Control, 0 = device control (IOCTL)*/
-	__u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
+	__u8 IsFsctl;  /* 1 = File System Control 0 = device control (IOCTL) */
+	__u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
 	__le16 ByteCount;
 	__u8 Pad[3];
 	__u8 Data[1];
@@ -1045,9 +1088,35 @@
 	__u8 SetupCount;	/* 1 */
 	__le16 ReturnedDataLen;
 	__u16 ByteCount;
-	__u8 Pad[3];
 } __attribute__((packed)) TRANSACT_IOCTL_RSP;
 
+#define CIFS_ACL_OWNER 1
+#define CIFS_ACL_GROUP 2
+#define CIFS_ACL_DACL  4
+#define CIFS_ACL_SACL  8
+
+typedef struct smb_com_transaction_qsec_req {
+	struct smb_hdr hdr;     /* wct = 19 */
+	__u8 MaxSetupCount;
+	__u16 Reserved;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 MaxParameterCount;
+	__le32 MaxDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__u8 SetupCount; /* no setup words follow subcommand */
+	/* SNIA spec incorrectly included spurious pad here */
+	__le16 SubCommand; /* 6 = QUERY_SECURITY_DESC */
+	__le16 ByteCount; /* bcc = 3 + 8 */
+	__u8 Pad[3];
+	__u16 Fid;
+	__u16 Reserved2;
+	__le32 AclFlags;
+} __attribute__((packed)) QUERY_SEC_DESC_REQ;
+
 typedef struct smb_com_transaction_change_notify_req {
 	struct smb_hdr hdr;     /* wct = 23 */
 	__u8 MaxSetupCount;
@@ -1068,10 +1137,12 @@
 	__u8 WatchTree;  /* 1 = Monitor subdirectories */
 	__u8 Reserved2;
 	__le16 ByteCount;
-/* __u8 Pad[3];*/
+/* 	__u8 Pad[3];*/
 /*	__u8 Data[1];*/
 } __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
 
+/* BB eventually change to use generic ntransact rsp struct 
+      and validation routine */
 typedef struct smb_com_transaction_change_notify_rsp {
 	struct smb_hdr hdr;	/* wct = 18 */
 	__u8 Reserved[3];
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1b73f4f..3c03aad 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -48,8 +48,8 @@
 			struct smb_hdr * /* out */ ,
 			int * /* bytes returned */ , const int long_op);
 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
-			struct kvec *, int /* nvec */,
-			int * /* bytes returned */ , const int long_op);
+			struct kvec *, int /* nvec to send */, 
+			int * /* type of buf returned */ , const int long_op);
 extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
 extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
 extern int is_valid_oplock_break(struct smb_hdr *smb);
@@ -93,11 +93,12 @@
 			const struct nls_table *);
 
 extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
-            const char *searchName, const struct nls_table *nls_codepage,
-            __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
+		const char *searchName, const struct nls_table *nls_codepage,
+		__u16 *searchHandle, struct cifs_search_info * psrch_inf, 
+		int map, const char dirsep);
 
 extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
-            __u16 searchHandle, struct cifs_search_info * psrch_inf);
+		__u16 searchHandle, struct cifs_search_info * psrch_inf);
 
 extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
 			const __u16 search_handle);
@@ -230,19 +231,18 @@
 			const int smb_file_id);
 
 extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
-			const int netfid, unsigned int count,
-			const __u64 lseek, unsigned int *nbytes, char **buf);
+                        const int netfid, unsigned int count,
+                        const __u64 lseek, unsigned int *nbytes, char **buf,
+			int * return_buf_type);
 extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
 			const int netfid, const unsigned int count,
 			const __u64 lseek, unsigned int *nbytes,
 			const char *buf, const char __user *ubuf, 
 			const int long_op);
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
 			const int netfid, const unsigned int count,
 			const __u64 offset, unsigned int *nbytes, 
 			struct kvec *iov, const int nvec, const int long_op);
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
 extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
 			const unsigned char *searchName, __u64 * inode_number,
 			const struct nls_table *nls_codepage, 
@@ -269,6 +269,8 @@
 extern int cifs_reconnect(struct TCP_Server_Info *server);
 
 extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
+extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
+			  __u32 *);
 extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
 	__u32 expected_sequence_number);
 extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
@@ -297,6 +299,9 @@
 		const char *fileName, const char * ea_name, 
 		const void * ea_value, const __u16 ea_value_len, 
 		const struct nls_table *nls_codepage, int remap_special_chars);
+extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
+			__u16 fid, char *acl_inf, const int buflen,
+			const int acl_type /* ACCESS vs. DEFAULT */);
 extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
 		const unsigned char *searchName,
 		char *acl_inf, const int buflen,const int acl_type,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6867e55..217323b 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -37,6 +37,7 @@
 #include "cifsproto.h"
 #include "cifs_unicode.h"
 #include "cifs_debug.h"
+#include "cifsacl.h"
 
 #ifdef CONFIG_CIFS_POSIX
 static struct {
@@ -372,8 +373,10 @@
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc == 0) {
-		server->secMode = pSMBr->SecurityMode;	
-		server->secType = NTLM; /* BB override default for 
+		server->secMode = pSMBr->SecurityMode;
+		if((server->secMode & SECMODE_USER) == 0)
+			cFYI(1,("share mode security"));
+		server->secType = NTLM; /* BB override default for
 					   NTLMv2 or kerberos v5 */
 		/* one byte - no need to convert this or EncryptionKeyLen
 		   from little endian */
@@ -383,7 +386,7 @@
 			min(le32_to_cpu(pSMBr->MaxBufferSize),
 			(__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
 		server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
-		cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
+		cFYI(0, ("Max buf = %d", ses->server->maxBuf));
 		GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
 		server->capabilities = le32_to_cpu(pSMBr->Capabilities);
 		server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);	
@@ -411,8 +414,7 @@
 						(server->server_GUID,
 						pSMBr->u.extended_response.
 						GUID, 16) != 0) {
-						cFYI(1,
-						     ("UID of server does not match previous connection to same ip address"));
+						cFYI(1, ("server UID changed"));
 						memcpy(server->
 							server_GUID,
 							pSMBr->u.
@@ -958,21 +960,19 @@
 	return rc;
 }
 
-/* If no buffer passed in, then caller wants to do the copy
-	as in the case of readpages so the SMB buffer must be
-	freed by the caller */
-
 int
 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
-	    const int netfid, const unsigned int count,
-	    const __u64 lseek, unsigned int *nbytes, char **buf)
+            const int netfid, const unsigned int count,
+            const __u64 lseek, unsigned int *nbytes, char **buf,
+	    int * pbuf_type)
 {
 	int rc = -EACCES;
 	READ_REQ *pSMB = NULL;
 	READ_RSP *pSMBr = NULL;
 	char *pReadData = NULL;
-	int bytes_returned;
 	int wct;
+	int resp_buf_type = 0;
+	struct kvec iov[1];
 
 	cFYI(1,("Reading %d bytes on fid %d",count,netfid));
 	if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -981,8 +981,7 @@
 		wct = 10; /* old style read */
 
 	*nbytes = 0;
-	rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
-		      (void **) &pSMBr);
+	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
 	if (rc)
 		return rc;
 
@@ -990,13 +989,13 @@
 	if (tcon->ses->server == NULL)
 		return -ECONNABORTED;
 
-	pSMB->AndXCommand = 0xFF;	/* none */
+	pSMB->AndXCommand = 0xFF;       /* none */
 	pSMB->Fid = netfid;
 	pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
 	if(wct == 12)
 		pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
-        else if((lseek >> 32) > 0) /* can not handle this big offset for old */
-                return -EIO;
+	else if((lseek >> 32) > 0) /* can not handle this big offset for old */
+		return -EIO;
 
 	pSMB->Remaining = 0;
 	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
@@ -1005,14 +1004,18 @@
 		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
 	else {
 		/* old style read */
-		struct smb_com_readx_req * pSMBW = 
+		struct smb_com_readx_req * pSMBW =
 			(struct smb_com_readx_req *)pSMB;
-		pSMBW->ByteCount = 0;	
+		pSMBW->ByteCount = 0;
 	}
-	
-	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+
+	iov[0].iov_base = (char *)pSMB;
+	iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
+	rc = SendReceive2(xid, tcon->ses, iov, 
+			  1 /* num iovecs */,
+			  &resp_buf_type, 0); 
 	cifs_stats_inc(&tcon->num_reads);
+	pSMBr = (READ_RSP *)iov[0].iov_base;
 	if (rc) {
 		cERROR(1, ("Send error in read = %d", rc));
 	} else {
@@ -1022,33 +1025,43 @@
 		*nbytes = data_length;
 
 		/*check that DataLength would not go beyond end of SMB */
-		if ((data_length > CIFSMaxBufSize) 
+		if ((data_length > CIFSMaxBufSize)
 				|| (data_length > count)) {
 			cFYI(1,("bad length %d for count %d",data_length,count));
 			rc = -EIO;
 			*nbytes = 0;
 		} else {
-			pReadData =
-			    (char *) (&pSMBr->hdr.Protocol) +
+			pReadData = (char *) (&pSMBr->hdr.Protocol) +
 			    le16_to_cpu(pSMBr->DataOffset);
-/*			if(rc = copy_to_user(buf, pReadData, data_length)) {
-				cERROR(1,("Faulting on read rc = %d",rc));
-				rc = -EFAULT;
-			}*/ /* can not use copy_to_user when using page cache*/
+/*                      if(rc = copy_to_user(buf, pReadData, data_length)) {
+                                cERROR(1,("Faulting on read rc = %d",rc));
+                                rc = -EFAULT;
+                        }*/ /* can not use copy_to_user when using page cache*/
 			if(*buf)
-			    memcpy(*buf,pReadData,data_length);
+				memcpy(*buf,pReadData,data_length);
 		}
 	}
-	if(*buf)
-		cifs_buf_release(pSMB);
-	else
-		*buf = (char *)pSMB;
 
-	/* Note: On -EAGAIN error only caller can retry on handle based calls 
+	cifs_small_buf_release(pSMB);
+	if(*buf) {
+		if(resp_buf_type == CIFS_SMALL_BUFFER)
+			cifs_small_buf_release(iov[0].iov_base);
+		else if(resp_buf_type == CIFS_LARGE_BUFFER)
+			cifs_buf_release(iov[0].iov_base);
+	} else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
+		*buf = iov[0].iov_base;
+		if(resp_buf_type == CIFS_SMALL_BUFFER)
+			*pbuf_type = CIFS_SMALL_BUFFER;
+		else if(resp_buf_type == CIFS_LARGE_BUFFER)
+			*pbuf_type = CIFS_LARGE_BUFFER;
+	}
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls
 		since file handle passed in no longer valid */
 	return rc;
 }
 
+
 int
 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
 	     const int netfid, const unsigned int count,
@@ -1155,7 +1168,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 int
 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
 	     const int netfid, const unsigned int count,
@@ -1164,10 +1176,10 @@
 {
 	int rc = -EACCES;
 	WRITE_REQ *pSMB = NULL;
-	int bytes_returned, wct;
+	int wct;
 	int smb_hdr_len;
+	int resp_buf_type = 0;
 
-	/* BB removeme BB */
 	cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
 
 	if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -1210,22 +1222,34 @@
 		pSMBW->ByteCount = cpu_to_le16(count + 5);
 	}
 	iov[0].iov_base = pSMB;
-	iov[0].iov_len = smb_hdr_len + 4;
+	if(wct == 14)
+		iov[0].iov_len = smb_hdr_len + 4;
+	else /* wct == 12 pad bigger by four bytes */
+		iov[0].iov_len = smb_hdr_len + 8;
+	
 
-	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
+	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
 			  long_op);
 	cifs_stats_inc(&tcon->num_writes);
 	if (rc) {
 		cFYI(1, ("Send error Write2 = %d", rc));
 		*nbytes = 0;
+	} else if(resp_buf_type == 0) {
+		/* presumably this can not happen, but best to be safe */
+		rc = -EIO;
+		*nbytes = 0;
 	} else {
-		WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
+		WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
 		*nbytes = (*nbytes) << 16;
 		*nbytes += le16_to_cpu(pSMBr->Count);
-	}
+	} 
 
 	cifs_small_buf_release(pSMB);
+	if(resp_buf_type == CIFS_SMALL_BUFFER)
+		cifs_small_buf_release(iov[0].iov_base);
+	else if(resp_buf_type == CIFS_LARGE_BUFFER)
+		cifs_buf_release(iov[0].iov_base);
 
 	/* Note: On -EAGAIN error only caller can retry on handle based calls 
 		since file handle passed in no longer valid */
@@ -1234,8 +1258,6 @@
 }
 
 
-#endif /* CIFS_EXPERIMENTAL */
-
 int
 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
 	    const __u16 smb_file_id, const __u64 len,
@@ -1906,6 +1928,90 @@
 	return rc;
 }
 
+/* Initialize NT TRANSACT SMB into small smb request buffer.
+   This assumes that all NT TRANSACTS that we init here have
+   total parm and data under about 400 bytes (to fit in small cifs
+   buffer size), which is the case so far, it easily fits. NB:
+	Setup words themselves and ByteCount
+	MaxSetupCount (size of returned setup area) and
+	MaxParameterCount (returned parms size) must be set by caller */
+static int 
+smb_init_ntransact(const __u16 sub_command, const int setup_count,
+		   const int parm_len, struct cifsTconInfo *tcon,
+		   void ** ret_buf)
+{
+	int rc;
+	__u32 temp_offset;
+	struct smb_com_ntransact_req * pSMB;
+
+	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
+				(void **)&pSMB);
+	if (rc)
+		return rc;
+	*ret_buf = (void *)pSMB;
+	pSMB->Reserved = 0;
+	pSMB->TotalParameterCount = cpu_to_le32(parm_len);
+	pSMB->TotalDataCount  = 0;
+	pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+					  MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->DataCount  = pSMB->TotalDataCount;
+	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
+			(setup_count * 2) - 4 /* for rfc1001 length itself */;
+	pSMB->ParameterOffset = cpu_to_le32(temp_offset);
+	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
+	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
+	pSMB->SubCommand = cpu_to_le16(sub_command);
+	return 0;
+}
+
+static int
+validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
+		   int * pdatalen, int * pparmlen)
+{
+	char * end_of_smb;
+	__u32 data_count, data_offset, parm_count, parm_offset;
+	struct smb_com_ntransact_rsp * pSMBr;
+
+	if(buf == NULL)
+		return -EINVAL;
+
+	pSMBr = (struct smb_com_ntransact_rsp *)buf;
+
+	/* ByteCount was converted from little endian in SendReceive */
+	end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount + 
+			(char *)&pSMBr->ByteCount;
+
+		
+	data_offset = le32_to_cpu(pSMBr->DataOffset);
+	data_count = le32_to_cpu(pSMBr->DataCount);
+        parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
+	parm_count = le32_to_cpu(pSMBr->ParameterCount);
+
+	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
+	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
+
+	/* should we also check that parm and data areas do not overlap? */
+	if(*ppparm > end_of_smb) {
+		cFYI(1,("parms start after end of smb"));
+		return -EINVAL;
+	} else if(parm_count + *ppparm > end_of_smb) {
+		cFYI(1,("parm end after end of smb"));
+		return -EINVAL;
+	} else if(*ppdata > end_of_smb) {
+		cFYI(1,("data starts after end of smb"));
+		return -EINVAL;
+	} else if(data_count + *ppdata > end_of_smb) {
+		cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
+			*ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr));  /* BB FIXME */
+		return -EINVAL;
+	} else if(parm_count + data_count > pSMBr->ByteCount) {
+		cFYI(1,("parm count and data count larger than SMB"));
+		return -EINVAL;
+	}
+	return 0;
+}
+
 int
 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
 			const unsigned char *searchName,
@@ -1928,7 +2034,8 @@
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le32(2);
 	/* BB find exact data count max from sess structure BB */
-	pSMB->MaxDataCount = cpu_to_le32(4000);
+	pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+					  MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
 	pSMB->MaxSetupCount = 4;
 	pSMB->Reserved = 0;
 	pSMB->ParameterOffset = 0;
@@ -1955,7 +2062,9 @@
 			rc = -EIO;	/* bad smb */
 		else {
 			if(data_count && (data_count < 2048)) {
-				char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
+				char * end_of_smb = 2 /* sizeof byte count */ +
+						pSMBr->ByteCount +
+						(char *)&pSMBr->ByteCount;
 
 				struct reparse_data * reparse_buf = (struct reparse_data *)
 					((char *)&pSMBr->hdr.Protocol + data_offset);
@@ -2199,6 +2308,7 @@
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	cifs_stats_inc(&tcon->num_acl_get);
 	if (rc) {
 		cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
 	} else {
@@ -2386,6 +2496,92 @@
 
 #endif /* CONFIG_POSIX */
 
+
+/* security id for everyone */
+const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
+/* group users */
+const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
+
+/* Convert CIFS ACL to POSIX form */
+static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
+{
+	return 0;
+}
+
+/* Get Security Descriptor (by handle) from remote server for a file or dir */
+int
+CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
+         /*  BB fix up return info */ char *acl_inf, const int buflen, 
+		  const int acl_type /* ACCESS/DEFAULT not sure implication */)
+{
+	int rc = 0;
+	int buf_type = 0;
+	QUERY_SEC_DESC_REQ * pSMB;
+	struct kvec iov[1];
+
+	cFYI(1, ("GetCifsACL"));
+
+	rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, 
+			8 /* parm len */, tcon, (void **) &pSMB);
+	if (rc)
+		return rc;
+
+	pSMB->MaxParameterCount = cpu_to_le32(4);
+	/* BB TEST with big acls that might need to be e.g. larger than 16K */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Fid = fid; /* file handle always le */
+	pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
+				     CIFS_ACL_DACL);
+	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
+	pSMB->hdr.smb_buf_length += 11;
+	iov[0].iov_base = (char *)pSMB;
+	iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
+
+	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
+	cifs_stats_inc(&tcon->num_acl_get);
+	if (rc) {
+		cFYI(1, ("Send error in QuerySecDesc = %d", rc));
+	} else {                /* decode response */
+		struct cifs_sid * psec_desc;
+		__le32 * parm;
+		int parm_len;
+		int data_len;
+		int acl_len;
+		struct smb_com_ntransact_rsp * pSMBr;
+
+/* validate_nttransact */
+		rc = validate_ntransact(iov[0].iov_base, (char **)&parm, 
+					(char **)&psec_desc,
+					&parm_len, &data_len);
+		
+		if(rc)
+			goto qsec_out;
+		pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
+
+		cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc));  /* BB removeme BB */
+
+		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
+			rc = -EIO;      /* bad smb */
+			goto qsec_out;
+		}
+
+/* BB check that data area is minimum length and as big as acl_len */
+
+		acl_len = le32_to_cpu(*(__le32 *)parm);
+		/* BB check if(acl_len > bufsize) */
+
+		parse_sec_desc(psec_desc, acl_len);
+	}
+qsec_out:
+	if(buf_type == CIFS_SMALL_BUFFER)
+		cifs_small_buf_release(iov[0].iov_base);
+	else if(buf_type == CIFS_LARGE_BUFFER)
+		cifs_buf_release(iov[0].iov_base);
+	cifs_small_buf_release(pSMB);
+	return rc;
+}
+
+
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
@@ -4284,7 +4480,7 @@
 {
 	int rc = 0;
 	struct smb_com_transaction_change_notify_req * pSMB = NULL;
-	struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
+	struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
 	struct dir_notify_req *dnotify_req;
 	int bytes_returned;
 
@@ -4299,6 +4495,10 @@
 	pSMB->MaxParameterCount = cpu_to_le32(2);
 	/* BB find exact data count max from sess structure BB */
 	pSMB->MaxDataCount = 0; /* same in little endian or be */
+/* BB VERIFY verify which is correct for above BB */
+	pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+					     MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+
 	pSMB->MaxSetupCount = 4;
 	pSMB->Reserved = 0;
 	pSMB->ParameterOffset = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c467de8..e488603 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -76,12 +76,19 @@
 	unsigned setuids:1;
 	unsigned noperm:1;
 	unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
+	unsigned cifs_acl:1;
 	unsigned no_xattr:1;   /* set if xattr (EA) support should be disabled*/
 	unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
 	unsigned direct_io:1;
 	unsigned remap:1;   /* set to remap seven reserved chars in filenames */
 	unsigned posix_paths:1;   /* unset to not ask for posix pathnames. */
 	unsigned sfu_emul:1;
+	unsigned krb5:1;
+	unsigned ntlm:1;
+	unsigned ntlmv2:1;
+	unsigned nullauth:1; /* attempt to authenticate with null user */
+	unsigned sign:1;
+	unsigned seal:1;     /* encrypt */
 	unsigned nocase;     /* request case insensitive filenames */
 	unsigned nobrl;      /* disable sending byte range locks to srv */
 	unsigned int rsize;
@@ -508,7 +515,7 @@
 		/* else length ok */
 		reconnect = 0;
 
-		if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
+		if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
 			isLargeBuf = TRUE;
 			memcpy(bigbuf, smallbuf, 4);
 			smb_buffer = bigbuf;
@@ -777,7 +784,7 @@
 
 	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
 	vol->rw = TRUE;
-
+	vol->ntlm = TRUE;
 	/* default is always to request posix paths. */
 	vol->posix_paths = 1;
 
@@ -903,6 +910,39 @@
 				printk(KERN_WARNING "CIFS: ip address too long\n");
 				return 1;
 			}
+                } else if (strnicmp(data, "sec", 3) == 0) { 
+                        if (!value || !*value) {
+				cERROR(1,("no security value specified"));
+                                continue;
+                        } else if (strnicmp(value, "krb5i", 5) == 0) {
+				vol->sign = 1;
+				vol->krb5 = 1;
+			} else if (strnicmp(value, "krb5p", 5) == 0) {
+				/* vol->seal = 1; 
+				   vol->krb5 = 1; */
+				cERROR(1,("Krb5 cifs privacy not supported"));
+				return 1;
+			} else if (strnicmp(value, "krb5", 4) == 0) {
+				vol->krb5 = 1;
+			} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
+				vol->ntlmv2 = 1;
+				vol->sign = 1;
+			} else if (strnicmp(value, "ntlmv2", 6) == 0) {
+				vol->ntlmv2 = 1;
+			} else if (strnicmp(value, "ntlmi", 5) == 0) {
+				vol->ntlm = 1;
+				vol->sign = 1;
+			} else if (strnicmp(value, "ntlm", 4) == 0) {
+				/* ntlm is default so can be turned off too */
+				vol->ntlm = 1;
+			} else if (strnicmp(value, "nontlm", 6) == 0) {
+				vol->ntlm = 0;
+			} else if (strnicmp(value, "none", 4) == 0) {
+				vol->nullauth = 1; 
+                        } else {
+                                cERROR(1,("bad security option: %s", value));
+                                return 1;
+                        }
 		} else if ((strnicmp(data, "unc", 3) == 0)
 			   || (strnicmp(data, "target", 6) == 0)
 			   || (strnicmp(data, "path", 4) == 0)) {
@@ -1120,6 +1160,10 @@
 			vol->server_ino = 1;
 		} else if (strnicmp(data, "noserverino",9) == 0) {
 			vol->server_ino = 0;
+		} else if (strnicmp(data, "cifsacl",7) == 0) {
+			vol->cifs_acl = 1;
+		} else if (strnicmp(data, "nocifsacl", 9) == 0) {
+			vol->cifs_acl = 0;
 		} else if (strnicmp(data, "acl",3) == 0) {
 			vol->no_psx_acl = 0;
 		} else if (strnicmp(data, "noacl",5) == 0) {
@@ -1546,7 +1590,7 @@
 		cFYI(1, ("Username: %s ", volume_info.username));
 
 	} else {
-		cifserror("No username specified ");
+		cifserror("No username specified");
         /* In userspace mount helper we can get user name from alternate
            locations such as env variables and files on disk */
 		kfree(volume_info.UNC);
@@ -1587,7 +1631,7 @@
 		return -EINVAL;
 	} else /* which servers DFS root would we conect to */ {
 		cERROR(1,
-		       ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified  "));
+		       ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
 		kfree(volume_info.UNC);
 		kfree(volume_info.password);
 		FreeXid(xid);
@@ -1626,7 +1670,7 @@
 
 
 	if (srvTcp) {
-		cFYI(1, ("Existing tcp session with server found "));                
+		cFYI(1, ("Existing tcp session with server found"));                
 	} else {	/* create socket */
 		if(volume_info.port)
 			sin_server.sin_port = htons(volume_info.port);
@@ -1689,11 +1733,11 @@
 
 	if (existingCifsSes) {
 		pSesInfo = existingCifsSes;
-		cFYI(1, ("Existing smb sess found "));
+		cFYI(1, ("Existing smb sess found"));
 		kfree(volume_info.password);
 		/* volume_info.UNC freed at end of function */
 	} else if (!rc) {
-		cFYI(1, ("Existing smb sess not found "));
+		cFYI(1, ("Existing smb sess not found"));
 		pSesInfo = sesInfoAlloc();
 		if (pSesInfo == NULL)
 			rc = -ENOMEM;
@@ -1741,7 +1785,16 @@
 		} else if(volume_info.wsize)
 			cifs_sb->wsize = volume_info.wsize;
 		else
-			cifs_sb->wsize = CIFSMaxBufSize; /* default */
+			cifs_sb->wsize = 
+				min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
+					127*1024);
+			/* old default of CIFSMaxBufSize was too small now
+			   that SMB Write2 can send multiple pages in kvec.   
+			   RFC1001 does not describe what happens when frame
+			   bigger than 128K is sent so use that as max in
+			   conjunction with 52K kvec constraint on arch with 4K
+			   page size  */
+
 		if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
 			cifs_sb->rsize = PAGE_CACHE_SIZE; 
 			/* Windows ME does this */
@@ -1751,7 +1804,8 @@
 		cifs_sb->mnt_gid = volume_info.linux_gid;
 		cifs_sb->mnt_file_mode = volume_info.file_mode;
 		cifs_sb->mnt_dir_mode = volume_info.dir_mode;
-		cFYI(1,("file mode: 0x%x  dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
+		cFYI(1,("file mode: 0x%x  dir mode: 0x%x",
+			cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
 
 		if(volume_info.noperm)
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
@@ -1767,6 +1821,8 @@
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
 		if(volume_info.nobrl)
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
+		if(volume_info.cifs_acl)
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
 
 		if(volume_info.direct_io) {
 			cFYI(1,("mounting share using direct i/o"));
@@ -1777,7 +1833,7 @@
 		    find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
 			     volume_info.username);
 		if (tcon) {
-			cFYI(1, ("Found match on UNC path "));
+			cFYI(1, ("Found match on UNC path"));
 			/* we can have only one retry value for a connection
 			   to a share so for resources mounted more than once
 			   to the same server share the last value passed in 
@@ -1926,7 +1982,7 @@
 	__u32 capabilities;
 	__u16 count;
 
-	cFYI(1, ("In sesssetup "));
+	cFYI(1, ("In sesssetup"));
 	if(ses == NULL)
 		return -EINVAL;
 	user = ses->userName;
@@ -3202,9 +3258,26 @@
 
 	pSMB->AndXCommand = 0xFF;
 	pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
-	pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
 	bcc_ptr = &pSMB->Password[0];
-	bcc_ptr++;		/* skip password */
+	if((ses->server->secMode) & SECMODE_USER) {
+		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
+		bcc_ptr++;              /* skip password */
+	} else {
+		pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+		/* BB FIXME add code to fail this if NTLMv2 or Kerberos
+		   specified as required (when that support is added to
+		   the vfs in the future) as only NTLM or the much
+		   weaker LANMAN (which we do not send) is accepted
+		   by Samba (not sure whether other servers allow
+		   NTLMv2 password here) */
+		SMBNTencrypt(ses->password,
+			     ses->server->cryptKey,
+			     bcc_ptr);
+
+		bcc_ptr += CIFS_SESSION_KEY_SIZE;
+		*bcc_ptr = 0;
+		bcc_ptr++; /* align */
+	}
 
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -3222,7 +3295,6 @@
 		bcc_ptr += 2 * length;	/* convert num of 16 bit words to bytes */
 		bcc_ptr += 2;	/* skip trailing null */
 	} else {		/* ASCII */
-
 		strcpy(bcc_ptr, tree);
 		bcc_ptr += strlen(tree) + 1;
 	}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 32cc96c..fed55e3 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -3,7 +3,7 @@
  *
  *   vfs operations that deal with dentries
  * 
- *   Copyright (C) International Business Machines  Corp., 2002,2003
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -200,8 +200,8 @@
 			(oplock & CIFS_CREATE_ACTION))
 			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
-					(__u64)current->euid,
-					(__u64)current->egid,
+					(__u64)current->fsuid,
+					(__u64)current->fsgid,
 					0 /* dev */,
 					cifs_sb->local_nls, 
 					cifs_sb->mnt_cifs_flags & 
@@ -325,7 +325,7 @@
 	else if (pTcon->ses->capabilities & CAP_UNIX) {
 		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
-				mode,(__u64)current->euid,(__u64)current->egid,
+				mode,(__u64)current->fsuid,(__u64)current->fsgid,
 				device_number, cifs_sb->local_nls,
 				cifs_sb->mnt_cifs_flags & 
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5ade53d..d17c97d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -553,13 +553,13 @@
 		}
 		ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
 		if (ptmp) {
-   /* BB removeme BB */	cFYI(1, ("freeing smb buf in srch struct in closedir"));
+			cFYI(1, ("closedir free smb buf in srch struct"));
 			pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
 			cifs_buf_release(ptmp);
 		}
 		ptmp = pCFileStruct->search_resume_name;
 		if (ptmp) {
-   /* BB removeme BB */	cFYI(1, ("freeing resume name in closedir"));
+			cFYI(1, ("closedir free resume name"));
 			pCFileStruct->search_resume_name = NULL;
 			kfree(ptmp);
 		}
@@ -868,10 +868,9 @@
 				if (rc != 0)
 					break;
 			}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 			/* BB FIXME We can not sign across two buffers yet */
-			if((experimEnabled) && ((pTcon->ses->server->secMode & 
-			 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
+			if((pTcon->ses->server->secMode & 
+			 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
 				struct kvec iov[2];
 				unsigned int len;
 
@@ -887,7 +886,6 @@
 						iov, 1, long_op);
 			} else
 			/* BB FIXME fixup indentation of line below */
-#endif			
 			rc = CIFSSMBWrite(xid, pTcon,
 				 open_file->netfid,
 				 min_t(const int, cifs_sb->wsize, 
@@ -1024,7 +1022,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 static int cifs_writepages(struct address_space *mapping,
 			   struct writeback_control *wbc)
 {
@@ -1193,7 +1190,6 @@
 					/* BB what if continued retry is
 					   requested via mount flags? */
 					set_bit(AS_EIO, &mapping->flags);
-					SetPageError(page);
 				} else {
 					cifs_stats_bytes_written(cifs_sb->tcon,
 								 bytes_written);
@@ -1201,6 +1197,13 @@
 			}
 			for (i = 0; i < n_iov; i++) {
 				page = pvec.pages[first + i];
+				/* Should we also set page error on
+				success rc but too little data written? */
+				/* BB investigate retry logic on temporary
+				server crash cases and how recovery works
+				when page marked as error */ 
+				if(rc)
+					SetPageError(page);
 				kunmap(page);
 				unlock_page(page);
 				page_cache_release(page);
@@ -1227,7 +1230,6 @@
 
 	return rc;
 }
-#endif
 
 static int cifs_writepage(struct page* page, struct writeback_control *wbc)
 {
@@ -1426,6 +1428,7 @@
 		rc = -EAGAIN;
 		smb_read_data = NULL;
 		while (rc == -EAGAIN) {
+			int buf_type = CIFS_NO_BUFFER;
 			if ((open_file->invalidHandle) && 
 			    (!open_file->closePend)) {
 				rc = cifs_reopen_file(file->f_dentry->d_inode,
@@ -1434,20 +1437,22 @@
 					break;
 			}
 			rc = CIFSSMBRead(xid, pTcon,
-					open_file->netfid,
-					current_read_size, *poffset,
-					&bytes_read, &smb_read_data);
+					 open_file->netfid,
+					 current_read_size, *poffset,
+					 &bytes_read, &smb_read_data,
+					 &buf_type);
 			pSMBr = (struct smb_com_read_rsp *)smb_read_data;
 			if (copy_to_user(current_offset, 
 					 smb_read_data + 4 /* RFC1001 hdr */
 					 + le16_to_cpu(pSMBr->DataOffset), 
 					 bytes_read)) {
 				rc = -EFAULT;
-				FreeXid(xid);
-				return rc;
-            }
+			}
 			if (smb_read_data) {
-				cifs_buf_release(smb_read_data);
+				if(buf_type == CIFS_SMALL_BUFFER)
+					cifs_small_buf_release(smb_read_data);
+				else if(buf_type == CIFS_LARGE_BUFFER)
+					cifs_buf_release(smb_read_data);
 				smb_read_data = NULL;
 			}
 		}
@@ -1480,6 +1485,7 @@
 	int xid;
 	char *current_offset;
 	struct cifsFileInfo *open_file;
+	int buf_type = CIFS_NO_BUFFER;
 
 	xid = GetXid();
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1516,9 +1522,10 @@
 					break;
 			}
 			rc = CIFSSMBRead(xid, pTcon,
-					open_file->netfid,
-					current_read_size, *poffset,
-					&bytes_read, &current_offset);
+					 open_file->netfid,
+					 current_read_size, *poffset,
+					 &bytes_read, &current_offset,
+					 &buf_type);
 		}
 		if (rc || (bytes_read == 0)) {
 			if (total_read) {
@@ -1616,6 +1623,7 @@
 	struct smb_com_read_rsp *pSMBr;
 	struct pagevec lru_pvec;
 	struct cifsFileInfo *open_file;
+	int buf_type = CIFS_NO_BUFFER;
 
 	xid = GetXid();
 	if (file->private_data == NULL) {
@@ -1672,14 +1680,17 @@
 			}
 
 			rc = CIFSSMBRead(xid, pTcon,
-					open_file->netfid,
-					read_size, offset,
-					&bytes_read, &smb_read_data);
-
+					 open_file->netfid,
+					 read_size, offset,
+					 &bytes_read, &smb_read_data,
+					 &buf_type);
 			/* BB more RC checks ? */
 			if (rc== -EAGAIN) {
 				if (smb_read_data) {
-					cifs_buf_release(smb_read_data);
+					if(buf_type == CIFS_SMALL_BUFFER)
+						cifs_small_buf_release(smb_read_data);
+					else if(buf_type == CIFS_LARGE_BUFFER)
+						cifs_buf_release(smb_read_data);
 					smb_read_data = NULL;
 				}
 			}
@@ -1736,7 +1747,10 @@
 			break;
 		}
 		if (smb_read_data) {
-			cifs_buf_release(smb_read_data);
+			if(buf_type == CIFS_SMALL_BUFFER)
+				cifs_small_buf_release(smb_read_data);
+			else if(buf_type == CIFS_LARGE_BUFFER)
+				cifs_buf_release(smb_read_data);
 			smb_read_data = NULL;
 		}
 		bytes_read = 0;
@@ -1746,7 +1760,10 @@
 
 /* need to free smb_read_data buf before exit */
 	if (smb_read_data) {
-		cifs_buf_release(smb_read_data);
+		if(buf_type == CIFS_SMALL_BUFFER)
+			cifs_small_buf_release(smb_read_data);
+		else if(buf_type == CIFS_LARGE_BUFFER)
+			cifs_buf_release(smb_read_data);
 		smb_read_data = NULL;
 	} 
 
@@ -1825,10 +1842,20 @@
 		open_file =  find_writable_file(cifsInode);
  
 	if(open_file) {
+		struct cifs_sb_info *cifs_sb;
+
 		/* there is not actually a write pending so let
 		this handle go free and allow it to
 		be closable if needed */
 		atomic_dec(&open_file->wrtPending);
+
+		cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
+		if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
+			/* since no page cache to corrupt on directio 
+			we can change size safely */
+			return 1;
+		}
+
 		return 0;
 	} else
 		return 1;
@@ -1873,9 +1900,7 @@
 	.readpage = cifs_readpage,
 	.readpages = cifs_readpages,
 	.writepage = cifs_writepage,
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 	.writepages = cifs_writepages,
-#endif
 	.prepare_write = cifs_prepare_write,
 	.commit_write = cifs_commit_write,
 	.set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 3ebce94..5935991 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -229,11 +229,12 @@
 			 cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc==0) {
+		int buf_type = CIFS_NO_BUFFER;
 			/* Read header */
 		rc = CIFSSMBRead(xid, pTcon,
 			         netfid,
 				 24 /* length */, 0 /* offset */,
-				 &bytes_read, &pbuf);
+				 &bytes_read, &pbuf, &buf_type);
 		if((rc == 0) && (bytes_read >= 8)) {
 			if(memcmp("IntxBLK", pbuf, 8) == 0) {
 				cFYI(1,("Block device"));
@@ -267,7 +268,7 @@
 		} else {
 			inode->i_mode |= S_IFREG; /* then it is a file */
 			rc = -EOPNOTSUPP; /* or some unknown SFU type */	
-		}
+		}		
 		CIFSSMBClose(xid, pTcon, netfid);
 	}
 	return rc;
@@ -750,8 +751,8 @@
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path,
 						    mode,
-						    (__u64)current->euid,
-						    (__u64)current->egid,
+						    (__u64)current->fsuid,
+						    (__u64)current->fsgid,
 						    0 /* dev_t */,
 						    cifs_sb->local_nls,
 						    cifs_sb->mnt_cifs_flags &
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 94baf6c..812c6bb 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/misc.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -161,6 +161,9 @@
 	if (ret_buf) {
 		memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
 		atomic_inc(&bufAllocCount);
+#ifdef CONFIG_CIFS_STATS2
+		atomic_inc(&totBufAllocCount);
+#endif /* CONFIG_CIFS_STATS2 */
 	}
 
 	return ret_buf;
@@ -195,6 +198,10 @@
 	/* No need to clear memory here, cleared in header assemble */
 	/*	memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
 		atomic_inc(&smBufAllocCount);
+#ifdef CONFIG_CIFS_STATS2
+		atomic_inc(&totSmBufAllocCount);
+#endif /* CONFIG_CIFS_STATS2 */
+
 	}
 	return ret_buf;
 }
@@ -292,7 +299,7 @@
 	struct cifsSesInfo * ses;
 	char *temp = (char *) buffer;
 
-	memset(temp,0,MAX_CIFS_HDR_SIZE);
+	memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */
 
 	buffer->smb_buf_length =
 	    (2 * word_count) + sizeof (struct smb_hdr) -
@@ -348,12 +355,12 @@
 		/*  BB Add support for establishing new tCon and SMB Session  */
 		/*      with userid/password pairs found on the smb session   */ 
 		/*	for other target tcp/ip addresses 		BB    */
-				if(current->uid != treeCon->ses->linux_uid) {
-					cFYI(1,("Multiuser mode and UID did not match tcon uid "));
+				if(current->fsuid != treeCon->ses->linux_uid) {
+					cFYI(1,("Multiuser mode and UID did not match tcon uid"));
 					read_lock(&GlobalSMBSeslock);
 					list_for_each(temp_item, &GlobalSMBSessionList) {
 						ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
-						if(ses->linux_uid == current->uid) {
+						if(ses->linux_uid == current->fsuid) {
 							if(ses->server == treeCon->ses->server) {
 								cFYI(1,("found matching uid substitute right smb_uid"));  
 								buffer->Uid = ses->Suid;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 9bdaaec..288cc04 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -214,8 +214,7 @@
 			tmp_inode->i_fop = &cifs_file_nobrl_ops;
 		else
 			tmp_inode->i_fop = &cifs_file_ops;
-		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-			tmp_inode->i_fop->lock = NULL;
+
 		tmp_inode->i_data.a_ops = &cifs_addr_ops;
 		if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
 		   (cifs_sb->tcon->ses->server->maxBuf <
@@ -327,12 +326,18 @@
 	if (S_ISREG(tmp_inode->i_mode)) {
 		cFYI(1, ("File inode"));
 		tmp_inode->i_op = &cifs_file_inode_ops;
-		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
-			tmp_inode->i_fop = &cifs_file_direct_ops;
+
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+				tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
+			else
+				tmp_inode->i_fop = &cifs_file_direct_ops;
+		
+		} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+			tmp_inode->i_fop = &cifs_file_nobrl_ops;
 		else
 			tmp_inode->i_fop = &cifs_file_ops;
-		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-			tmp_inode->i_fop->lock = NULL;
+
 		tmp_inode->i_data.a_ops = &cifs_addr_ops;
 		if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
 		   (cifs_sb->tcon->ses->server->maxBuf < 
diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
index 9222033..aede606 100644
--- a/fs/cifs/rfc1002pdu.h
+++ b/fs/cifs/rfc1002pdu.h
@@ -24,11 +24,11 @@
 /* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
 
 	/* RFC 1002 session packet types */
-#define RFC1002_SESSION_MESASAGE 0x00
+#define RFC1002_SESSION_MESSAGE 0x00
 #define RFC1002_SESSION_REQUEST  0x81
 #define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
 #define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
-#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
+#define RFC1002_RETARGET_SESSION_RESPONSE 0x84
 #define RFC1002_SESSION_KEEP_ALIVE 0x85
 
 	/* RFC 1002 flags (only one defined */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index f887119..b12cb8a 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -206,7 +206,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 static int
 smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
 	  struct sockaddr *sin)
@@ -299,7 +298,7 @@
 
 int
 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 
-	     struct kvec *iov, int n_vec, int *pbytes_returned,
+	     struct kvec *iov, int n_vec, int * pRespBufType /* ret */, 
 	     const int long_op)
 {
 	int rc = 0;
@@ -307,6 +306,8 @@
 	unsigned long timeout;
 	struct mid_q_entry *midQ;
 	struct smb_hdr *in_buf = iov[0].iov_base;
+	
+	*pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
 
 	if (ses == NULL) {
 		cERROR(1,("Null smb session"));
@@ -392,8 +393,7 @@
 		return -ENOMEM;
 	}
 
-/* BB FIXME */
-/* 	rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
+ 	rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
 
 	midQ->midState = MID_REQUEST_SUBMITTED;
 #ifdef CONFIG_CIFS_STATS2
@@ -489,21 +489,22 @@
 			receive_len, xid));
 		rc = -EIO;
 	} else {		/* rcvd frame is ok */
-
 		if (midQ->resp_buf && 
 			(midQ->midState == MID_RESPONSE_RECEIVED)) {
-			in_buf->smb_buf_length = receive_len;
-			/* BB verify that length would not overrun small buf */
-			memcpy((char *)in_buf + 4,
-			       (char *)midQ->resp_buf + 4,
-			       receive_len);
 
-			dump_smb(in_buf, 80);
+			iov[0].iov_base = (char *)midQ->resp_buf;
+			if(midQ->largeBuf)
+				*pRespBufType = CIFS_LARGE_BUFFER;
+			else
+				*pRespBufType = CIFS_SMALL_BUFFER;
+			iov[0].iov_len = receive_len + 4;
+
+			dump_smb(midQ->resp_buf, 80);
 			/* convert the length into a more usable form */
 			if((receive_len > 24) &&
 			   (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
 					SECMODE_SIGN_ENABLED))) {
-				rc = cifs_verify_signature(in_buf,
+				rc = cifs_verify_signature(midQ->resp_buf,
 						ses->server->mac_signing_key,
 						midQ->sequence_number+1);
 				if(rc) {
@@ -512,18 +513,19 @@
 				}
 			}
 
-			*pbytes_returned = in_buf->smb_buf_length;
-
 			/* BB special case reconnect tid and uid here? */
 			/* BB special case Errbadpassword and pwdexpired here */
-			rc = map_smb_to_linux_error(in_buf);
+			rc = map_smb_to_linux_error(midQ->resp_buf);
 
 			/* convert ByteCount if necessary */
 			if (receive_len >=
 			    sizeof (struct smb_hdr) -
 			    4 /* do not count RFC1001 header */  +
-			    (2 * in_buf->WordCount) + 2 /* bcc */ )
-				BCC(in_buf) = le16_to_cpu(BCC_LE(in_buf));
+			    (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
+				BCC(midQ->resp_buf) = 
+					le16_to_cpu(BCC_LE(midQ->resp_buf));
+			midQ->resp_buf = NULL;  /* mark it so will not be freed
+						by DeleteMidQEntry */
 		} else {
 			rc = -EIO;
 			cFYI(1,("Bad MID state?"));
@@ -549,7 +551,6 @@
 
 	return rc;
 }
-#endif /* CIFS_EXPERIMENTAL */
 
 int
 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
@@ -790,7 +791,7 @@
 				BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
 		} else {
 			rc = -EIO;
-			cERROR(1,("Bad MID state? "));
+			cERROR(1,("Bad MID state?"));
 		}
 	}
 cifs_no_response_exit:
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index f375f87..777e336 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -254,7 +254,8 @@
 		rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
 			buf_size, cifs_sb->local_nls,
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
-	} else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
+	} else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
+			  strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
 #ifdef CONFIG_CIFS_POSIX
 		if(sb->s_flags & MS_POSIXACL)
 			rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
@@ -262,10 +263,27 @@
 				cifs_sb->local_nls,
 				cifs_sb->mnt_cifs_flags & 
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
+/*		else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+			__u16 fid;
+			int oplock = FALSE;
+			rc = CIFSSMBOpen(xid, pTcon, full_path,
+					 FILE_OPEN, GENERIC_READ, 0, &fid,
+					 &oplock, NULL, cifs_sb->local_nls,
+					 cifs_sb->mnt_cifs_flags &
+					 CIFS_MOUNT_MAP_SPECIAL_CHR);
+			if(rc == 0) {
+				rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
+					ea_value, buf_size,
+					ACL_TYPE_ACCESS);
+				CIFSSMBClose(xid, pTcon, fid)
+			}
+		} */  /* BB enable after fixing up return data */
+                  		
 #else 
 		cFYI(1,("query POSIX ACL not supported yet"));
 #endif /* CONFIG_CIFS_POSIX */
-	} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
+	} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,
+			  strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
 #ifdef CONFIG_CIFS_POSIX
 		if(sb->s_flags & MS_POSIXACL)
 			rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
diff --git a/fs/compat.c b/fs/compat.c
index 2468ac1..a2ba78b 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -53,6 +53,8 @@
 #include <asm/mmu_context.h>
 #include <asm/ioctls.h>
 
+extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
+
 /*
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
@@ -68,28 +70,33 @@
 		tv[0].tv_usec = 0;
 		tv[1].tv_usec = 0;
 	}
-	return do_utimes(filename, t ? tv : NULL);
+	return do_utimes(AT_FDCWD, filename, t ? tv : NULL);
 }
 
-asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t)
+asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t)
 {
 	struct timeval tv[2];
 
-	if (t) { 
+	if (t) {
 		if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
 		    get_user(tv[0].tv_usec, &t[0].tv_usec) ||
 		    get_user(tv[1].tv_sec, &t[1].tv_sec) ||
 		    get_user(tv[1].tv_usec, &t[1].tv_usec))
-			return -EFAULT; 
-	} 
-	return do_utimes(filename, t ? tv : NULL);
+			return -EFAULT;
+	}
+	return do_utimes(dfd, filename, t ? tv : NULL);
+}
+
+asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t)
+{
+	return compat_sys_futimesat(AT_FDCWD, filename, t);
 }
 
 asmlinkage long compat_sys_newstat(char __user * filename,
 		struct compat_stat __user *statbuf)
 {
 	struct kstat stat;
-	int error = vfs_stat(filename, &stat);
+	int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
 
 	if (!error)
 		error = cp_compat_stat(&stat, statbuf);
@@ -100,13 +107,34 @@
 		struct compat_stat __user *statbuf)
 {
 	struct kstat stat;
-	int error = vfs_lstat(filename, &stat);
+	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
 
 	if (!error)
 		error = cp_compat_stat(&stat, statbuf);
 	return error;
 }
 
+asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename,
+		struct compat_stat __user *statbuf, int flag)
+{
+	struct kstat stat;
+	int error = -EINVAL;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat_fd(dfd, filename, &stat);
+	else
+		error = vfs_stat_fd(dfd, filename, &stat);
+
+	if (!error)
+		error = cp_compat_stat(&stat, statbuf);
+
+out:
+	return error;
+}
+
 asmlinkage long compat_sys_newfstat(unsigned int fd,
 		struct compat_stat __user * statbuf)
 {
@@ -1290,7 +1318,17 @@
 asmlinkage long
 compat_sys_open(const char __user *filename, int flags, int mode)
 {
-	return do_sys_open(filename, flags, mode);
+	return do_sys_open(AT_FDCWD, filename, flags, mode);
+}
+
+/*
+ * Exactly like fs/open.c:sys_openat(), except that it doesn't set the
+ * O_LARGEFILE flag.
+ */
+asmlinkage long
+compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode)
+{
+	return do_sys_open(dfd, filename, flags, mode);
 }
 
 /*
@@ -1621,36 +1659,14 @@
 #define MAX_SELECT_SECONDS \
 	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
 
-asmlinkage long
-compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp,
-		compat_ulong_t __user *exp, struct compat_timeval __user *tvp)
+int compat_core_sys_select(int n, compat_ulong_t __user *inp,
+	compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout)
 {
 	fd_set_bits fds;
 	char *bits;
-	long timeout;
 	int size, max_fdset, ret = -EINVAL;
 	struct fdtable *fdt;
 
-	timeout = MAX_SCHEDULE_TIMEOUT;
-	if (tvp) {
-		time_t sec, usec;
-
-		if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
-		    || __get_user(sec, &tvp->tv_sec)
-		    || __get_user(usec, &tvp->tv_usec)) {
-			ret = -EFAULT;
-			goto out_nofds;
-		}
-
-		if (sec < 0 || usec < 0)
-			goto out_nofds;
-
-		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
-			timeout = ROUND_UP(usec, 1000000/HZ);
-			timeout += sec * (unsigned long) HZ;
-		}
-	}
-
 	if (n < 0)
 		goto out_nofds;
 
@@ -1687,19 +1703,7 @@
 	zero_fd_set(n, fds.res_out);
 	zero_fd_set(n, fds.res_ex);
 
-	ret = do_select(n, &fds, &timeout);
-
-	if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
-		time_t sec = 0, usec = 0;
-		if (timeout) {
-			sec = timeout / HZ;
-			usec = timeout % HZ;
-			usec *= (1000000/HZ);
-		}
-		if (put_user(sec, &tvp->tv_sec) ||
-		    put_user(usec, &tvp->tv_usec))
-			ret = -EFAULT;
-	}
+	ret = do_select(n, &fds, timeout);
 
 	if (ret < 0)
 		goto out;
@@ -1720,6 +1724,237 @@
 	return ret;
 }
 
+asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
+	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+	struct compat_timeval __user *tvp)
+{
+	s64 timeout = -1;
+	struct compat_timeval tv;
+	int ret;
+
+	if (tvp) {
+		if (copy_from_user(&tv, tvp, sizeof(tv)))
+			return -EFAULT;
+
+		if (tv.tv_sec < 0 || tv.tv_usec < 0)
+			return -EINVAL;
+
+		/* Cast to u64 to make GCC stop complaining */
+		if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
+			timeout = -1;	/* infinite */
+		else {
+			timeout = ROUND_UP(tv.tv_usec, 1000000/HZ);
+			timeout += tv.tv_sec * HZ;
+		}
+	}
+
+	ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+
+	if (tvp) {
+		struct compat_timeval rtv;
+
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
+		rtv.tv_sec = timeout;
+		if (compat_timeval_compare(&rtv, &tv) < 0)
+			rtv = tv;
+		if (copy_to_user(tvp, &rtv, sizeof(rtv))) {
+sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND)
+				ret = -EINTR;
+		}
+	}
+
+	return ret;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
+	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+	struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
+	compat_size_t sigsetsize)
+{
+	compat_sigset_t ss32;
+	sigset_t ksigmask, sigsaved;
+	s64 timeout = MAX_SCHEDULE_TIMEOUT;
+	struct compat_timespec ts;
+	int ret;
+
+	if (tsp) {
+		if (copy_from_user(&ts, tsp, sizeof(ts)))
+			return -EFAULT;
+
+		if (ts.tv_sec < 0 || ts.tv_nsec < 0)
+			return -EINVAL;
+	}
+
+	if (sigmask) {
+		if (sigsetsize != sizeof(compat_sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+			return -EFAULT;
+		sigset_from_compat(&ksigmask, &ss32);
+
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	do {
+		if (tsp) {
+			if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
+				timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
+				timeout += ts.tv_sec * (unsigned long)HZ;
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			} else {
+				ts.tv_sec -= MAX_SELECT_SECONDS;
+				timeout = MAX_SELECT_SECONDS * HZ;
+			}
+		}
+
+		ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+
+	} while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
+
+	if (tsp && !(current->personality & STICKY_TIMEOUTS)) {
+		struct compat_timespec rts;
+
+		rts.tv_sec = timeout / HZ;
+		rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ);
+		if (rts.tv_nsec >= NSEC_PER_SEC) {
+			rts.tv_sec++;
+			rts.tv_nsec -= NSEC_PER_SEC;
+		}
+		if (compat_timespec_compare(&rts, &ts) < 0)
+			rts = ts;
+		copy_to_user(tsp, &rts, sizeof(rts));
+	}
+
+	if (ret == -ERESTARTNOHAND) {
+		/*
+		 * Don't restore the signal mask yet. Let do_signal() deliver
+		 * the signal on the way back to userspace, before the signal
+		 * mask is restored.
+		 */
+		if (sigmask) {
+			memcpy(&current->saved_sigmask, &sigsaved,
+					sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+	} else if (sigmask)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	return ret;
+}
+
+asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
+	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+	struct compat_timespec __user *tsp, void __user *sig)
+{
+	compat_size_t sigsetsize = 0;
+	compat_uptr_t up = 0;
+
+	if (sig) {
+		if (!access_ok(VERIFY_READ, sig,
+				sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
+		    	__get_user(up, (compat_uptr_t __user *)sig) ||
+		    	__get_user(sigsetsize,
+				(compat_size_t __user *)(sig+sizeof(up))))
+			return -EFAULT;
+	}
+	return compat_sys_pselect7(n, inp, outp, exp, tsp, compat_ptr(up),
+					sigsetsize);
+}
+
+asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
+	unsigned int nfds, struct compat_timespec __user *tsp,
+	const compat_sigset_t __user *sigmask, compat_size_t sigsetsize)
+{
+	compat_sigset_t ss32;
+	sigset_t ksigmask, sigsaved;
+	struct compat_timespec ts;
+	s64 timeout = -1;
+	int ret;
+
+	if (tsp) {
+		if (copy_from_user(&ts, tsp, sizeof(ts)))
+			return -EFAULT;
+
+		/* We assume that ts.tv_sec is always lower than
+		   the number of seconds that can be expressed in
+		   an s64. Otherwise the compiler bitches at us */
+		timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
+		timeout += ts.tv_sec * HZ;
+	}
+
+	if (sigmask) {
+		if (sigsetsize |= sizeof(compat_sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+			return -EFAULT;
+		sigset_from_compat(&ksigmask, &ss32);
+
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	ret = do_sys_poll(ufds, nfds, &timeout);
+
+	/* We can restart this syscall, usually */
+	if (ret == -EINTR) {
+		/*
+		 * Don't restore the signal mask yet. Let do_signal() deliver
+		 * the signal on the way back to userspace, before the signal
+		 * mask is restored.
+		 */
+		if (sigmask) {
+			memcpy(&current->saved_sigmask, &sigsaved,
+				sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+		ret = -ERESTARTNOHAND;
+	} else if (sigmask)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	if (tsp && timeout >= 0) {
+		struct compat_timespec rts;
+
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		/* Yes, we know it's actually an s64, but it's also positive. */
+		rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) *
+					1000;
+		rts.tv_sec = timeout;
+		if (compat_timespec_compare(&rts, &ts) < 0)
+			rts = ts;
+		if (copy_to_user(tsp, &rts, sizeof(rts))) {
+sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND && timeout >= 0)
+				ret = -EINTR;
+		}
+	}
+
+	return ret;
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
 #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
 /* Stuff for NFS server syscalls... */
 struct compat_nfsctl_svc {
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 5dd0207..057e602 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -931,8 +931,8 @@
 static int sg_grt_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	int err, i;
-	sg_req_info_t *r;
-	struct compat_sg_req_info *o = (struct compat_sg_req_info *)arg;
+	sg_req_info_t __user *r;
+	struct compat_sg_req_info __user *o = (void __user *)arg;
 	r = compat_alloc_user_space(sizeof(sg_req_info_t)*SG_MAX_QUEUE);
 	err = sys_ioctl(fd,cmd,(unsigned long)r);
 	if (err < 0)
@@ -2739,8 +2739,8 @@
 static int
 lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	struct compat_timeval *tc = (struct compat_timeval *)arg;
-	struct timeval *tn = compat_alloc_user_space(sizeof(struct timeval));
+	struct compat_timeval __user *tc = (struct compat_timeval __user *)arg;
+	struct timeval __user *tn = compat_alloc_user_space(sizeof(struct timeval));
 	struct timeval ts;
 	if (get_user(ts.tv_sec, &tc->tv_sec) ||
 	    get_user(ts.tv_usec, &tc->tv_usec) ||
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index 8899d9c..f70e469 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -36,6 +36,7 @@
 	int			s_type;
 	umode_t			s_mode;
 	struct dentry		* s_dentry;
+	struct iattr		* s_iattr;
 };
 
 #define CONFIGFS_ROOT		0x0001
@@ -48,10 +49,11 @@
 #define CONFIGFS_NOT_PINNED	(CONFIGFS_ITEM_ATTR)
 
 extern struct vfsmount * configfs_mount;
+extern kmem_cache_t *configfs_dir_cachep;
 
 extern int configfs_is_root(struct config_item *item);
 
-extern struct inode * configfs_new_inode(mode_t mode);
+extern struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent *);
 extern int configfs_create(struct dentry *, int mode, int (*init)(struct inode *));
 
 extern int configfs_create_file(struct config_item *, const struct configfs_attribute *);
@@ -63,6 +65,7 @@
 
 extern const unsigned char * configfs_get_name(struct configfs_dirent *sd);
 extern void configfs_drop_dentry(struct configfs_dirent *sd, struct dentry *parent);
+extern int configfs_setattr(struct dentry *dentry, struct iattr *iattr);
 
 extern int configfs_pin_fs(void);
 extern void configfs_release_fs(void);
@@ -120,8 +123,10 @@
 
 static inline void release_configfs_dirent(struct configfs_dirent * sd)
 {
-	if (!(sd->s_type & CONFIGFS_ROOT))
-		kfree(sd);
+	if (!(sd->s_type & CONFIGFS_ROOT)) {
+		kfree(sd->s_iattr);
+		kmem_cache_free(configfs_dir_cachep, sd);
+	}
 }
 
 static inline struct configfs_dirent * configfs_get(struct configfs_dirent * sd)
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index b668ec6..ca60e3a 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -72,7 +72,7 @@
 {
 	struct configfs_dirent * sd;
 
-	sd = kmalloc(sizeof(*sd), GFP_KERNEL);
+	sd = kmem_cache_alloc(configfs_dir_cachep, GFP_KERNEL);
 	if (!sd)
 		return NULL;
 
@@ -136,13 +136,19 @@
 	int error;
 	umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
 
-	error = configfs_create(d, mode, init_dir);
+	error = configfs_make_dirent(p->d_fsdata, d, k, mode,
+				     CONFIGFS_DIR);
 	if (!error) {
-		error = configfs_make_dirent(p->d_fsdata, d, k, mode,
-					   CONFIGFS_DIR);
+		error = configfs_create(d, mode, init_dir);
 		if (!error) {
 			p->d_inode->i_nlink++;
 			(d)->d_op = &configfs_dentry_ops;
+		} else {
+			struct configfs_dirent *sd = d->d_fsdata;
+			if (sd) {
+				list_del_init(&sd->s_sibling);
+				configfs_put(sd);
+			}
 		}
 	}
 	return error;
@@ -182,12 +188,19 @@
 	int err = 0;
 	umode_t mode = S_IFLNK | S_IRWXUGO;
 
-	err = configfs_create(dentry, mode, init_symlink);
+	err = configfs_make_dirent(parent->d_fsdata, dentry, sl, mode,
+				   CONFIGFS_ITEM_LINK);
 	if (!err) {
-		err = configfs_make_dirent(parent->d_fsdata, dentry, sl,
-					 mode, CONFIGFS_ITEM_LINK);
+		err = configfs_create(dentry, mode, init_symlink);
 		if (!err)
 			dentry->d_op = &configfs_dentry_ops;
+		else {
+			struct configfs_dirent *sd = dentry->d_fsdata;
+			if (sd) {
+				list_del_init(&sd->s_sibling);
+				configfs_put(sd);
+			}
+		}
 	}
 	return err;
 }
@@ -241,13 +254,15 @@
 	struct configfs_attribute * attr = sd->s_element;
 	int error;
 
-	error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, init_file);
-	if (error)
-		return error;
-
-	dentry->d_op = &configfs_dentry_ops;
 	dentry->d_fsdata = configfs_get(sd);
 	sd->s_dentry = dentry;
+	error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, init_file);
+	if (error) {
+		configfs_put(sd);
+		return error;
+	}
+
+	dentry->d_op = &configfs_dentry_ops;
 	d_rehash(dentry);
 
 	return 0;
@@ -839,6 +854,7 @@
 	.symlink	= configfs_symlink,
 	.unlink		= configfs_unlink,
 	.lookup		= configfs_lookup,
+	.setattr	= configfs_setattr,
 };
 
 #if 0
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index c26cd61..3921920 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -26,7 +26,6 @@
 
 #include <linux/fs.h>
 #include <linux/module.h>
-#include <linux/dnotify.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
@@ -150,7 +149,7 @@
 /**
  *	fill_write_buffer - copy buffer from userspace.
  *	@buffer:	data buffer for file.
- *	@userbuf:	data from user.
+ *	@buf:		data from user.
  *	@count:		number of bytes in @userbuf.
  *
  *	Allocate @buffer->page if it hasn't been already, then
@@ -177,8 +176,9 @@
 
 /**
  *	flush_write_buffer - push buffer to config_item.
- *	@file:		file pointer.
+ *	@dentry:	dentry to the attribute
  *	@buffer:	data buffer for file.
+ *	@count:		number of bytes
  *
  *	Get the correct pointers for the config_item and the attribute we're
  *	dealing with, then call the store() method for the attribute,
@@ -217,15 +217,16 @@
 configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	struct configfs_buffer * buffer = file->private_data;
+	ssize_t len;
 
 	down(&buffer->sem);
-	count = fill_write_buffer(buffer,buf,count);
-	if (count > 0)
-		count = flush_write_buffer(file->f_dentry,buffer,count);
-	if (count > 0)
-		*ppos += count;
+	len = fill_write_buffer(buffer, buf, count);
+	if (len > 0)
+		len = flush_write_buffer(file->f_dentry, buffer, count);
+	if (len > 0)
+		*ppos += len;
 	up(&buffer->sem);
-	return count;
+	return len;
 }
 
 static int check_perm(struct inode * inode, struct file * file)
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index 6577c58..c153bd9 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -31,6 +31,7 @@
 #include <linux/pagemap.h>
 #include <linux/namei.h>
 #include <linux/backing-dev.h>
+#include <linux/capability.h>
 
 #include <linux/configfs.h>
 #include "configfs_internal.h"
@@ -48,18 +49,107 @@
 	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
 };
 
-struct inode * configfs_new_inode(mode_t mode)
+static struct inode_operations configfs_inode_operations ={
+	.setattr	= configfs_setattr,
+};
+
+int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
+{
+	struct inode * inode = dentry->d_inode;
+	struct configfs_dirent * sd = dentry->d_fsdata;
+	struct iattr * sd_iattr;
+	unsigned int ia_valid = iattr->ia_valid;
+	int error;
+
+	if (!sd)
+		return -EINVAL;
+
+	sd_iattr = sd->s_iattr;
+
+	error = inode_change_ok(inode, iattr);
+	if (error)
+		return error;
+
+	error = inode_setattr(inode, iattr);
+	if (error)
+		return error;
+
+	if (!sd_iattr) {
+		/* setting attributes for the first time, allocate now */
+		sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+		if (!sd_iattr)
+			return -ENOMEM;
+		/* assign default attributes */
+		memset(sd_iattr, 0, sizeof(struct iattr));
+		sd_iattr->ia_mode = sd->s_mode;
+		sd_iattr->ia_uid = 0;
+		sd_iattr->ia_gid = 0;
+		sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
+		sd->s_iattr = sd_iattr;
+	}
+
+	/* attributes were changed atleast once in past */
+
+	if (ia_valid & ATTR_UID)
+		sd_iattr->ia_uid = iattr->ia_uid;
+	if (ia_valid & ATTR_GID)
+		sd_iattr->ia_gid = iattr->ia_gid;
+	if (ia_valid & ATTR_ATIME)
+		sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
+						inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_MTIME)
+		sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
+						inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_CTIME)
+		sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
+						inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_MODE) {
+		umode_t mode = iattr->ia_mode;
+
+		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+			mode &= ~S_ISGID;
+		sd_iattr->ia_mode = sd->s_mode = mode;
+	}
+
+	return error;
+}
+
+static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
+{
+	inode->i_mode = mode;
+	inode->i_uid = 0;
+	inode->i_gid = 0;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+
+static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
+{
+	inode->i_mode = iattr->ia_mode;
+	inode->i_uid = iattr->ia_uid;
+	inode->i_gid = iattr->ia_gid;
+	inode->i_atime = iattr->ia_atime;
+	inode->i_mtime = iattr->ia_mtime;
+	inode->i_ctime = iattr->ia_ctime;
+}
+
+struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd)
 {
 	struct inode * inode = new_inode(configfs_sb);
 	if (inode) {
-		inode->i_mode = mode;
-		inode->i_uid = 0;
-		inode->i_gid = 0;
 		inode->i_blksize = PAGE_CACHE_SIZE;
 		inode->i_blocks = 0;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		inode->i_mapping->a_ops = &configfs_aops;
 		inode->i_mapping->backing_dev_info = &configfs_backing_dev_info;
+		inode->i_op = &configfs_inode_operations;
+
+		if (sd->s_iattr) {
+			/* sysfs_dirent has non-default attributes
+			 * get them for the new inode from persistent copy
+			 * in sysfs_dirent
+			 */
+			set_inode_attr(inode, sd->s_iattr);
+		} else
+			set_default_inode_attr(inode, mode);
 	}
 	return inode;
 }
@@ -70,7 +160,8 @@
 	struct inode * inode = NULL;
 	if (dentry) {
 		if (!dentry->d_inode) {
-			if ((inode = configfs_new_inode(mode))) {
+			struct configfs_dirent *sd = dentry->d_fsdata;
+			if ((inode = configfs_new_inode(mode, sd))) {
 				if (dentry->d_parent && dentry->d_parent->d_inode) {
 					struct inode *p_inode = dentry->d_parent->d_inode;
 					p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
@@ -103,10 +194,9 @@
  */
 const unsigned char * configfs_get_name(struct configfs_dirent *sd)
 {
-	struct attribute * attr;
+	struct configfs_attribute *attr;
 
-	if (!sd || !sd->s_element)
-		BUG();
+	BUG_ON(!sd || !sd->s_element);
 
 	/* These always have a dentry, so use that */
 	if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK))
@@ -114,7 +204,7 @@
 
 	if (sd->s_type & CONFIGFS_ITEM_ATTR) {
 		attr = sd->s_element;
-		return attr->name;
+		return attr->ca_name;
 	}
 	return NULL;
 }
@@ -130,13 +220,17 @@
 
 	if (dentry) {
 		spin_lock(&dcache_lock);
+		spin_lock(&dentry->d_lock);
 		if (!(d_unhashed(dentry) && dentry->d_inode)) {
 			dget_locked(dentry);
 			__d_drop(dentry);
+			spin_unlock(&dentry->d_lock);
 			spin_unlock(&dcache_lock);
 			simple_unlink(parent->d_inode, dentry);
-		} else
+		} else {
+			spin_unlock(&dentry->d_lock);
 			spin_unlock(&dcache_lock);
+		}
 	}
 }
 
@@ -145,6 +239,10 @@
 	struct configfs_dirent * sd;
 	struct configfs_dirent * parent_sd = dir->d_fsdata;
 
+	if (dir->d_inode == NULL)
+		/* no inode means this hasn't been made visible yet */
+		return;
+
 	mutex_lock(&dir->d_inode->i_mutex);
 	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
 		if (!sd->s_element)
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index 1a2f6f6..f920d30 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -38,6 +38,7 @@
 
 struct vfsmount * configfs_mount = NULL;
 struct super_block * configfs_sb = NULL;
+kmem_cache_t *configfs_dir_cachep;
 static int configfs_mnt_count = 0;
 
 static struct super_operations configfs_ops = {
@@ -62,6 +63,7 @@
 	.s_children	= LIST_HEAD_INIT(configfs_root.s_children),
 	.s_element	= &configfs_root_group.cg_item,
 	.s_type		= CONFIGFS_ROOT,
+	.s_iattr	= NULL,
 };
 
 static int configfs_fill_super(struct super_block *sb, void *data, int silent)
@@ -73,9 +75,11 @@
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
 	sb->s_magic = CONFIGFS_MAGIC;
 	sb->s_op = &configfs_ops;
+	sb->s_time_gran = 1;
 	configfs_sb = sb;
 
-	inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
+	inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+				   &configfs_root);
 	if (inode) {
 		inode->i_op = &configfs_dir_inode_operations;
 		inode->i_fop = &configfs_dir_operations;
@@ -128,19 +132,31 @@
 
 static int __init configfs_init(void)
 {
-	int err;
+	int err = -ENOMEM;
+
+	configfs_dir_cachep = kmem_cache_create("configfs_dir_cache",
+						sizeof(struct configfs_dirent),
+						0, 0, NULL, NULL);
+	if (!configfs_dir_cachep)
+		goto out;
 
 	kset_set_kset_s(&config_subsys, kernel_subsys);
 	err = subsystem_register(&config_subsys);
-	if (err)
-		return err;
+	if (err) {
+		kmem_cache_destroy(configfs_dir_cachep);
+		configfs_dir_cachep = NULL;
+		goto out;
+	}
 
 	err = register_filesystem(&configfs_fs_type);
 	if (err) {
 		printk(KERN_ERR "configfs: Unable to register filesystem!\n");
 		subsystem_unregister(&config_subsys);
+		kmem_cache_destroy(configfs_dir_cachep);
+		configfs_dir_cachep = NULL;
 	}
 
+out:
 	return err;
 }
 
@@ -148,11 +164,13 @@
 {
 	unregister_filesystem(&configfs_fs_type);
 	subsystem_unregister(&config_subsys);
+	kmem_cache_destroy(configfs_dir_cachep);
+	configfs_dir_cachep = NULL;
 }
 
 MODULE_AUTHOR("Oracle");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.1");
+MODULE_VERSION("0.0.2");
 MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration.");
 
 module_init(configfs_init);
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index 50f5840..e5512e2 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -162,8 +162,7 @@
 	if (!(sd->s_type & CONFIGFS_ITEM_LINK))
 		goto out;
 
-	if (dentry->d_parent == configfs_sb->s_root)
-		BUG();
+	BUG_ON(dentry->d_parent == configfs_sb->s_root);
 
 	sl = sd->s_element;
 
@@ -277,5 +276,6 @@
 	.follow_link = configfs_follow_link,
 	.readlink = generic_readlink,
 	.put_link = configfs_put_link,
+	.setattr = configfs_setattr,
 };
 
diff --git a/fs/dcache.c b/fs/dcache.c
index 86bdb93..a173bba 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -743,7 +743,9 @@
 	dentry->d_op = NULL;
 	dentry->d_fsdata = NULL;
 	dentry->d_mounted = 0;
+#ifdef CONFIG_PROFILING
 	dentry->d_cookie = NULL;
+#endif
 	INIT_HLIST_NODE(&dentry->d_hash);
 	INIT_LIST_HEAD(&dentry->d_lru);
 	INIT_LIST_HEAD(&dentry->d_subdirs);
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index efc97d9..d575452 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -56,7 +56,7 @@
 DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
 
 /**
- * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
+ * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write an unsigned 8 bit value.
  *
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have
@@ -98,7 +98,7 @@
 DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
 
 /**
- * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
+ * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write an unsigned 16 bit value.
  *
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have
@@ -140,7 +140,7 @@
 DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
 
 /**
- * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
+ * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write an unsigned 32 bit value.
  *
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 30dbbd1..848044a 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -857,6 +857,7 @@
 			/* Handle holes */
 			if (!buffer_mapped(map_bh)) {
 				char *kaddr;
+				loff_t i_size_aligned;
 
 				/* AKPM: eargh, -ENOTBLK is a hack */
 				if (dio->rw == WRITE) {
@@ -864,8 +865,14 @@
 					return -ENOTBLK;
 				}
 
+				/*
+				 * Be sure to account for a partial block as the
+				 * last block in the file
+				 */
+				i_size_aligned = ALIGN(i_size_read(dio->inode),
+							1 << blkbits);
 				if (dio->block_in_file >=
-					i_size_read(dio->inode)>>blkbits) {
+						i_size_aligned >> blkbits) {
 					/* We hit eof */
 					page_cache_release(page);
 					goto out;
diff --git a/fs/exec.c b/fs/exec.c
index 62b40af..055378d 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -477,7 +477,7 @@
 	int err;
 	struct file *file;
 
-	err = path_lookup_open(name, LOOKUP_FOLLOW, &nd, FMODE_READ);
+	err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ);
 	file = ERR_PTR(err);
 
 	if (!err) {
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 5bfe400..b06b54f 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -11,6 +11,33 @@
 
 #define dprintk(fmt, args...) do{}while(0)
 
+static struct dentry *
+find_acceptable_alias(struct dentry *result,
+		int (*acceptable)(void *context, struct dentry *dentry),
+		void *context)
+{
+	struct dentry *dentry, *toput = NULL;
+
+	spin_lock(&dcache_lock);
+	list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
+		dget_locked(dentry);
+		spin_unlock(&dcache_lock);
+		if (toput)
+			dput(toput);
+		if (dentry != result && acceptable(context, dentry)) {
+			dput(result);
+			return dentry;
+		}
+		spin_lock(&dcache_lock);
+		toput = dentry;
+	}
+	spin_unlock(&dcache_lock);
+
+	if (toput)
+		dput(toput);
+	return NULL;
+}
+
 /**
  * find_exported_dentry - helper routine to implement export_operations->decode_fh
  * @sb:		The &super_block identifying the filesystem
@@ -52,8 +79,7 @@
 	struct dentry *target_dir;
 	int err;
 	struct export_operations *nops = sb->s_export_op;
-	struct list_head *le, *head;
-	struct dentry *toput = NULL;
+	struct dentry *alias;
 	int noprogress;
 	char nbuf[NAME_MAX+1];
 
@@ -79,27 +105,10 @@
 			/* there is no other dentry, so fail */
 			goto err_result;
 		}
-		/* try any other aliases */
-		spin_lock(&dcache_lock);
-		head = &result->d_inode->i_dentry;
-		list_for_each(le, head) {
-			struct dentry *dentry = list_entry(le, struct dentry, d_alias);
-			dget_locked(dentry);
-			spin_unlock(&dcache_lock);
-			if (toput)
-				dput(toput);
-			toput = NULL;
-			if (dentry != result &&
-			    acceptable(context, dentry)) {
-				dput(result);
-				return dentry;
-			}
-			spin_lock(&dcache_lock);
-			toput = dentry;
-		}
-		spin_unlock(&dcache_lock);
-		if (toput)
-			dput(toput);
+
+		alias = find_acceptable_alias(result, acceptable, context);
+		if (alias)
+			return alias;
 	}			
 
 	/* It's a directory, or we are required to confirm the file's
@@ -258,26 +267,10 @@
 	/* now result is properly connected, it is our best bet */
 	if (acceptable(context, result))
 		return result;
-	/* one last try of the aliases.. */
-	spin_lock(&dcache_lock);
-	toput = NULL;
-	head = &result->d_inode->i_dentry;
-	list_for_each(le, head) {
-		struct dentry *dentry = list_entry(le, struct dentry, d_alias);
-		dget_locked(dentry);
-		spin_unlock(&dcache_lock);
-		if (toput) dput(toput);
-		if (dentry != result &&
-		    acceptable(context, dentry)) {
-			dput(result);
-			return dentry;
-		}
-		spin_lock(&dcache_lock);
-		toput = dentry;
-	}
-	spin_unlock(&dcache_lock);
-	if (toput)
-		dput(toput);
+
+	alias = find_acceptable_alias(result, acceptable, context);
+	if (alias)
+		return alias;
 
 	/* drat - I just cannot find anything acceptable */
 	dput(result);
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 35acc43..da52b4a 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -220,7 +220,7 @@
 	struct ext2_inode_info *ei = EXT2_I(inode);
 	int name_index;
 	void *value = NULL;
-	size_t size;
+	size_t size = 0;
 	int error;
 
 	if (S_ISLNK(inode->i_mode))
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 74714af..e527652 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -605,7 +605,7 @@
 	insert_inode_hash(inode);
 
 	if (DQUOT_ALLOC_INODE(inode)) {
-		err = -ENOSPC;
+		err = -EDQUOT;
 		goto fail_drop;
 	}
 
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index e7d3f05..a717837 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -706,6 +706,7 @@
 	.bmap			= ext2_bmap,
 	.direct_IO		= ext2_direct_IO,
 	.writepages		= ext2_writepages,
+	.migratepage		= buffer_migrate_page,
 };
 
 struct address_space_operations ext2_aops_xip = {
@@ -723,6 +724,7 @@
 	.bmap			= ext2_bmap,
 	.direct_IO		= ext2_direct_IO,
 	.writepages		= ext2_writepages,
+	.migratepage		= buffer_migrate_page,
 };
 
 /*
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 8d68198..cb6f9bd 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -221,6 +221,11 @@
 		seq_puts(seq, ",grpquota");
 #endif
 
+#if defined(CONFIG_EXT2_FS_XIP)
+	if (sbi->s_mount_opt & EXT2_MOUNT_XIP)
+		seq_puts(seq, ",xip");
+#endif
+
 	return 0;
 }
 
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 47a9da2..0d21d55 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -226,7 +226,7 @@
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	int name_index;
 	void *value = NULL;
-	size_t size;
+	size_t size = 0;
 	int error;
 
 	if (S_ISLNK(inode->i_mode))
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 8824e84..3fc4238 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1559,6 +1559,7 @@
 	.invalidatepage	= ext3_invalidatepage,
 	.releasepage	= ext3_releasepage,
 	.direct_IO	= ext3_direct_IO,
+	.migratepage	= buffer_migrate_page,
 };
 
 static struct address_space_operations ext3_writeback_aops = {
@@ -1572,6 +1573,7 @@
 	.invalidatepage	= ext3_invalidatepage,
 	.releasepage	= ext3_releasepage,
 	.direct_IO	= ext3_direct_IO,
+	.migratepage	= buffer_migrate_page,
 };
 
 static struct address_space_operations ext3_journalled_aops = {
diff --git a/fs/fat/file.c b/fs/fat/file.c
index e99c5a7..88aa1ae 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -210,10 +210,30 @@
 	if (MSDOS_I(inode)->i_start == 0)
 		return 0;
 
-	/*
-	 * Write a new EOF, and get the remaining cluster chain for freeing.
-	 */
+	fat_cache_inval_inode(inode);
+
 	wait = IS_DIRSYNC(inode);
+	i_start = free_start = MSDOS_I(inode)->i_start;
+	i_logstart = MSDOS_I(inode)->i_logstart;
+
+	/* First, we write the new file size. */
+	if (!skip) {
+		MSDOS_I(inode)->i_start = 0;
+		MSDOS_I(inode)->i_logstart = 0;
+	}
+	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+	if (wait) {
+		err = fat_sync_inode(inode);
+		if (err) {
+			MSDOS_I(inode)->i_start = i_start;
+			MSDOS_I(inode)->i_logstart = i_logstart;
+			return err;
+		}
+	} else
+		mark_inode_dirty(inode);
+
+	/* Write a new EOF, and get the remaining cluster chain for freeing. */
 	if (skip) {
 		struct fat_entry fatent;
 		int ret, fclus, dclus;
@@ -244,35 +264,11 @@
 			return ret;
 
 		free_start = ret;
-		i_start = i_logstart = 0;
-		fat_cache_inval_inode(inode);
-	} else {
-		fat_cache_inval_inode(inode);
-
-		i_start = free_start = MSDOS_I(inode)->i_start;
-		i_logstart = MSDOS_I(inode)->i_logstart;
-		MSDOS_I(inode)->i_start = 0;
-		MSDOS_I(inode)->i_logstart = 0;
 	}
-	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
-	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
-	if (wait) {
-		err = fat_sync_inode(inode);
-		if (err)
-			goto error;
-	} else
-		mark_inode_dirty(inode);
 	inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);
 
 	/* Freeing the remained cluster chain */
 	return fat_free_clusters(inode, free_start);
-
-error:
-	if (i_start) {
-		MSDOS_I(inode)->i_start = i_start;
-		MSDOS_I(inode)->i_logstart = i_logstart;
-	}
-	return err;
 }
 
 void fat_truncate(struct inode *inode)
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 32fb0a3..944652e 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -196,19 +196,9 @@
 
 int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
 {
-	int i, e, err = 0;
+	int i, err = 0;
 
-	for (i = 0; i < nr_bhs; i++) {
-		lock_buffer(bhs[i]);
-		if (test_clear_buffer_dirty(bhs[i])) {
-			get_bh(bhs[i]);
-			bhs[i]->b_end_io = end_buffer_write_sync;
-			e = submit_bh(WRITE, bhs[i]);
-			if (!err && e)
-				err = e;
-		} else
-			unlock_buffer(bhs[i]);
-	}
+	ll_rw_block(SWRITE, nr_bhs, bhs);
 	for (i = 0; i < nr_bhs; i++) {
 		wait_on_buffer(bhs[i]);
 		if (buffer_eopnotsupp(bhs[i])) {
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 5f96786..dc4a700 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -208,8 +208,11 @@
 	struct inode * inode = filp->f_dentry->d_inode;
 	int error = 0;
 
-	/* O_APPEND cannot be cleared if the file is marked as append-only */
-	if (!(arg & O_APPEND) && IS_APPEND(inode))
+	/*
+	 * O_APPEND cannot be cleared if the file is marked as append-only
+	 * and the file is open for write.
+	 */
+	if (((arg ^ filp->f_flags) & O_APPEND) && IS_APPEND(inode))
 		return -EPERM;
 
 	/* O_NOATIME can only be set by the owner or superuser */
diff --git a/fs/file.c b/fs/file.c
index fd066b2..cea7cbe 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -379,7 +379,6 @@
 void __init files_defer_init(void)
 {
 	int i;
-	/* Really early - can't use for_each_cpu */
-	for (i = 0; i < NR_CPUS; i++)
+	for_each_cpu(i)
 		fdtable_defer_list_init(i);
 }
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 4526da8..f556a0d 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -120,9 +120,9 @@
 	return do_get_request(fc);
 }
 
+/* Must be called with fuse_lock held */
 static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
 {
-	spin_lock(&fuse_lock);
 	if (req->preallocated) {
 		atomic_dec(&fc->num_waiting);
 		list_add(&req->list, &fc->unused_list);
@@ -134,11 +134,19 @@
 		fc->outstanding_debt--;
 	else
 		up(&fc->outstanding_sem);
-	spin_unlock(&fuse_lock);
 }
 
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 {
+	if (atomic_dec_and_test(&req->count)) {
+		spin_lock(&fuse_lock);
+		fuse_putback_request(fc, req);
+		spin_unlock(&fuse_lock);
+	}
+}
+
+static void fuse_put_request_locked(struct fuse_conn *fc, struct fuse_req *req)
+{
 	if (atomic_dec_and_test(&req->count))
 		fuse_putback_request(fc, req);
 }
@@ -163,26 +171,36 @@
  * still waiting), the 'end' callback is called if given, else the
  * reference to the request is released
  *
+ * Releasing extra reference for foreground requests must be done
+ * within the same locked region as setting state to finished.  This
+ * is because fuse_reset_request() may be called after request is
+ * finished and it must be the sole possessor.  If request is
+ * interrupted and put in the background, it will return with an error
+ * and hence never be reset and reused.
+ *
  * Called with fuse_lock, unlocks it
  */
 static void request_end(struct fuse_conn *fc, struct fuse_req *req)
 {
-	void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
-	req->end = NULL;
 	list_del(&req->list);
 	req->state = FUSE_REQ_FINISHED;
-	spin_unlock(&fuse_lock);
-	if (req->background) {
+	if (!req->background) {
+		wake_up(&req->waitq);
+		fuse_put_request_locked(fc, req);
+		spin_unlock(&fuse_lock);
+	} else {
+		void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
+		req->end = NULL;
+		spin_unlock(&fuse_lock);
 		down_read(&fc->sbput_sem);
 		if (fc->mounted)
 			fuse_release_background(req);
 		up_read(&fc->sbput_sem);
+		if (end)
+			end(fc, req);
+		else
+			fuse_put_request(fc, req);
 	}
-	wake_up(&req->waitq);
-	if (end)
-		end(fc, req);
-	else
-		fuse_put_request(fc, req);
 }
 
 /*
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index a7ef5e7..2963516 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -335,9 +335,14 @@
 	loff_t pos = page_offset(req->pages[0]);
 	size_t count = req->num_pages << PAGE_CACHE_SHIFT;
 	req->out.page_zeroing = 1;
-	req->end = fuse_readpages_end;
 	fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
-	request_send_background(fc, req);
+	if (fc->async_read) {
+		req->end = fuse_readpages_end;
+		request_send_background(fc, req);
+	} else {
+		request_send(fc, req);
+		fuse_readpages_end(fc, req);
+	}
 }
 
 struct fuse_readpages_data {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 46cf933..4a83adf 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -272,6 +272,9 @@
 	    reply, before any other request, and never cleared */
 	unsigned conn_error : 1;
 
+	/** Do readpages asynchronously?  Only set in INIT */
+	unsigned async_read : 1;
+
 	/*
 	 * The following bitfields are only for optimization purposes
 	 * and hence races in setting them will not cause malfunction
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index c755a04..879e6fb 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -473,6 +473,16 @@
 	if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION)
 		fc->conn_error = 1;
 	else {
+		unsigned long ra_pages;
+
+		if (arg->minor >= 6) {
+			ra_pages = arg->max_readahead / PAGE_CACHE_SIZE;
+			if (arg->flags & FUSE_ASYNC_READ)
+				fc->async_read = 1;
+		} else
+			ra_pages = fc->max_read / PAGE_CACHE_SIZE;
+
+		fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
 		fc->minor = arg->minor;
 		fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
 	}
@@ -496,6 +506,8 @@
 
 	arg->major = FUSE_KERNEL_VERSION;
 	arg->minor = FUSE_KERNEL_MINOR_VERSION;
+	arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
+	arg->flags |= FUSE_ASYNC_READ;
 	req->in.h.opcode = FUSE_INIT;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(*arg);
@@ -552,8 +564,6 @@
 	fc->user_id = d.user_id;
 	fc->group_id = d.group_id;
 	fc->max_read = d.max_read;
-	if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
-		fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
 
 	/* Used by get_root_inode() */
 	sb->s_fs_info = fc;
diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c
index 89450ae..f13f149 100644
--- a/fs/hfs/bfind.c
+++ b/fs/hfs/bfind.c
@@ -64,7 +64,6 @@
 		else
 			e = rec - 1;
 	} while (b <= e);
-	//printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
 	if (rec != e && e >= 0) {
 		len = hfs_brec_lenoff(bnode, e, &off);
 		keylen = hfs_brec_keylen(bnode, e);
@@ -127,7 +126,7 @@
 	return res;
 
 invalid:
-	printk("HFS: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
+	printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
 		height, bnode->height, bnode->type, nidx, parent);
 	res = -EIO;
 release:
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index 3d5cdc6..a7a7d77 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -198,7 +198,7 @@
 
 	// move down?
 	if (!node->prev && !node->next) {
-		printk("hfs_btree_del_level\n");
+		printk(KERN_DEBUG "hfs_btree_del_level\n");
 	}
 	if (!node->parent) {
 		tree->root = 0;
@@ -219,7 +219,7 @@
 	struct hfs_bnode *node;
 
 	if (cnid >= tree->node_count) {
-		printk("HFS: request for non-existent node %d in B*Tree\n", cnid);
+		printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
 		return NULL;
 	}
 
@@ -242,7 +242,7 @@
 	loff_t off;
 
 	if (cnid >= tree->node_count) {
-		printk("HFS: request for non-existent node %d in B*Tree\n", cnid);
+		printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
 		return NULL;
 	}
 
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
index 7d8fff2..5c87cf4 100644
--- a/fs/hfs/brec.c
+++ b/fs/hfs/brec.c
@@ -362,7 +362,7 @@
 		end_off = hfs_bnode_read_u16(parent, end_rec_off);
 		if (end_rec_off - end_off < diff) {
 
-			printk("splitting index node...\n");
+			printk(KERN_DEBUG "hfs: splitting index node...\n");
 			fd->bnode = parent;
 			new_node = hfs_bnode_split(fd);
 			if (IS_ERR(new_node))
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 394725e..7bb11ed 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -111,7 +111,7 @@
 		while ((node = tree->node_hash[i])) {
 			tree->node_hash[i] = node->next_hash;
 			if (atomic_read(&node->refcnt))
-				printk("HFS: node %d:%d still has %d user(s)!\n",
+				printk(KERN_ERR "hfs: node %d:%d still has %d user(s)!\n",
 					node->tree->cnid, node->this, atomic_read(&node->refcnt));
 			hfs_bnode_free(node);
 			tree->node_hash_cnt--;
@@ -252,7 +252,7 @@
 		kunmap(*pagep);
 		nidx = node->next;
 		if (!nidx) {
-			printk("create new bmap node...\n");
+			printk(KERN_DEBUG "hfs: create new bmap node...\n");
 			next_node = hfs_bmap_new_bmap(node, idx);
 		} else
 			next_node = hfs_bnode_find(tree, nidx);
@@ -292,7 +292,7 @@
 		hfs_bnode_put(node);
 		if (!i) {
 			/* panic */;
-			printk("HFS: unable to free bnode %u. bmap not found!\n", node->this);
+			printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this);
 			return;
 		}
 		node = hfs_bnode_find(tree, i);
@@ -300,7 +300,7 @@
 			return;
 		if (node->type != HFS_NODE_MAP) {
 			/* panic */;
-			printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type);
+			printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type);
 			hfs_bnode_put(node);
 			return;
 		}
@@ -313,7 +313,7 @@
 	m = 1 << (~nidx & 7);
 	byte = data[off];
 	if (!(byte & m)) {
-		printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type);
+		printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type);
 		kunmap(page);
 		hfs_bnode_put(node);
 		return;
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 2fcd679..ba85157 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -184,7 +184,7 @@
 
 	type = rec.type;
 	if (type != HFS_CDR_THD && type != HFS_CDR_FTH) {
-		printk("HFS-fs: Found bad thread record in catalog\n");
+		printk(KERN_ERR "hfs: found bad thread record in catalog\n");
 		return -EIO;
 	}
 
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index e1f24be..534e5a7 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -81,12 +81,12 @@
 	case 1:
 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
 		if (entry.type != HFS_CDR_THD) {
-			printk("HFS: bad catalog folder thread\n");
+			printk(KERN_ERR "hfs: bad catalog folder thread\n");
 			err = -EIO;
 			goto out;
 		}
 		//if (fd.entrylength < HFS_MIN_THREAD_SZ) {
-		//	printk("HFS: truncated catalog thread\n");
+		//	printk(KERN_ERR "hfs: truncated catalog thread\n");
 		//	err = -EIO;
 		//	goto out;
 		//}
@@ -105,7 +105,7 @@
 
 	for (;;) {
 		if (be32_to_cpu(fd.key->cat.ParID) != inode->i_ino) {
-			printk("HFS: walked past end of dir\n");
+			printk(KERN_ERR "hfs: walked past end of dir\n");
 			err = -EIO;
 			goto out;
 		}
@@ -114,7 +114,7 @@
 		len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName);
 		if (type == HFS_CDR_DIR) {
 			if (fd.entrylength < sizeof(struct hfs_cat_dir)) {
-				printk("HFS: small dir entry\n");
+				printk(KERN_ERR "hfs: small dir entry\n");
 				err = -EIO;
 				goto out;
 			}
@@ -123,7 +123,7 @@
 				break;
 		} else if (type == HFS_CDR_FIL) {
 			if (fd.entrylength < sizeof(struct hfs_cat_file)) {
-				printk("HFS: small file entry\n");
+				printk(KERN_ERR "hfs: small file entry\n");
 				err = -EIO;
 				goto out;
 			}
@@ -131,7 +131,7 @@
 				    be32_to_cpu(entry.file.FlNum), DT_REG))
 				break;
 		} else {
-			printk("HFS: bad catalog entry type %d\n", type);
+			printk(KERN_ERR "hfs: bad catalog entry type %d\n", type);
 			err = -EIO;
 			goto out;
 		}
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index cc5dcd5..18ce47a 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -35,9 +35,6 @@
 #define dprint(flg, fmt, args...) \
 	if (flg & DBG_MASK) printk(fmt , ## args)
 
-#define hfs_warn(format, args...) printk(KERN_WARNING format , ## args)
-#define hfs_error(format, args...) printk(KERN_ERR format , ## args)
-
 /*
  * struct hfs_inode_info
  *
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 050a492..39fd85b 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -95,7 +95,6 @@
 		} while (--i && nidx < tree->node_count);
 		spin_unlock(&tree->hash_lock);
 	}
-	//printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
 	return res ? try_to_free_buffers(page) : 0;
 }
 
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index 0a473f7..b4651e1 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -47,7 +47,7 @@
 			*start = (sector_t)te.cdte_addr.lba << 2;
 			return 0;
 		}
-		printk(KERN_ERR "HFS: Invalid session number or type of track\n");
+		printk(KERN_ERR "hfs: invalid session number or type of track\n");
 		return -EINVAL;
 	}
 	ms_info.addr_format = CDROM_LBA;
@@ -100,7 +100,7 @@
 
 	HFS_SB(sb)->alloc_blksz = size = be32_to_cpu(mdb->drAlBlkSiz);
 	if (!size || (size & (HFS_SECTOR_SIZE - 1))) {
-		hfs_warn("hfs_fs: bad allocation block size %d\n", size);
+		printk(KERN_ERR "hfs: bad allocation block size %d\n", size);
 		goto out_bh;
 	}
 
@@ -117,7 +117,7 @@
 		size >>= 1;
 	brelse(bh);
 	if (!sb_set_blocksize(sb, size)) {
-		printk("hfs_fs: unable to set blocksize to %u\n", size);
+		printk(KERN_ERR "hfs: unable to set blocksize to %u\n", size);
 		goto out;
 	}
 
@@ -161,8 +161,8 @@
 	}
 
 	if (!HFS_SB(sb)->alt_mdb) {
-		hfs_warn("hfs_fs: unable to locate alternate MDB\n");
-		hfs_warn("hfs_fs: continuing without an alternate MDB\n");
+		printk(KERN_WARNING "hfs: unable to locate alternate MDB\n");
+		printk(KERN_WARNING "hfs: continuing without an alternate MDB\n");
 	}
 
 	HFS_SB(sb)->bitmap = (__be32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
@@ -177,7 +177,7 @@
 	while (size) {
 		bh = sb_bread(sb, off >> sb->s_blocksize_bits);
 		if (!bh) {
-			hfs_warn("hfs_fs: unable to read volume bitmap\n");
+			printk(KERN_ERR "hfs: unable to read volume bitmap\n");
 			goto out;
 		}
 		off2 = off & (sb->s_blocksize - 1);
@@ -191,23 +191,23 @@
 
 	HFS_SB(sb)->ext_tree = hfs_btree_open(sb, HFS_EXT_CNID, hfs_ext_keycmp);
 	if (!HFS_SB(sb)->ext_tree) {
-		hfs_warn("hfs_fs: unable to open extent tree\n");
+		printk(KERN_ERR "hfs: unable to open extent tree\n");
 		goto out;
 	}
 	HFS_SB(sb)->cat_tree = hfs_btree_open(sb, HFS_CAT_CNID, hfs_cat_keycmp);
 	if (!HFS_SB(sb)->cat_tree) {
-		hfs_warn("hfs_fs: unable to open catalog tree\n");
+		printk(KERN_ERR "hfs: unable to open catalog tree\n");
 		goto out;
 	}
 
 	attrib = mdb->drAtrb;
 	if (!(attrib & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) {
-		hfs_warn("HFS-fs warning: Filesystem was not cleanly unmounted, "
+		printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
 			 "running fsck.hfs is recommended.  mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
 	}
 	if ((attrib & cpu_to_be16(HFS_SB_ATTRIB_SLOCK))) {
-		hfs_warn("HFS-fs: Filesystem is marked locked, mounting read-only.\n");
+		printk(KERN_WARNING "hfs: filesystem is marked locked, mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
 	}
 	if (!(sb->s_flags & MS_RDONLY)) {
@@ -303,7 +303,7 @@
 		while (size) {
 			bh = sb_bread(sb, block);
 			if (!bh) {
-				hfs_warn("hfs_fs: unable to read volume bitmap\n");
+				printk(KERN_ERR "hfs: unable to read volume bitmap\n");
 				break;
 			}
 			len = min((int)sb->s_blocksize - off, size);
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index c5074ae..1181d11 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -101,12 +101,12 @@
 		return 0;
 	if (!(*flags & MS_RDONLY)) {
 		if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) {
-			printk("HFS-fs warning: Filesystem was not cleanly unmounted, "
+			printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
 			       "running fsck.hfs is recommended.  leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
 			*flags |= MS_RDONLY;
 		} else if (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_SLOCK)) {
-			printk("HFS-fs: Filesystem is marked locked, leaving read-only.\n");
+			printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
 			*flags |= MS_RDONLY;
 		}
@@ -229,21 +229,21 @@
 		switch (token) {
 		case opt_uid:
 			if (match_int(&args[0], &tmp)) {
-				printk("HFS: uid requires an argument\n");
+				printk(KERN_ERR "hfs: uid requires an argument\n");
 				return 0;
 			}
 			hsb->s_uid = (uid_t)tmp;
 			break;
 		case opt_gid:
 			if (match_int(&args[0], &tmp)) {
-				printk("HFS: gid requires an argument\n");
+				printk(KERN_ERR "hfs: gid requires an argument\n");
 				return 0;
 			}
 			hsb->s_gid = (gid_t)tmp;
 			break;
 		case opt_umask:
 			if (match_octal(&args[0], &tmp)) {
-				printk("HFS: umask requires a value\n");
+				printk(KERN_ERR "hfs: umask requires a value\n");
 				return 0;
 			}
 			hsb->s_file_umask = (umode_t)tmp;
@@ -251,39 +251,39 @@
 			break;
 		case opt_file_umask:
 			if (match_octal(&args[0], &tmp)) {
-				printk("HFS: file_umask requires a value\n");
+				printk(KERN_ERR "hfs: file_umask requires a value\n");
 				return 0;
 			}
 			hsb->s_file_umask = (umode_t)tmp;
 			break;
 		case opt_dir_umask:
 			if (match_octal(&args[0], &tmp)) {
-				printk("HFS: dir_umask requires a value\n");
+				printk(KERN_ERR "hfs: dir_umask requires a value\n");
 				return 0;
 			}
 			hsb->s_dir_umask = (umode_t)tmp;
 			break;
 		case opt_part:
 			if (match_int(&args[0], &hsb->part)) {
-				printk("HFS: part requires an argument\n");
+				printk(KERN_ERR "hfs: part requires an argument\n");
 				return 0;
 			}
 			break;
 		case opt_session:
 			if (match_int(&args[0], &hsb->session)) {
-				printk("HFS: session requires an argument\n");
+				printk(KERN_ERR "hfs: session requires an argument\n");
 				return 0;
 			}
 			break;
 		case opt_type:
 			if (match_fourchar(&args[0], &hsb->s_type)) {
-				printk("HFS+-fs: type requires a 4 character value\n");
+				printk(KERN_ERR "hfs: type requires a 4 character value\n");
 				return 0;
 			}
 			break;
 		case opt_creator:
 			if (match_fourchar(&args[0], &hsb->s_creator)) {
-				printk("HFS+-fs: creator requires a 4 character value\n");
+				printk(KERN_ERR "hfs: creator requires a 4 character value\n");
 				return 0;
 			}
 			break;
@@ -292,13 +292,13 @@
 			break;
 		case opt_codepage:
 			if (hsb->nls_disk) {
-				printk("HFS+-fs: unable to change codepage\n");
+				printk(KERN_ERR "hfs: unable to change codepage\n");
 				return 0;
 			}
 			p = match_strdup(&args[0]);
 			hsb->nls_disk = load_nls(p);
 			if (!hsb->nls_disk) {
-				printk("HFS+-fs: unable to load codepage \"%s\"\n", p);
+				printk(KERN_ERR "hfs: unable to load codepage \"%s\"\n", p);
 				kfree(p);
 				return 0;
 			}
@@ -306,13 +306,13 @@
 			break;
 		case opt_iocharset:
 			if (hsb->nls_io) {
-				printk("HFS: unable to change iocharset\n");
+				printk(KERN_ERR "hfs: unable to change iocharset\n");
 				return 0;
 			}
 			p = match_strdup(&args[0]);
 			hsb->nls_io = load_nls(p);
 			if (!hsb->nls_io) {
-				printk("HFS: unable to load iocharset \"%s\"\n", p);
+				printk(KERN_ERR "hfs: unable to load iocharset \"%s\"\n", p);
 				kfree(p);
 				return 0;
 			}
@@ -326,7 +326,7 @@
 	if (hsb->nls_disk && !hsb->nls_io) {
 		hsb->nls_io = load_nls_default();
 		if (!hsb->nls_io) {
-			printk("HFS: unable to load default iocharset\n");
+			printk(KERN_ERR "hfs: unable to load default iocharset\n");
 			return 0;
 		}
 	}
@@ -364,7 +364,7 @@
 
 	res = -EINVAL;
 	if (!parse_options((char *)data, sbi)) {
-		hfs_warn("hfs_fs: unable to parse mount options.\n");
+		printk(KERN_ERR "hfs: unable to parse mount options.\n");
 		goto bail;
 	}
 
@@ -375,7 +375,7 @@
 	res = hfs_mdb_get(sb);
 	if (res) {
 		if (!silent)
-			hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
+			printk(KERN_WARNING "hfs: can't find a HFS filesystem on dev %s.\n",
 				hfs_mdb_name(sb));
 		res = -EINVAL;
 		goto bail;
@@ -407,7 +407,7 @@
 bail_iput:
 	iput(root_inode);
 bail_no_root:
-	hfs_warn("hfs_fs: get root inode failed.\n");
+	printk(KERN_ERR "hfs: get root inode failed.\n");
 bail:
 	hfs_mdb_put(sb);
 	return res;
@@ -454,7 +454,7 @@
 {
 	unregister_filesystem(&hfs_fs_type);
 	if (kmem_cache_destroy(hfs_inode_cachep))
-		printk(KERN_INFO "hfs_inode_cache: not all structures were freed\n");
+		printk(KERN_ERR "hfs_inode_cache: not all structures were freed\n");
 }
 
 module_init(init_hfs_fs)
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 257cdde..5007a41 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -64,7 +64,6 @@
 		else
 			e = rec - 1;
 	} while (b <= e);
-	//printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
 	if (rec != e && e >= 0) {
 		len = hfs_brec_lenoff(bnode, e, &off);
 		keylen = hfs_brec_keylen(bnode, e);
@@ -127,7 +126,7 @@
 	return res;
 
 invalid:
-	printk("HFS+-fs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
+	printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
 		height, bnode->height, bnode->type, nidx, parent);
 	res = -EIO;
 release:
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 930cd92..8f07e8f 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -358,7 +358,7 @@
 
 	// move down?
 	if (!node->prev && !node->next) {
-		printk("hfs_btree_del_level\n");
+		printk(KERN_DEBUG "hfs_btree_del_level\n");
 	}
 	if (!node->parent) {
 		tree->root = 0;
@@ -379,7 +379,7 @@
 	struct hfs_bnode *node;
 
 	if (cnid >= tree->node_count) {
-		printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid);
+		printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
 		return NULL;
 	}
 
@@ -402,7 +402,7 @@
 	loff_t off;
 
 	if (cnid >= tree->node_count) {
-		printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid);
+		printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
 		return NULL;
 	}
 
@@ -576,8 +576,9 @@
 	node = hfs_bnode_findhash(tree, num);
 	spin_unlock(&tree->hash_lock);
 	if (node) {
-		printk("new node %u already hashed?\n", num);
-		BUG();
+		printk(KERN_CRIT "new node %u already hashed?\n", num);
+		WARN_ON(1);
+		return node;
 	}
 	node = __hfs_bnode_create(tree, num);
 	if (!node)
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index 0ccef2a..c88e5d7 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -360,7 +360,7 @@
 		end_off = hfs_bnode_read_u16(parent, end_rec_off);
 		if (end_rec_off - end_off < diff) {
 
-			printk("splitting index node...\n");
+			printk(KERN_DEBUG "hfs: splitting index node...\n");
 			fd->bnode = parent;
 			new_node = hfs_bnode_split(fd);
 			if (IS_ERR(new_node))
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 44326aa..a67edfa 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -31,17 +31,8 @@
 
 	init_MUTEX(&tree->tree_lock);
 	spin_lock_init(&tree->hash_lock);
-	/* Set the correct compare function */
 	tree->sb = sb;
 	tree->cnid = id;
-	if (id == HFSPLUS_EXT_CNID) {
-		tree->keycmp = hfsplus_ext_cmp_key;
-	} else if (id == HFSPLUS_CAT_CNID) {
-		tree->keycmp = hfsplus_cat_cmp_key;
-	} else {
-		printk("HFS+-fs: unknown B*Tree requested\n");
-		goto free_tree;
-	}
 	tree->inode = iget(sb, id);
 	if (!tree->inode)
 		goto free_tree;
@@ -64,6 +55,20 @@
 	tree->max_key_len = be16_to_cpu(head->max_key_len);
 	tree->depth = be16_to_cpu(head->depth);
 
+	/* Set the correct compare function */
+	if (id == HFSPLUS_EXT_CNID) {
+		tree->keycmp = hfsplus_ext_cmp_key;
+	} else if (id == HFSPLUS_CAT_CNID) {
+		if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
+		    (head->key_type == HFSPLUS_KEY_BINARY))
+			tree->keycmp = hfsplus_cat_bin_cmp_key;
+		else
+			tree->keycmp = hfsplus_cat_case_cmp_key;
+	} else {
+		printk(KERN_ERR "hfs: unknown B*Tree requested\n");
+		goto fail_page;
+	}
+
 	size = tree->node_size;
 	if (!size || size & (size - 1))
 		goto fail_page;
@@ -99,7 +104,7 @@
 		while ((node = tree->node_hash[i])) {
 			tree->node_hash[i] = node->next_hash;
 			if (atomic_read(&node->refcnt))
-				printk("HFS+: node %d:%d still has %d user(s)!\n",
+				printk(KERN_CRIT "hfs: node %d:%d still has %d user(s)!\n",
 					node->tree->cnid, node->this, atomic_read(&node->refcnt));
 			hfs_bnode_free(node);
 			tree->node_hash_cnt--;
@@ -223,10 +228,6 @@
 						tree->free_nodes--;
 						mark_inode_dirty(tree->inode);
 						hfs_bnode_put(node);
-						if (!idx) {
-							printk("unexpected idx %u (%u)\n", idx, node->this);
-							BUG();
-						}
 						return hfs_bnode_create(tree, idx);
 					}
 				}
@@ -242,7 +243,7 @@
 		kunmap(*pagep);
 		nidx = node->next;
 		if (!nidx) {
-			printk("create new bmap node...\n");
+			printk(KERN_DEBUG "hfs: create new bmap node...\n");
 			next_node = hfs_bmap_new_bmap(node, idx);
 		} else
 			next_node = hfs_bnode_find(tree, nidx);
@@ -284,7 +285,7 @@
 		hfs_bnode_put(node);
 		if (!i) {
 			/* panic */;
-			printk("HFS: unable to free bnode %u. bmap not found!\n", node->this);
+			printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this);
 			return;
 		}
 		node = hfs_bnode_find(tree, i);
@@ -292,7 +293,7 @@
 			return;
 		if (node->type != HFS_NODE_MAP) {
 			/* panic */;
-			printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type);
+			printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type);
 			hfs_bnode_put(node);
 			return;
 		}
@@ -305,7 +306,7 @@
 	m = 1 << (~nidx & 7);
 	byte = data[off];
 	if (!(byte & m)) {
-		printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type);
+		printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type);
 		kunmap(page);
 		hfs_bnode_put(node);
 		return;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 9471279..f2d7c49 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -13,7 +13,8 @@
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 
-int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
+int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *k1,
+			     const hfsplus_btree_key *k2)
 {
 	__be32 k1p, k2p;
 
@@ -22,7 +23,20 @@
 	if (k1p != k2p)
 		return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
 
-	return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name);
+	return hfsplus_strcasecmp(&k1->cat.name, &k2->cat.name);
+}
+
+int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1,
+			    const hfsplus_btree_key *k2)
+{
+	__be32 k1p, k2p;
+
+	k1p = k1->cat.parent;
+	k2p = k2->cat.parent;
+	if (k1p != k2p)
+		return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
+
+	return hfsplus_strcmp(&k1->cat.name, &k2->cat.name);
 }
 
 void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key,
@@ -80,8 +94,11 @@
 		memset(folder, 0, sizeof(*folder));
 		folder->type = cpu_to_be16(HFSPLUS_FOLDER);
 		folder->id = cpu_to_be32(inode->i_ino);
-		folder->create_date = folder->content_mod_date =
-			folder->attribute_mod_date = folder->access_date = hfsp_now2mt();
+		HFSPLUS_I(inode).create_date =
+			folder->create_date =
+			folder->content_mod_date =
+			folder->attribute_mod_date =
+			folder->access_date = hfsp_now2mt();
 		hfsplus_set_perms(inode, &folder->permissions);
 		if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
 			/* invisible and namelocked */
@@ -95,18 +112,27 @@
 		file->type = cpu_to_be16(HFSPLUS_FILE);
 		file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS);
 		file->id = cpu_to_be32(cnid);
-		file->create_date = file->content_mod_date =
-			file->attribute_mod_date = file->access_date = hfsp_now2mt();
+		HFSPLUS_I(inode).create_date =
+			file->create_date =
+			file->content_mod_date =
+			file->attribute_mod_date =
+			file->access_date = hfsp_now2mt();
 		if (cnid == inode->i_ino) {
 			hfsplus_set_perms(inode, &file->permissions);
-			file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
-			file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
+			if (S_ISLNK(inode->i_mode)) {
+				file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
+				file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
+			} else {
+				file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
+				file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
+			}
 			if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
 				file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
 		} else {
 			file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
 			file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
 			file->user_info.fdFlags = cpu_to_be16(0x100);
+			file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date;
 			file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev);
 		}
 		return sizeof(*file);
@@ -139,7 +165,7 @@
 
 	type = be16_to_cpu(tmp.type);
 	if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) {
-		printk("HFS+-fs: Found bad thread record in catalog\n");
+		printk(KERN_ERR "hfs: found bad thread record in catalog\n");
 		return -EIO;
 	}
 
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 50c8f44b..01a6fe3 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -66,25 +66,32 @@
 		}
 		cnid = be32_to_cpu(entry.file.id);
 		if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
-		    entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) {
+		    entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
+		    (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date ||
+		     entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) &&
+		    HFSPLUS_SB(sb).hidden_dir) {
 			struct qstr str;
 			char name[32];
 
 			if (dentry->d_fsdata) {
-				err = -ENOENT;
-				inode = NULL;
-				goto out;
+				/*
+				 * We found a link pointing to another link,
+				 * so ignore it and treat it as regular file.
+				 */
+				cnid = (unsigned long)dentry->d_fsdata;
+				linkid = 0;
+			} else {
+				dentry->d_fsdata = (void *)(unsigned long)cnid;
+				linkid = be32_to_cpu(entry.file.permissions.dev);
+				str.len = sprintf(name, "iNode%d", linkid);
+				str.name = name;
+				hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
+				goto again;
 			}
-			dentry->d_fsdata = (void *)(unsigned long)cnid;
-			linkid = be32_to_cpu(entry.file.permissions.dev);
-			str.len = sprintf(name, "iNode%d", linkid);
-			str.name = name;
-			hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
-			goto again;
 		} else if (!dentry->d_fsdata)
 			dentry->d_fsdata = (void *)(unsigned long)cnid;
 	} else {
-		printk("HFS+-fs: Illegal catalog entry type in lookup\n");
+		printk(KERN_ERR "hfs: invalid catalog entry type in lookup\n");
 		err = -EIO;
 		goto fail;
 	}
@@ -132,12 +139,12 @@
 	case 1:
 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
 		if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
-			printk("HFS+-fs: bad catalog folder thread\n");
+			printk(KERN_ERR "hfs: bad catalog folder thread\n");
 			err = -EIO;
 			goto out;
 		}
 		if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) {
-			printk("HFS+-fs: truncated catalog thread\n");
+			printk(KERN_ERR "hfs: truncated catalog thread\n");
 			err = -EIO;
 			goto out;
 		}
@@ -156,7 +163,7 @@
 
 	for (;;) {
 		if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) {
-			printk("HFS+-fs: walked past end of dir\n");
+			printk(KERN_ERR "hfs: walked past end of dir\n");
 			err = -EIO;
 			goto out;
 		}
@@ -168,7 +175,7 @@
 			goto out;
 		if (type == HFSPLUS_FOLDER) {
 			if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
-				printk("HFS+-fs: small dir entry\n");
+				printk(KERN_ERR "hfs: small dir entry\n");
 				err = -EIO;
 				goto out;
 			}
@@ -180,7 +187,7 @@
 				break;
 		} else if (type == HFSPLUS_FILE) {
 			if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
-				printk("HFS+-fs: small file entry\n");
+				printk(KERN_ERR "hfs: small file entry\n");
 				err = -EIO;
 				goto out;
 			}
@@ -188,7 +195,7 @@
 				    be32_to_cpu(entry.file.id), DT_REG))
 				break;
 		} else {
-			printk("HFS+-fs: bad catalog entry type\n");
+			printk(KERN_ERR "hfs: bad catalog entry type\n");
 			err = -EIO;
 			goto out;
 		}
@@ -330,7 +337,8 @@
 	if (res)
 		return res;
 
-	inode->i_nlink--;
+	if (inode->i_nlink > 0)
+		inode->i_nlink--;
 	hfsplus_delete_inode(inode);
 	if (inode->i_ino != cnid && !inode->i_nlink) {
 		if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
@@ -339,7 +347,8 @@
 				hfsplus_delete_inode(inode);
 		} else
 			inode->i_flags |= S_DEAD;
-	}
+	} else
+		inode->i_nlink = 0;
 	inode->i_ctime = CURRENT_TIME_SEC;
 	mark_inode_dirty(inode);
 
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index e3ff56a..1a74800 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -16,7 +16,8 @@
 #include "hfsplus_raw.h"
 
 /* Compare two extents keys, returns 0 on same, pos/neg for difference */
-int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
+int hfsplus_ext_cmp_key(const hfsplus_btree_key *k1,
+			const hfsplus_btree_key *k2)
 {
 	__be32 k1id, k2id;
 	__be32 k1s, k2s;
@@ -349,10 +350,9 @@
 
 	if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) {
 		// extend alloc file
-		printk("extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
+		printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
 			HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks);
 		return -ENOSPC;
-		//BUG();
 	}
 
 	down(&HFSPLUS_I(inode).extents_lock);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 0fa1ab6..7ae3936 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -36,7 +36,7 @@
 #define HFSPLUS_TYPE_DATA 0x00
 #define HFSPLUS_TYPE_RSRC 0xFF
 
-typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *);
+typedef int (*btree_keycmp)(const hfsplus_btree_key *, const hfsplus_btree_key *);
 
 #define NODE_HASH_SIZE	256
 
@@ -149,6 +149,7 @@
 #define HFSPLUS_SB_WRITEBACKUP	0x0001
 #define HFSPLUS_SB_NODECOMPOSE	0x0002
 #define HFSPLUS_SB_FORCE	0x0004
+#define HFSPLUS_SB_HFSX		0x0008
 
 
 struct hfsplus_inode_info {
@@ -165,6 +166,7 @@
 	struct inode *rsrc_inode;
 	unsigned long flags;
 
+	__be32 create_date;
 	/* Device number in hfsplus_permissions in catalog */
 	u32 dev;
 	/* BSD system and user file flags */
@@ -303,7 +305,8 @@
 int hfs_brec_goto(struct hfs_find_data *, int);
 
 /* catalog.c */
-int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
+int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
+int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
 void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *);
 int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *);
 int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
@@ -312,7 +315,7 @@
 		       struct inode *, struct qstr *);
 
 /* extents.c */
-int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
+int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
 void hfsplus_ext_write_extent(struct inode *);
 int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
 int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int);
@@ -350,7 +353,8 @@
 extern u16 hfsplus_compose_table[];
 
 /* unicode.c */
-int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
+int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
+int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
 int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
 int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
 
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index b4fbed6..4920553 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -22,8 +22,10 @@
 #define HFSPLUS_SECTOR_SHIFT         9
 #define HFSPLUS_VOLHEAD_SECTOR       2
 #define HFSPLUS_VOLHEAD_SIG     0x482b
+#define HFSPLUS_VOLHEAD_SIGX    0x4858
 #define HFSPLUS_SUPER_MAGIC     0x482b
-#define HFSPLUS_CURRENT_VERSION      4
+#define HFSPLUS_MIN_VERSION          4
+#define HFSPLUS_CURRENT_VERSION      5
 
 #define HFSP_WRAP_MAGIC         0x4244
 #define HFSP_WRAP_ATTRIB_SLOCK  0x8000
@@ -41,6 +43,9 @@
 #define HFSP_HARDLINK_TYPE	0x686c6e6b	/* 'hlnk' */
 #define HFSP_HFSPLUS_CREATOR	0x6866732b	/* 'hfs+' */
 
+#define HFSP_SYMLINK_TYPE	0x736c6e6b	/* 'slnk' */
+#define HFSP_SYMLINK_CREATOR	0x72686170	/* 'rhap' */
+
 #define HFSP_MOUNT_VERSION	0x482b4c78	/* 'H+Lx' */
 
 /* Structures used on disk */
@@ -161,7 +166,7 @@
 	u16 reserved1;
 	__be32 clump_size;
 	u8 btree_type;
-	u8 reserved2;
+	u8 key_type;
 	__be32 attributes;
 	u32 reserved3[16];
 } __packed;
@@ -186,6 +191,10 @@
 #define HFSPLUS_EXCH_CNID		15	/* ExchangeFiles temp id */
 #define HFSPLUS_FIRSTUSER_CNID		16	/* first available user id */
 
+/* btree key type */
+#define HFSPLUS_KEY_CASEFOLDING		0xCF	/* case-insensitive */
+#define HFSPLUS_KEY_BINARY		0xBC	/* case-sensitive */
+
 /* HFS+ catalog entry key */
 struct hfsplus_cat_key {
 	__be16 key_len;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 7acff6c..12ed2b7 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -18,13 +18,11 @@
 
 static int hfsplus_readpage(struct file *file, struct page *page)
 {
-	//printk("readpage: %lu\n", page->index);
 	return block_read_full_page(page, hfsplus_get_block);
 }
 
 static int hfsplus_writepage(struct page *page, struct writeback_control *wbc)
 {
-	//printk("writepage: %lu\n", page->index);
 	return block_write_full_page(page, hfsplus_get_block, wbc);
 }
 
@@ -92,7 +90,6 @@
 		} while (--i && nidx < tree->node_count);
 		spin_unlock(&tree->hash_lock);
 	}
-	//printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
 	return res ? try_to_free_buffers(page) : 0;
 }
 
@@ -434,7 +431,8 @@
 		inode->i_size = 2 + be32_to_cpu(folder->valence);
 		inode->i_atime = hfsp_mt2ut(folder->access_date);
 		inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
-		inode->i_ctime = inode->i_mtime;
+		inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
+		HFSPLUS_I(inode).create_date = folder->create_date;
 		HFSPLUS_I(inode).fs_blocks = 0;
 		inode->i_op = &hfsplus_dir_inode_operations;
 		inode->i_fop = &hfsplus_dir_operations;
@@ -465,9 +463,10 @@
 		}
 		inode->i_atime = hfsp_mt2ut(file->access_date);
 		inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
-		inode->i_ctime = inode->i_mtime;
+		inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
+		HFSPLUS_I(inode).create_date = file->create_date;
 	} else {
-		printk("HFS+-fs: bad catalog entry used to create inode\n");
+		printk(KERN_ERR "hfs: bad catalog entry used to create inode\n");
 		res = -EIO;
 	}
 	return res;
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index 935dafb..dc64fac 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -83,58 +83,58 @@
 		switch (token) {
 		case opt_creator:
 			if (match_fourchar(&args[0], &sbi->creator)) {
-				printk("HFS+-fs: creator requires a 4 character value\n");
+				printk(KERN_ERR "hfs: creator requires a 4 character value\n");
 				return 0;
 			}
 			break;
 		case opt_type:
 			if (match_fourchar(&args[0], &sbi->type)) {
-				printk("HFS+-fs: type requires a 4 character value\n");
+				printk(KERN_ERR "hfs: type requires a 4 character value\n");
 				return 0;
 			}
 			break;
 		case opt_umask:
 			if (match_octal(&args[0], &tmp)) {
-				printk("HFS+-fs: umask requires a value\n");
+				printk(KERN_ERR "hfs: umask requires a value\n");
 				return 0;
 			}
 			sbi->umask = (umode_t)tmp;
 			break;
 		case opt_uid:
 			if (match_int(&args[0], &tmp)) {
-				printk("HFS+-fs: uid requires an argument\n");
+				printk(KERN_ERR "hfs: uid requires an argument\n");
 				return 0;
 			}
 			sbi->uid = (uid_t)tmp;
 			break;
 		case opt_gid:
 			if (match_int(&args[0], &tmp)) {
-				printk("HFS+-fs: gid requires an argument\n");
+				printk(KERN_ERR "hfs: gid requires an argument\n");
 				return 0;
 			}
 			sbi->gid = (gid_t)tmp;
 			break;
 		case opt_part:
 			if (match_int(&args[0], &sbi->part)) {
-				printk("HFS+-fs: part requires an argument\n");
+				printk(KERN_ERR "hfs: part requires an argument\n");
 				return 0;
 			}
 			break;
 		case opt_session:
 			if (match_int(&args[0], &sbi->session)) {
-				printk("HFS+-fs: session requires an argument\n");
+				printk(KERN_ERR "hfs: session requires an argument\n");
 				return 0;
 			}
 			break;
 		case opt_nls:
 			if (sbi->nls) {
-				printk("HFS+-fs: unable to change nls mapping\n");
+				printk(KERN_ERR "hfs: unable to change nls mapping\n");
 				return 0;
 			}
 			p = match_strdup(&args[0]);
 			sbi->nls = load_nls(p);
 			if (!sbi->nls) {
-				printk("HFS+-fs: unable to load nls mapping \"%s\"\n", p);
+				printk(KERN_ERR "hfs: unable to load nls mapping \"%s\"\n", p);
 				kfree(p);
 				return 0;
 			}
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index d791780..7843f79 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -169,7 +169,7 @@
 			block = HFSPLUS_SB(sb).blockoffset;
 			block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9);
 			offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1);
-			printk("backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset,
+			printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset,
 				HFSPLUS_SB(sb).sect_count, block, offset);
 			bh = sb_bread(sb, block);
 			if (bh) {
@@ -179,7 +179,7 @@
 					mark_buffer_dirty(bh);
 					brelse(bh);
 				} else
-					printk("backup not found!\n");
+					printk(KERN_WARNING "hfs: backup not found!\n");
 			}
 		}
 		HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP;
@@ -240,18 +240,18 @@
 			return -EINVAL;
 
 		if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
-			printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
+			printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
 			       "running fsck.hfsplus is recommended.  leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
 			*flags |= MS_RDONLY;
 		} else if (sbi.flags & HFSPLUS_SB_FORCE) {
 			/* nothing */
 		} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
-			printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n");
+			printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
 			*flags |= MS_RDONLY;
 		} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
-			printk("HFS+-fs: Filesystem is marked journaled, leaving read-only.\n");
+			printk(KERN_WARNING "hfs: filesystem is marked journaled, leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
 			*flags |= MS_RDONLY;
 		}
@@ -292,8 +292,7 @@
 	INIT_HLIST_HEAD(&sbi->rsrc_inodes);
 	hfsplus_fill_defaults(sbi);
 	if (!hfsplus_parse_options(data, sbi)) {
-		if (!silent)
-			printk("HFS+-fs: unable to parse mount options\n");
+		printk(KERN_ERR "hfs: unable to parse mount options\n");
 		err = -EINVAL;
 		goto cleanup;
 	}
@@ -302,7 +301,7 @@
 	nls = sbi->nls;
 	sbi->nls = load_nls("utf8");
 	if (!sbi->nls) {
-		printk("HFS+: unable to load nls for utf8\n");
+		printk(KERN_ERR "hfs: unable to load nls for utf8\n");
 		err = -EINVAL;
 		goto cleanup;
 	}
@@ -310,17 +309,17 @@
 	/* Grab the volume header */
 	if (hfsplus_read_wrapper(sb)) {
 		if (!silent)
-			printk("HFS+-fs: unable to find HFS+ superblock\n");
+			printk(KERN_WARNING "hfs: unable to find HFS+ superblock\n");
 		err = -EINVAL;
 		goto cleanup;
 	}
 	vhdr = HFSPLUS_SB(sb).s_vhdr;
 
 	/* Copy parts of the volume header into the superblock */
-	sb->s_magic = be16_to_cpu(vhdr->signature);
-	if (be16_to_cpu(vhdr->version) != HFSPLUS_CURRENT_VERSION) {
-		if (!silent)
-			printk("HFS+-fs: wrong filesystem version\n");
+	sb->s_magic = HFSPLUS_VOLHEAD_SIG;
+	if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION ||
+	    be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) {
+		printk(KERN_ERR "hfs: wrong filesystem version\n");
 		goto cleanup;
 	}
 	HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks);
@@ -341,20 +340,17 @@
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
 
 	if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
-		if (!silent)
-			printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
-			       "running fsck.hfsplus is recommended.  mounting read-only.\n");
+		printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, "
+		       "running fsck.hfsplus is recommended.  mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
 	} else if (sbi->flags & HFSPLUS_SB_FORCE) {
 		/* nothing */
 	} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
-		if (!silent)
-			printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n");
+		printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
 	} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
-		if (!silent)
-			printk("HFS+-fs: write access to a jounaled filesystem is not supported, "
-			       "use the force option at your own risk, mounting read-only.\n");
+		printk(KERN_WARNING "hfs: write access to a jounaled filesystem is not supported, "
+		       "use the force option at your own risk, mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
 	}
 	sbi->flags &= ~HFSPLUS_SB_FORCE;
@@ -362,21 +358,18 @@
 	/* Load metadata objects (B*Trees) */
 	HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
 	if (!HFSPLUS_SB(sb).ext_tree) {
-		if (!silent)
-			printk("HFS+-fs: failed to load extents file\n");
+		printk(KERN_ERR "hfs: failed to load extents file\n");
 		goto cleanup;
 	}
 	HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
 	if (!HFSPLUS_SB(sb).cat_tree) {
-		if (!silent)
-			printk("HFS+-fs: failed to load catalog file\n");
+		printk(KERN_ERR "hfs: failed to load catalog file\n");
 		goto cleanup;
 	}
 
 	HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID);
 	if (!HFSPLUS_SB(sb).alloc_file) {
-		if (!silent)
-			printk("HFS+-fs: failed to load allocation file\n");
+		printk(KERN_ERR "hfs: failed to load allocation file\n");
 		goto cleanup;
 	}
 
@@ -384,8 +377,7 @@
 	root = iget(sb, HFSPLUS_ROOT_CNID);
 	sb->s_root = d_alloc_root(root);
 	if (!sb->s_root) {
-		if (!silent)
-			printk("HFS+-fs: failed to load root directory\n");
+		printk(KERN_ERR "hfs: failed to load root directory\n");
 		iput(root);
 		goto cleanup;
 	}
@@ -419,7 +411,7 @@
 	sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
 
 	if (!HFSPLUS_SB(sb).hidden_dir) {
-		printk("HFS+: create hidden dir...\n");
+		printk(KERN_DEBUG "hfs: create hidden dir...\n");
 		HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
 		hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode,
 				   &str, HFSPLUS_SB(sb).hidden_dir);
@@ -499,7 +491,7 @@
 {
 	unregister_filesystem(&hfsplus_fs_type);
 	if (kmem_cache_destroy(hfsplus_inode_cachep))
-		printk(KERN_INFO "hfsplus_inode_cache: not all structures were freed\n");
+		printk(KERN_ERR "hfsplus_inode_cache: not all structures were freed\n");
 }
 
 module_init(init_hfsplus_fs)
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 060c690..689c8bd 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -28,7 +28,8 @@
 }
 
 /* Compare unicode strings, return values like normal strcmp */
-int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2)
+int hfsplus_strcasecmp(const struct hfsplus_unistr *s1,
+		       const struct hfsplus_unistr *s2)
 {
 	u16 len1, len2, c1, c2;
 	const hfsplus_unichr *p1, *p2;
@@ -59,6 +60,33 @@
 	}
 }
 
+/* Compare names as a sequence of 16-bit unsigned integers */
+int hfsplus_strcmp(const struct hfsplus_unistr *s1,
+		   const struct hfsplus_unistr *s2)
+{
+	u16 len1, len2, c1, c2;
+	const hfsplus_unichr *p1, *p2;
+	int len;
+
+	len1 = be16_to_cpu(s1->length);
+	len2 = be16_to_cpu(s2->length);
+	p1 = s1->unicode;
+	p2 = s2->unicode;
+
+	for (len = min(len1, len2); len > 0; len--) {
+		c1 = be16_to_cpu(*p1);
+		c2 = be16_to_cpu(*p2);
+		if (c1 != c2)
+			return c1 < c2 ? -1 : 1;
+		p1++;
+		p2++;
+	}
+
+	return len1 < len2 ? -1 :
+	       len1 > len2 ? 1 : 0;
+}
+
+
 #define Hangul_SBase	0xac00
 #define Hangul_LBase	0x1100
 #define Hangul_VBase	0x1161
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 95455e8..72cab78 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -28,8 +28,11 @@
 {
 	u32 extent;
 	u16 attrib;
+	__be16 sig;
 
-	if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG)
+	sig = *(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG);
+	if (sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIG) &&
+	    sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX))
 		return 0;
 
 	attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
@@ -70,7 +73,7 @@
 			*start = (sector_t)te.cdte_addr.lba << 2;
 			return 0;
 		}
-		printk(KERN_ERR "HFS: Invalid session number or type of track\n");
+		printk(KERN_ERR "hfs: invalid session number or type of track\n");
 		return -EINVAL;
 	}
 	ms_info.addr_format = CDROM_LBA;
@@ -114,6 +117,10 @@
 		}
 		if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
 			break;
+		if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) {
+			HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX;
+			break;
+		}
 		brelse(bh);
 
 		/* check for a partition block
@@ -143,7 +150,7 @@
 		blocksize >>= 1;
 
 	if (sb_set_blocksize(sb, blocksize) != blocksize) {
-		printk("HFS+: unable to blocksize to %u!\n", blocksize);
+		printk(KERN_ERR "hfs: unable to set blocksize to %u!\n", blocksize);
 		return -EINVAL;
 	}
 
@@ -158,7 +165,9 @@
 		return -EIO;
 
 	/* should still be the same... */
-	if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG)
+	if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ?
+				cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) :
+				cpu_to_be16(HFSPLUS_VOLHEAD_SIG)))
 		goto error;
 	HFSPLUS_SB(sb).s_vhbh = bh;
 	HFSPLUS_SB(sb).s_vhdr = vhdr;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index f568102..b351952899 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -72,8 +72,8 @@
 	unsigned long start = vma->vm_start;
 	unsigned long end = vma->vm_end;
 	unsigned long hugepages = (end - start) >> HPAGE_SHIFT;
-	pgoff_t next = vma->vm_pgoff;
-	pgoff_t endpg = next + ((end - start) >> PAGE_SHIFT);
+	pgoff_t next = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT);
+	pgoff_t endpg = next + hugepages;
 
 	pagevec_init(&pvec, 0);
 	while (next < endpg) {
diff --git a/fs/inode.c b/fs/inode.c
index 108138d..d0be615 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1179,7 +1179,7 @@
 /**
  *	touch_atime	-	update the access time
  *	@mnt: mount the inode is accessed on
- *	@inode: inode accessed
+ *	@dentry: dentry accessed
  *
  *	Update the accessed time on an inode and mark it for writeback.
  *	This function automatically handles read only file systems and media,
diff --git a/fs/inotify.c b/fs/inotify.c
index 2fecb7a..3041503 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -33,6 +33,7 @@
 #include <linux/list.h>
 #include <linux/writeback.h>
 #include <linux/inotify.h>
+#include <linux/syscalls.h>
 
 #include <asm/ioctls.h>
 
@@ -966,7 +967,7 @@
 		mask_add = 1;
 
 	/* don't let user-space set invalid bits: we don't want flags set */
-	mask &= IN_ALL_EVENTS;
+	mask &= IN_ALL_EVENTS | IN_ONESHOT;
 	if (unlikely(!mask)) {
 		ret = -EINVAL;
 		goto out;
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index cb3cef5..e6265a0 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -338,7 +338,7 @@
 	 * done (maybe it's a new transaction, but it fell at the same
 	 * address).
 	 */
- 	if (journal->j_checkpoint_transactions == transaction ||
+ 	if (journal->j_checkpoint_transactions == transaction &&
 			transaction->t_tid == this_tid) {
 		int batch_count = 0;
 		struct buffer_head *bhs[NR_BATCH];
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 002ad2b..29e62d9 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -829,7 +829,8 @@
 	journal->j_committing_transaction = NULL;
 	spin_unlock(&journal->j_state_lock);
 
-	if (commit_transaction->t_checkpoint_list == NULL) {
+	if (commit_transaction->t_checkpoint_list == NULL &&
+	    commit_transaction->t_checkpoint_io_list == NULL) {
 		__journal_drop_transaction(journal, commit_transaction);
 	} else {
 		if (journal->j_checkpoint_transactions == NULL) {
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 429f4b2..ca91797 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1308,6 +1308,7 @@
 	transaction_t *transaction = handle->h_transaction;
 	journal_t *journal = transaction->t_journal;
 	int old_handle_count, err;
+	pid_t pid;
 
 	J_ASSERT(transaction->t_updates > 0);
 	J_ASSERT(journal_current_handle() == handle);
@@ -1333,8 +1334,15 @@
 	 * It doesn't cost much - we're about to run a commit and sleep
 	 * on IO anyway.  Speeds up many-threaded, many-dir operations
 	 * by 30x or more...
+	 *
+	 * But don't do this if this process was the most recent one to
+	 * perform a synchronous write.  We do this to detect the case where a
+	 * single process is doing a stream of sync writes.  No point in waiting
+	 * for joiners in that case.
 	 */
-	if (handle->h_sync) {
+	pid = current->pid;
+	if (handle->h_sync && journal->j_last_sync_writer != pid) {
+		journal->j_last_sync_writer = pid;
 		do {
 			old_handle_count = transaction->t_handle_count;
 			schedule_timeout_uninterruptible(1);
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index b2e9542..ce7b54b 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -1965,7 +1965,7 @@
 		iovec_cnt++;
 
 		if (JFFS_GET_PAD_BYTES(raw_inode->nsize)) {
-			static char allff[3]={255,255,255};
+			static unsigned char allff[3]={255,255,255};
 			/* Add some extra padding if necessary */
 			node_iovec[iovec_cnt].iov_base = allff;
 			node_iovec[iovec_cnt].iov_len =
diff --git a/fs/libfs.c b/fs/libfs.c
index 63c020e..71fd08f 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -388,6 +388,7 @@
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
+	inode->i_nlink = 2;
 	root = d_alloc_root(inode);
 	if (!root) {
 		iput(inode);
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 1455240..220058d 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -22,12 +22,14 @@
 #define NLMDBG_FACILITY		NLMDBG_CLIENT
 #define NLMCLNT_GRACE_WAIT	(5*HZ)
 #define NLMCLNT_POLL_TIMEOUT	(30*HZ)
+#define NLMCLNT_MAX_RETRIES	3
 
 static int	nlmclnt_test(struct nlm_rqst *, struct file_lock *);
 static int	nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
 static int	nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
 static int	nlm_stat_to_errno(u32 stat);
 static void	nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
+static int	nlmclnt_cancel(struct nlm_host *, int , struct file_lock *);
 
 static const struct rpc_call_ops nlmclnt_unlock_ops;
 static const struct rpc_call_ops nlmclnt_cancel_ops;
@@ -598,7 +600,7 @@
 	nlmclnt_finish_block(req);
 	/* Cancel the blocked request if it is still pending */
 	if (resp->status == NLM_LCK_BLOCKED)
-		nlmclnt_cancel(host, fl);
+		nlmclnt_cancel(host, req->a_args.block, fl);
 out:
 	nlmclnt_release_lockargs(req);
 	return status;
@@ -728,8 +730,7 @@
  * We always use an async RPC call for this in order not to hang a
  * process that has been Ctrl-C'ed.
  */
-int
-nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl)
+static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl)
 {
 	struct nlm_rqst	*req;
 	unsigned long	flags;
@@ -750,6 +751,7 @@
 	req->a_flags = RPC_TASK_ASYNC;
 
 	nlmclnt_setlockargs(req, fl);
+	req->a_args.block = block;
 
 	status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops);
 	if (status < 0) {
@@ -801,6 +803,9 @@
 	return;
 
 retry_cancel:
+	/* Don't ever retry more than 3 times */
+	if (req->a_retries++ >= NLMCLNT_MAX_RETRIES)
+		goto die;
 	nlm_rebind_host(req->a_host);
 	rpc_restart_call(task);
 	rpc_delay(task, 30 * HZ);
diff --git a/fs/namei.c b/fs/namei.c
index 33fb5bd..e28de84 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -30,6 +30,8 @@
 #include <linux/audit.h>
 #include <linux/capability.h>
 #include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/namei.h>
 #include <asm/namei.h>
 #include <asm/uaccess.h>
 
@@ -788,7 +790,7 @@
 
 	inode = nd->dentry->d_inode;
 	if (nd->depth)
-		lookup_flags = LOOKUP_FOLLOW;
+		lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE);
 
 	/* At this point we know we have a real path component. */
 	for(;;) {
@@ -883,7 +885,8 @@
 last_with_slashes:
 		lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
 last_component:
-		nd->flags &= ~LOOKUP_CONTINUE;
+		/* Clear LOOKUP_CONTINUE iff it was previously unset */
+		nd->flags &= lookup_flags | ~LOOKUP_CONTINUE;
 		if (lookup_flags & LOOKUP_PARENT)
 			goto lookup_parent;
 		if (this.name[0] == '.') switch (this.len) {
@@ -1063,9 +1066,12 @@
 }
 
 /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
-int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
+static int fastcall do_path_lookup(int dfd, const char *name,
+				unsigned int flags, struct nameidata *nd)
 {
 	int retval = 0;
+	int fput_needed;
+	struct file *file;
 
 	nd->last_type = LAST_ROOT; /* if there are only slashes... */
 	nd->flags = flags;
@@ -1083,22 +1089,59 @@
 		}
 		nd->mnt = mntget(current->fs->rootmnt);
 		nd->dentry = dget(current->fs->root);
-	} else {
+	} else if (dfd == AT_FDCWD) {
 		nd->mnt = mntget(current->fs->pwdmnt);
 		nd->dentry = dget(current->fs->pwd);
+	} else {
+		struct dentry *dentry;
+
+		file = fget_light(dfd, &fput_needed);
+		retval = -EBADF;
+		if (!file)
+			goto unlock_fail;
+
+		dentry = file->f_dentry;
+
+		retval = -ENOTDIR;
+		if (!S_ISDIR(dentry->d_inode->i_mode))
+			goto fput_unlock_fail;
+
+		retval = file_permission(file, MAY_EXEC);
+		if (retval)
+			goto fput_unlock_fail;
+
+		nd->mnt = mntget(file->f_vfsmnt);
+		nd->dentry = dget(dentry);
+
+		fput_light(file, fput_needed);
 	}
 	read_unlock(&current->fs->lock);
 	current->total_link_count = 0;
 	retval = link_path_walk(name, nd);
 out:
-	if (unlikely(current->audit_context
-		     && nd && nd->dentry && nd->dentry->d_inode))
+	if (likely(retval == 0)) {
+		if (unlikely(current->audit_context && nd && nd->dentry &&
+				nd->dentry->d_inode))
 		audit_inode(name, nd->dentry->d_inode, flags);
+	}
+	return retval;
+
+fput_unlock_fail:
+	fput_light(file, fput_needed);
+unlock_fail:
+	read_unlock(&current->fs->lock);
 	return retval;
 }
 
-static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags,
-		struct nameidata *nd, int open_flags, int create_mode)
+int fastcall path_lookup(const char *name, unsigned int flags,
+			struct nameidata *nd)
+{
+	return do_path_lookup(AT_FDCWD, name, flags, nd);
+}
+
+static int __path_lookup_intent_open(int dfd, const char *name,
+		unsigned int lookup_flags, struct nameidata *nd,
+		int open_flags, int create_mode)
 {
 	struct file *filp = get_empty_filp();
 	int err;
@@ -1108,7 +1151,7 @@
 	nd->intent.open.file = filp;
 	nd->intent.open.flags = open_flags;
 	nd->intent.open.create_mode = create_mode;
-	err = path_lookup(name, lookup_flags|LOOKUP_OPEN, nd);
+	err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
 	if (IS_ERR(nd->intent.open.file)) {
 		if (err == 0) {
 			err = PTR_ERR(nd->intent.open.file);
@@ -1121,32 +1164,34 @@
 
 /**
  * path_lookup_open - lookup a file path with open intent
+ * @dfd: the directory to use as base, or AT_FDCWD
  * @name: pointer to file name
  * @lookup_flags: lookup intent flags
  * @nd: pointer to nameidata
  * @open_flags: open intent flags
  */
-int path_lookup_open(const char *name, unsigned int lookup_flags,
+int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags,
 		struct nameidata *nd, int open_flags)
 {
-	return __path_lookup_intent_open(name, lookup_flags, nd,
+	return __path_lookup_intent_open(dfd, name, lookup_flags, nd,
 			open_flags, 0);
 }
 
 /**
  * path_lookup_create - lookup a file path with open + create intent
+ * @dfd: the directory to use as base, or AT_FDCWD
  * @name: pointer to file name
  * @lookup_flags: lookup intent flags
  * @nd: pointer to nameidata
  * @open_flags: open intent flags
  * @create_mode: create intent flags
  */
-static int path_lookup_create(const char *name, unsigned int lookup_flags,
-			      struct nameidata *nd, int open_flags,
-			      int create_mode)
+static int path_lookup_create(int dfd, const char *name,
+			      unsigned int lookup_flags, struct nameidata *nd,
+			      int open_flags, int create_mode)
 {
-	return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd,
-			open_flags, create_mode);
+	return __path_lookup_intent_open(dfd, name, lookup_flags|LOOKUP_CREATE,
+			nd, open_flags, create_mode);
 }
 
 int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
@@ -1156,7 +1201,7 @@
 	int err = PTR_ERR(tmp);
 
 	if (!IS_ERR(tmp)) {
-		err = __path_lookup_intent_open(tmp, lookup_flags, nd, open_flags, 0);
+		err = __path_lookup_intent_open(AT_FDCWD, tmp, lookup_flags, nd, open_flags, 0);
 		putname(tmp);
 	}
 	return err;
@@ -1248,18 +1293,24 @@
  * that namei follows links, while lnamei does not.
  * SMP-safe
  */
-int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
+int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
+			    struct nameidata *nd)
 {
 	char *tmp = getname(name);
 	int err = PTR_ERR(tmp);
 
 	if (!IS_ERR(tmp)) {
-		err = path_lookup(tmp, flags, nd);
+		err = do_path_lookup(dfd, tmp, flags, nd);
 		putname(tmp);
 	}
 	return err;
 }
 
+int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
+{
+	return __user_walk_fd(AT_FDCWD, name, flags, nd);
+}
+
 /*
  * It's inline, so penalty for filesystems that don't use sticky bit is
  * minimal.
@@ -1518,7 +1569,8 @@
  * for symlinks (where the permissions are checked later).
  * SMP-safe
  */
-int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
+int open_namei(int dfd, const char *pathname, int flag,
+		int mode, struct nameidata *nd)
 {
 	int acc_mode, error;
 	struct path path;
@@ -1540,7 +1592,8 @@
 	 * The simplest case - just a plain lookup.
 	 */
 	if (!(flag & O_CREAT)) {
-		error = path_lookup_open(pathname, lookup_flags(flag), nd, flag);
+		error = path_lookup_open(dfd, pathname, lookup_flags(flag),
+					 nd, flag);
 		if (error)
 			return error;
 		goto ok;
@@ -1549,7 +1602,7 @@
 	/*
 	 * Create - we need to know the parent.
 	 */
-	error = path_lookup_create(pathname, LOOKUP_PARENT, nd, flag, mode);
+	error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
 	if (error)
 		return error;
 
@@ -1744,7 +1797,8 @@
 	return error;
 }
 
-asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev)
+asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
+				unsigned dev)
 {
 	int error = 0;
 	char * tmp;
@@ -1757,7 +1811,7 @@
 	if (IS_ERR(tmp))
 		return PTR_ERR(tmp);
 
-	error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+	error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
 	if (error)
 		goto out;
 	dentry = lookup_create(&nd, 0);
@@ -1793,6 +1847,11 @@
 	return error;
 }
 
+asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev)
+{
+	return sys_mknodat(AT_FDCWD, filename, mode, dev);
+}
+
 int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	int error = may_create(dir, dentry, NULL);
@@ -1815,7 +1874,7 @@
 	return error;
 }
 
-asmlinkage long sys_mkdir(const char __user * pathname, int mode)
+asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
 {
 	int error = 0;
 	char * tmp;
@@ -1826,7 +1885,7 @@
 		struct dentry *dentry;
 		struct nameidata nd;
 
-		error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+		error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
 		if (error)
 			goto out;
 		dentry = lookup_create(&nd, 1);
@@ -1846,6 +1905,11 @@
 	return error;
 }
 
+asmlinkage long sys_mkdir(const char __user *pathname, int mode)
+{
+	return sys_mkdirat(AT_FDCWD, pathname, mode);
+}
+
 /*
  * We try to drop the dentry early: we should have
  * a usage count of 2 if we're the only user of this
@@ -1907,7 +1971,7 @@
 	return error;
 }
 
-asmlinkage long sys_rmdir(const char __user * pathname)
+static long do_rmdir(int dfd, const char __user *pathname)
 {
 	int error = 0;
 	char * name;
@@ -1918,7 +1982,7 @@
 	if(IS_ERR(name))
 		return PTR_ERR(name);
 
-	error = path_lookup(name, LOOKUP_PARENT, &nd);
+	error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
 	if (error)
 		goto exit;
 
@@ -1948,6 +2012,11 @@
 	return error;
 }
 
+asmlinkage long sys_rmdir(const char __user *pathname)
+{
+	return do_rmdir(AT_FDCWD, pathname);
+}
+
 int vfs_unlink(struct inode *dir, struct dentry *dentry)
 {
 	int error = may_delete(dir, dentry, 0);
@@ -1984,7 +2053,7 @@
  * writeout happening, and we don't want to prevent access to the directory
  * while waiting on the I/O.
  */
-asmlinkage long sys_unlink(const char __user * pathname)
+static long do_unlinkat(int dfd, const char __user *pathname)
 {
 	int error = 0;
 	char * name;
@@ -1996,7 +2065,7 @@
 	if(IS_ERR(name))
 		return PTR_ERR(name);
 
-	error = path_lookup(name, LOOKUP_PARENT, &nd);
+	error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
 	if (error)
 		goto exit;
 	error = -EISDIR;
@@ -2031,6 +2100,22 @@
 	goto exit2;
 }
 
+asmlinkage long sys_unlinkat(int dfd, const char __user *pathname, int flag)
+{
+	if ((flag & ~AT_REMOVEDIR) != 0)
+		return -EINVAL;
+
+	if (flag & AT_REMOVEDIR)
+		return do_rmdir(dfd, pathname);
+
+	return do_unlinkat(dfd, pathname);
+}
+
+asmlinkage long sys_unlink(const char __user *pathname)
+{
+	return do_unlinkat(AT_FDCWD, pathname);
+}
+
 int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
 {
 	int error = may_create(dir, dentry, NULL);
@@ -2052,7 +2137,8 @@
 	return error;
 }
 
-asmlinkage long sys_symlink(const char __user * oldname, const char __user * newname)
+asmlinkage long sys_symlinkat(const char __user *oldname,
+			      int newdfd, const char __user *newname)
 {
 	int error = 0;
 	char * from;
@@ -2067,7 +2153,7 @@
 		struct dentry *dentry;
 		struct nameidata nd;
 
-		error = path_lookup(to, LOOKUP_PARENT, &nd);
+		error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
 		if (error)
 			goto out;
 		dentry = lookup_create(&nd, 0);
@@ -2085,6 +2171,11 @@
 	return error;
 }
 
+asmlinkage long sys_symlink(const char __user *oldname, const char __user *newname)
+{
+	return sys_symlinkat(oldname, AT_FDCWD, newname);
+}
+
 int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
 {
 	struct inode *inode = old_dentry->d_inode;
@@ -2132,7 +2223,8 @@
  * with linux 2.0, and to avoid hard-linking to directories
  * and other special files.  --ADM
  */
-asmlinkage long sys_link(const char __user * oldname, const char __user * newname)
+asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
+			   int newdfd, const char __user *newname)
 {
 	struct dentry *new_dentry;
 	struct nameidata nd, old_nd;
@@ -2143,10 +2235,10 @@
 	if (IS_ERR(to))
 		return PTR_ERR(to);
 
-	error = __user_walk(oldname, 0, &old_nd);
+	error = __user_walk_fd(olddfd, oldname, 0, &old_nd);
 	if (error)
 		goto exit;
-	error = path_lookup(to, LOOKUP_PARENT, &nd);
+	error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
 	if (error)
 		goto out;
 	error = -EXDEV;
@@ -2169,6 +2261,11 @@
 	return error;
 }
 
+asmlinkage long sys_link(const char __user *oldname, const char __user *newname)
+{
+	return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname);
+}
+
 /*
  * The worst of all namespace operations - renaming directory. "Perverted"
  * doesn't even start to describe it. Somebody in UCB had a heck of a trip...
@@ -2315,7 +2412,8 @@
 	return error;
 }
 
-static int do_rename(const char * oldname, const char * newname)
+static int do_rename(int olddfd, const char *oldname,
+			int newdfd, const char *newname)
 {
 	int error = 0;
 	struct dentry * old_dir, * new_dir;
@@ -2323,11 +2421,11 @@
 	struct dentry * trap;
 	struct nameidata oldnd, newnd;
 
-	error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
+	error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd);
 	if (error)
 		goto exit;
 
-	error = path_lookup(newname, LOOKUP_PARENT, &newnd);
+	error = do_path_lookup(newdfd, newname, LOOKUP_PARENT, &newnd);
 	if (error)
 		goto exit1;
 
@@ -2391,7 +2489,8 @@
 	return error;
 }
 
-asmlinkage long sys_rename(const char __user * oldname, const char __user * newname)
+asmlinkage long sys_renameat(int olddfd, const char __user *oldname,
+			     int newdfd, const char __user *newname)
 {
 	int error;
 	char * from;
@@ -2403,13 +2502,18 @@
 	to = getname(newname);
 	error = PTR_ERR(to);
 	if (!IS_ERR(to)) {
-		error = do_rename(from,to);
+		error = do_rename(olddfd, from, newdfd, to);
 		putname(to);
 	}
 	putname(from);
 	return error;
 }
 
+asmlinkage long sys_rename(const char __user *oldname, const char __user *newname)
+{
+	return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname);
+}
+
 int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link)
 {
 	int len;
@@ -2553,6 +2657,7 @@
 };
 
 EXPORT_SYMBOL(__user_walk);
+EXPORT_SYMBOL(__user_walk_fd);
 EXPORT_SYMBOL(follow_down);
 EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
diff --git a/fs/namespace.c b/fs/namespace.c
index ce97bec..058a448 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -494,7 +494,7 @@
 		p->mnt_namespace = NULL;
 		list_del_init(&p->mnt_child);
 		if (p->mnt_parent != p)
-			mnt->mnt_mountpoint->d_mounted--;
+			p->mnt_mountpoint->d_mounted--;
 		change_mnt_propagation(p, MS_PRIVATE);
 	}
 }
@@ -1325,27 +1325,17 @@
 	return retval;
 }
 
-int copy_namespace(int flags, struct task_struct *tsk)
+/*
+ * Allocate a new namespace structure and populate it with contents
+ * copied from the namespace of the passed in task structure.
+ */
+struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
 {
 	struct namespace *namespace = tsk->namespace;
 	struct namespace *new_ns;
 	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
-	struct fs_struct *fs = tsk->fs;
 	struct vfsmount *p, *q;
 
-	if (!namespace)
-		return 0;
-
-	get_namespace(namespace);
-
-	if (!(flags & CLONE_NEWNS))
-		return 0;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		put_namespace(namespace);
-		return -EPERM;
-	}
-
 	new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL);
 	if (!new_ns)
 		goto out;
@@ -1396,8 +1386,6 @@
 	}
 	up_write(&namespace_sem);
 
-	tsk->namespace = new_ns;
-
 	if (rootmnt)
 		mntput(rootmnt);
 	if (pwdmnt)
@@ -1405,12 +1393,40 @@
 	if (altrootmnt)
 		mntput(altrootmnt);
 
-	put_namespace(namespace);
-	return 0;
+out:
+	return new_ns;
+}
+
+int copy_namespace(int flags, struct task_struct *tsk)
+{
+	struct namespace *namespace = tsk->namespace;
+	struct namespace *new_ns;
+	int err = 0;
+
+	if (!namespace)
+		return 0;
+
+	get_namespace(namespace);
+
+	if (!(flags & CLONE_NEWNS))
+		return 0;
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		err = -EPERM;
+		goto out;
+	}
+
+	new_ns = dup_namespace(tsk, tsk->fs);
+	if (!new_ns) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	tsk->namespace = new_ns;
 
 out:
 	put_namespace(namespace);
-	return -ENOMEM;
+	return err;
 }
 
 asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name,
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 10ae377..04ab2fc 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -481,7 +481,7 @@
 		if (wdata->verf.committed != NFS_FILE_SYNC) {
 			need_commit = 1;
 			if (memcmp(&first_verf.verifier, &wdata->verf.verifier,
-					sizeof(first_verf.verifier)));
+					sizeof(first_verf.verifier)))
 				goto sync_retry;
 		}
 
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index e897e00..c0a754e 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -465,10 +465,11 @@
 					"number from server, using default\n");
 			port = nfsd_port;
 		}
-		nfs_port = htons(port);
+		nfs_port = port;
 		dprintk("Root-NFS: Portmapper on server returned %d "
 			"as nfsd port\n", port);
 	}
+	nfs_port = htons(nfs_port);
 
 	if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) {
 		printk(KERN_ERR "Root-NFS: Unable to get mountd port "
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index 0b14938..0d4cf94 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -5,6 +5,7 @@
  *
  */
 #include <linux/config.h>
+#include <linux/types.h>
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/sunrpc/svc.h>
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 361b400..6d63f1d 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -192,6 +192,16 @@
 	}
 	if (status)
 		goto out;
+
+	/* Openowner is now set, so sequence id will get bumped.  Now we need
+	 * these checks before we do any creates: */
+	status = nfserr_grace;
+	if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+		goto out;
+	status = nfserr_no_grace;
+	if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+		goto out;
+
 	switch (open->op_claim_type) {
 		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
 			status = nfserr_inval;
@@ -210,6 +220,7 @@
 				goto out;
 			break;
 		case NFS4_OPEN_CLAIM_PREVIOUS:
+			open->op_stateowner->so_confirmed = 1;
 			/*
 			 * The CURRENT_FH is already set to the file being
 			 * opened.  (1) set open->op_cinfo, (2) set
@@ -221,6 +232,7 @@
 				goto out;
 			break;
              	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+			open->op_stateowner->so_confirmed = 1;
 			printk("NFSD: unsupported OPEN claim type %d\n",
 				open->op_claim_type);
 			status = nfserr_notsupp;
@@ -584,31 +596,23 @@
 {
 	int status = nfs_ok;
 
-	if (!current_fh->fh_dentry)
-		return nfserr_nofilehandle;
-
-	status = nfs_ok;
 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
 		nfs4_lock_state();
-		if ((status = nfs4_preprocess_stateid_op(current_fh,
-						&setattr->sa_stateid,
-						CHECK_FH | WR_STATE, NULL))) {
-			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
-			goto out_unlock;
-		}
+		status = nfs4_preprocess_stateid_op(current_fh,
+			&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
 		nfs4_unlock_state();
+		if (status) {
+			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!");
+			return status;
+		}
 	}
 	status = nfs_ok;
 	if (setattr->sa_acl != NULL)
 		status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
 	if (status)
-		goto out;
+		return status;
 	status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
 				0, (time_t)0);
-out:
-	return status;
-out_unlock:
-	nfs4_unlock_state();
 	return status;
 }
 
@@ -626,15 +630,17 @@
 		return nfserr_inval;
 
 	nfs4_lock_state();
-	if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
-					CHECK_FH | WR_STATE, &filp))) {
-		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
-		goto out;
-	}
+	status = nfs4_preprocess_stateid_op(current_fh, stateid,
+					CHECK_FH | WR_STATE, &filp);
 	if (filp)
 		get_file(filp);
 	nfs4_unlock_state();
 
+	if (status) {
+		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
+		return status;
+	}
+
 	write->wr_bytes_written = write->wr_buflen;
 	write->wr_how_written = write->wr_stable_how;
 	p = (u32 *)write->wr_verifier.data;
@@ -650,9 +656,6 @@
 	if (status == nfserr_symlink)
 		status = nfserr_inval;
 	return status;
-out:
-	nfs4_unlock_state();
-	return status;
 }
 
 /* This routine never returns NFS_OK!  If there are no other errors, it
@@ -768,6 +771,8 @@
 	while (!status && resp->opcnt < args->opcnt) {
 		op = &args->ops[resp->opcnt++];
 
+		dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum);
+
 		/*
 		 * The XDR decode routines may have pre-set op->status;
 		 * for example, if there is a miscellaneous XDR error
@@ -792,17 +797,13 @@
 		/* All operations except RENEW, SETCLIENTID, RESTOREFH
 		* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
 		* require a valid current filehandle
-		*
-		* SETATTR NOFILEHANDLE error handled in nfsd4_setattr
-		* due to required returned bitmap argument
 		*/
 		if ((!current_fh->fh_dentry) &&
 		   !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
 		   (op->opnum == OP_SETCLIENTID) ||
 		   (op->opnum == OP_SETCLIENTID_CONFIRM) ||
 		   (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
-		   (op->opnum == OP_RELEASE_LOCKOWNER) ||
-		   (op->opnum == OP_SETATTR))) {
+		   (op->opnum == OP_RELEASE_LOCKOWNER))) {
 			op->status = nfserr_nofilehandle;
 			goto encode_op;
 		}
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index be963a1..06da750 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -222,8 +222,7 @@
 
 	nfs4_save_user(&uid, &gid);
 
-	filp = dentry_open(dget(dir), mntget(rec_dir.mnt),
-			O_RDWR);
+	filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
 	status = PTR_ERR(filp);
 	if (IS_ERR(filp))
 		goto out;
@@ -400,9 +399,10 @@
 
 	nfs4_save_user(&uid, &gid);
 
-	status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir);
-	if (status == -ENOENT)
-		printk("NFSD: recovery directory %s doesn't exist\n",
+	status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
+			&rec_dir);
+	if (status)
+		printk("NFSD: unable to find recovery directory %s\n",
 				rec_dirname);
 
 	if (!status)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6bbefd0..1143cfb 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1088,7 +1088,7 @@
 	sop->so_seqid = open->op_seqid;
 	sop->so_confirmed = 0;
 	rp = &sop->so_replay;
-	rp->rp_status = NFSERR_SERVERFAULT;
+	rp->rp_status = nfserr_serverfault;
 	rp->rp_buflen = 0;
 	rp->rp_buf = rp->rp_ibuf;
 	return sop;
@@ -1178,7 +1178,6 @@
 		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
 	put_nfs4_file(stp->st_file);
 	kmem_cache_free(stateid_slab, stp);
-	stp = NULL;
 }
 
 static void
@@ -1191,22 +1190,6 @@
 	sop->so_time = get_seconds();
 }
 
-static void
-release_state_owner(struct nfs4_stateid *stp, int flag)
-{
-	struct nfs4_stateowner *sop = stp->st_stateowner;
-
-	dprintk("NFSD: release_state_owner\n");
-	release_stateid(stp, flag);
-
-	/* place unused nfs4_stateowners on so_close_lru list to be
-	 * released by the laundromat service after the lease period
-	 * to enable us to handle CLOSE replay
-	 */
-	if (sop->so_confirmed && list_empty(&sop->so_stateids))
-		move_to_close_lru(sop);
-}
-
 static int
 cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
 	return ((sop->so_owner.len == owner->len) && 
@@ -1446,92 +1429,61 @@
 };
 
 
-/*
- * nfsd4_process_open1()
- * 	lookup stateowner.
- * 		found:
- * 			check confirmed 
- * 				confirmed:
- * 					check seqid
- * 				not confirmed:
- * 					delete owner
- * 					create new owner
- * 		notfound:
- * 			verify clientid
- * 			create new owner
- *
- * called with nfs4_lock_state() held.
- */
 int
 nfsd4_process_open1(struct nfsd4_open *open)
 {
-	int status;
 	clientid_t *clientid = &open->op_clientid;
 	struct nfs4_client *clp = NULL;
 	unsigned int strhashval;
 	struct nfs4_stateowner *sop = NULL;
 
-	status = nfserr_inval;
 	if (!check_name(open->op_owner))
-		goto out;
+		return nfserr_inval;
 
 	if (STALE_CLIENTID(&open->op_clientid))
 		return nfserr_stale_clientid;
 
 	strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
 	sop = find_openstateowner_str(strhashval, open);
-	if (sop) {
-		open->op_stateowner = sop;
-		/* check for replay */
-		if (open->op_seqid == sop->so_seqid - 1){
-			if (sop->so_replay.rp_buflen)
-				return NFSERR_REPLAY_ME;
-			else {
-				/* The original OPEN failed so spectacularly
-				 * that we don't even have replay data saved!
-				 * Therefore, we have no choice but to continue
-				 * processing this OPEN; presumably, we'll
-				 * fail again for the same reason.
-				 */
-				dprintk("nfsd4_process_open1:"
-					" replay with no replay cache\n");
-				goto renew;
-			}
-		} else if (sop->so_confirmed) {
-			if (open->op_seqid == sop->so_seqid)
-				goto renew;
-			status = nfserr_bad_seqid;
-			goto out;
-		} else {
-			/* If we get here, we received an OPEN for an
-			 * unconfirmed nfs4_stateowner. Since the seqid's are
-			 * different, purge the existing nfs4_stateowner, and
-			 * instantiate a new one.
-			 */
-			clp = sop->so_client;
-			release_stateowner(sop);
-		}
-	} else {
-		/* nfs4_stateowner not found.
-		 * Verify clientid and instantiate new nfs4_stateowner.
-		 * If verify fails this is presumably the result of the
-		 * client's lease expiring.
-		 */
-		status = nfserr_expired;
+	open->op_stateowner = sop;
+	if (!sop) {
+		/* Make sure the client's lease hasn't expired. */
 		clp = find_confirmed_client(clientid);
 		if (clp == NULL)
-			goto out;
+			return nfserr_expired;
+		goto renew;
 	}
-	status = nfserr_resource;
-	sop = alloc_init_open_stateowner(strhashval, clp, open);
-	if (sop == NULL)
-		goto out;
-	open->op_stateowner = sop;
+	if (!sop->so_confirmed) {
+		/* Replace unconfirmed owners without checking for replay. */
+		clp = sop->so_client;
+		release_stateowner(sop);
+		open->op_stateowner = NULL;
+		goto renew;
+	}
+	if (open->op_seqid == sop->so_seqid - 1) {
+		if (sop->so_replay.rp_buflen)
+			return NFSERR_REPLAY_ME;
+		/* The original OPEN failed so spectacularly
+		 * that we don't even have replay data saved!
+		 * Therefore, we have no choice but to continue
+		 * processing this OPEN; presumably, we'll
+		 * fail again for the same reason.
+		 */
+		dprintk("nfsd4_process_open1: replay with no replay cache\n");
+		goto renew;
+	}
+	if (open->op_seqid != sop->so_seqid)
+		return nfserr_bad_seqid;
 renew:
-	status = nfs_ok;
+	if (open->op_stateowner == NULL) {
+		sop = alloc_init_open_stateowner(strhashval, clp, open);
+		if (sop == NULL)
+			return nfserr_resource;
+		open->op_stateowner = sop;
+	}
+	list_del_init(&sop->so_close_lru);
 	renew_client(sop->so_client);
-out:
-	return status;
+	return nfs_ok;
 }
 
 static inline int
@@ -1648,7 +1600,7 @@
 	if (!open->op_truncate)
 		return 0;
 	if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
-		return -EINVAL;
+		return nfserr_inval;
 	return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
 }
 
@@ -1657,26 +1609,26 @@
 {
 	struct file *filp = stp->st_vfs_file;
 	struct inode *inode = filp->f_dentry->d_inode;
-	unsigned int share_access;
+	unsigned int share_access, new_writer;
 	int status;
 
 	set_access(&share_access, stp->st_access_bmap);
-	share_access = ~share_access;
-	share_access &= open->op_share_access;
+	new_writer = (~share_access) & open->op_share_access
+			& NFS4_SHARE_ACCESS_WRITE;
 
-	if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
-		return nfsd4_truncate(rqstp, cur_fh, open);
-
-	status = get_write_access(inode);
-	if (status)
-		return nfserrno(status);
+	if (new_writer) {
+		status = get_write_access(inode);
+		if (status)
+			return nfserrno(status);
+	}
 	status = nfsd4_truncate(rqstp, cur_fh, open);
 	if (status) {
-		put_write_access(inode);
+		if (new_writer)
+			put_write_access(inode);
 		return status;
 	}
 	/* remember the open */
-	filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
+	filp->f_mode |= open->op_share_access;
 	set_bit(open->op_share_access, &stp->st_access_bmap);
 	set_bit(open->op_share_deny, &stp->st_deny_bmap);
 
@@ -1780,12 +1732,6 @@
 	struct nfs4_delegation *dp = NULL;
 	int status;
 
-	if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
-		return nfserr_grace;
-
-	if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
-		return nfserr_no_grace;
-
 	status = nfserr_inval;
 	if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
 		goto out;
@@ -2423,15 +2369,19 @@
 					CHECK_FH | OPEN_STATE | CLOSE_STATE,
 					&close->cl_stateowner, &stp, NULL)))
 		goto out; 
-	/*
-	*  Return success, but first update the stateid.
-	*/
 	status = nfs_ok;
 	update_stateid(&stp->st_stateid);
 	memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
 
-	/* release_state_owner() calls nfsd_close() if needed */
-	release_state_owner(stp, OPEN_STATE);
+	/* release_stateid() calls nfsd_close() if needed */
+	release_stateid(stp, OPEN_STATE);
+
+	/* place unused nfs4_stateowners on so_close_lru list to be
+	 * released by the laundromat service after the lease period
+	 * to enable us to handle CLOSE replay
+	 */
+	if (list_empty(&close->cl_stateowner->so_stateids))
+		move_to_close_lru(close->cl_stateowner);
 out:
 	if (close->cl_stateowner) {
 		nfs4_get_stateowner(close->cl_stateowner);
@@ -2633,7 +2583,7 @@
 	sop->so_seqid = lock->lk_new_lock_seqid + 1;
 	sop->so_confirmed = 1;
 	rp = &sop->so_replay;
-	rp->rp_status = NFSERR_SERVERFAULT;
+	rp->rp_status = nfserr_serverfault;
 	rp->rp_buflen = 0;
 	rp->rp_buf = rp->rp_ibuf;
 	return sop;
@@ -2700,6 +2650,11 @@
 	if (check_lock_length(lock->lk_offset, lock->lk_length))
 		 return nfserr_inval;
 
+	if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
+		dprintk("NFSD: nfsd4_lock: permission denied!\n");
+		return status;
+	}
+
 	nfs4_lock_state();
 
 	if (lock->lk_is_new) {
@@ -2720,11 +2675,11 @@
 				        lock->lk_new_open_seqid,
 		                        &lock->lk_new_open_stateid,
 		                        CHECK_FH | OPEN_STATE,
-		                        &lock->lk_stateowner, &open_stp,
+		                        &lock->lk_replay_owner, &open_stp,
 					lock);
 		if (status)
 			goto out;
-		open_sop = lock->lk_stateowner;
+		open_sop = lock->lk_replay_owner;
 		/* create lockowner and lock stateid */
 		fp = open_stp->st_file;
 		strhashval = lock_ownerstr_hashval(fp->fi_inode, 
@@ -2739,29 +2694,22 @@
 		if (lock_sop == NULL)
 			goto out;
 		lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
-		if (lock_stp == NULL) {
-			release_stateowner(lock_sop);
+		if (lock_stp == NULL)
 			goto out;
-		}
 	} else {
 		/* lock (lock owner + lock stateid) already exists */
 		status = nfs4_preprocess_seqid_op(current_fh,
 				       lock->lk_old_lock_seqid, 
 				       &lock->lk_old_lock_stateid, 
 				       CHECK_FH | LOCK_STATE, 
-				       &lock->lk_stateowner, &lock_stp, lock);
+				       &lock->lk_replay_owner, &lock_stp, lock);
 		if (status)
 			goto out;
-		lock_sop = lock->lk_stateowner;
+		lock_sop = lock->lk_replay_owner;
 	}
-	/* lock->lk_stateowner and lock_stp have been created or found */
+	/* lock->lk_replay_owner and lock_stp have been created or found */
 	filp = lock_stp->st_vfs_file;
 
-	if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
-		dprintk("NFSD: nfsd4_lock: permission denied!\n");
-		goto out;
-	}
-
 	status = nfserr_grace;
 	if (nfs4_in_grace() && !lock->lk_reclaim)
 		goto out;
@@ -2802,8 +2750,6 @@
 	*/
 
 	status = posix_lock_file(filp, &file_lock);
-	if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
-		file_lock.fl_ops->fl_release_private(&file_lock);
 	dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
 	switch (-status) {
 	case 0: /* success! */
@@ -2815,9 +2761,12 @@
 		goto conflicting_lock;
 	case (EDEADLK):
 		status = nfserr_deadlock;
-	default:        
 		dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
-		goto out_destroy_new_stateid;
+		goto out;
+	default:        
+		status = nfserrno(status);
+		dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
+		goto out;
 	}
 
 conflicting_lock:
@@ -2831,20 +2780,12 @@
 		goto out;
 	}
 	nfs4_set_lock_denied(conflock, &lock->lk_denied);
-
-out_destroy_new_stateid:
-	if (lock->lk_is_new) {
-		dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
-		/*
-		 * An error encountered after instantiation of the new
-		 * stateid has forced us to destroy it.
-		 */
-		release_state_owner(lock_stp, LOCK_STATE);
-	}
 out:
-	if (lock->lk_stateowner) {
-		nfs4_get_stateowner(lock->lk_stateowner);
-		*replay_owner = lock->lk_stateowner;
+	if (status && lock->lk_is_new && lock_sop)
+		release_stateowner(lock_sop);
+	if (lock->lk_replay_owner) {
+		nfs4_get_stateowner(lock->lk_replay_owner);
+		*replay_owner = lock->lk_replay_owner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -2977,8 +2918,6 @@
 	*  Try to unlock the file in the VFS.
 	*/
 	status = posix_lock_file(filp, &file_lock); 
-	if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
-		file_lock.fl_ops->fl_release_private(&file_lock);
 	if (status) {
 		dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
 		goto out_nfserr;
@@ -3016,9 +2955,10 @@
 
 	lock_kernel();
 	for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
-		if ((*flpp)->fl_owner == (fl_owner_t)lowner)
+		if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
 			status = 1;
 			goto out;
+		}
 	}
 out:
 	unlock_kernel();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index dcd6731..69d3501 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -528,7 +528,7 @@
 {
 	DECODE_HEAD;
 
-	lock->lk_stateowner = NULL;
+	lock->lk_replay_owner = NULL;
 	/*
 	* type, reclaim(boolean), offset, length, new_lock_owner(boolean)
 	*/
@@ -1764,10 +1764,11 @@
 		 */
 		if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
 			goto fail;
-		nfserr = nfserr_toosmall;
 		p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
-		if (p == NULL)
+		if (p == NULL) {
+			nfserr = nfserr_toosmall;
 			goto fail;
+		}
 	}
 	cd->buflen -= (p - cd->buffer);
 	cd->buffer = p;
@@ -1895,7 +1896,6 @@
 static void
 nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
 {
-
 	ENCODE_SEQID_OP_HEAD;
 
 	if (!nfserr) {
@@ -1906,7 +1906,7 @@
 	} else if (nfserr == nfserr_denied)
 		nfsd4_encode_lock_denied(resp, &lock->lk_denied);
 
-	ENCODE_SEQID_OP_TAIL(lock->lk_stateowner);
+	ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
 }
 
 static void
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 0aa1b96..3e6b75c 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -36,6 +36,22 @@
 	return nfs_ok;
 }
 
+static int
+nfsd_return_attrs(int err, struct nfsd_attrstat *resp)
+{
+	if (err) return err;
+	return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
+				    resp->fh.fh_dentry,
+				    &resp->stat));
+}
+static int
+nfsd_return_dirop(int err, struct nfsd_diropres *resp)
+{
+	if (err) return err;
+	return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
+				    resp->fh.fh_dentry,
+				    &resp->stat));
+}
 /*
  * Get a file's attributes
  * N.B. After this call resp->fh needs an fh_put
@@ -44,10 +60,12 @@
 nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
 					  struct nfsd_attrstat *resp)
 {
+	int nfserr;
 	dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
 
 	fh_copy(&resp->fh, &argp->fh);
-	return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+	nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+	return nfsd_return_attrs(nfserr, resp);
 }
 
 /*
@@ -58,12 +76,14 @@
 nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
 					  struct nfsd_attrstat  *resp)
 {
+	int nfserr;
 	dprintk("nfsd: SETATTR  %s, valid=%x, size=%ld\n",
 		SVCFH_fmt(&argp->fh),
 		argp->attrs.ia_valid, (long) argp->attrs.ia_size);
 
 	fh_copy(&resp->fh, &argp->fh);
-	return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
+	nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
+	return nfsd_return_attrs(nfserr, resp);
 }
 
 /*
@@ -86,7 +106,7 @@
 				 &resp->fh);
 
 	fh_put(&argp->fh);
-	return nfserr;
+	return nfsd_return_dirop(nfserr, resp);
 }
 
 /*
@@ -142,7 +162,10 @@
 			   	  argp->vec, argp->vlen,
 				  &resp->count);
 
-	return nfserr;
+	if (nfserr) return nfserr;
+	return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
+				    resp->fh.fh_dentry,
+				    &resp->stat));
 }
 
 /*
@@ -165,7 +188,7 @@
 				   argp->vec, argp->vlen,
 				   argp->len,
 				   &stable);
-	return nfserr;
+	return nfsd_return_attrs(nfserr, resp);
 }
 
 /*
@@ -322,7 +345,7 @@
 
 done:
 	fh_put(dirfhp);
-	return nfserr;
+	return nfsd_return_dirop(nfserr, resp);
 }
 
 static int
@@ -425,7 +448,7 @@
 	nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
 				    &argp->attrs, S_IFDIR, 0, &resp->fh);
 	fh_put(&argp->fh);
-	return nfserr;
+	return nfsd_return_dirop(nfserr, resp);
 }
 
 /*
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 89ed046..1d163b6 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -64,6 +64,32 @@
 };
 static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
 
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+static struct svc_stat	nfsd_acl_svcstats;
+static struct svc_version *	nfsd_acl_version[] = {
+	[2] = &nfsd_acl_version2,
+	[3] = &nfsd_acl_version3,
+};
+
+#define NFSD_ACL_MINVERS            2
+#define NFSD_ACL_NRVERS		(sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0]))
+static struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS];
+
+static struct svc_program	nfsd_acl_program = {
+	.pg_prog		= NFS_ACL_PROGRAM,
+	.pg_nvers		= NFSD_ACL_NRVERS,
+	.pg_vers		= nfsd_acl_versions,
+	.pg_name		= "nfsd",
+	.pg_class		= "nfsd",
+	.pg_stats		= &nfsd_acl_svcstats,
+	.pg_authenticate	= &svc_set_client,
+};
+
+static struct svc_stat	nfsd_acl_svcstats = {
+	.program	= &nfsd_acl_program,
+};
+#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
+
 static struct svc_version *	nfsd_version[] = {
 	[2] = &nfsd_version2,
 #if defined(CONFIG_NFSD_V3)
@@ -79,6 +105,9 @@
 static struct svc_version *nfsd_versions[NFSD_NRVERS];
 
 struct svc_program		nfsd_program = {
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+	.pg_next		= &nfsd_acl_program,
+#endif
 	.pg_prog		= NFS_PROGRAM,		/* program number */
 	.pg_nvers		= NFSD_NRVERS,		/* nr of entries in nfsd_version */
 	.pg_vers		= nfsd_versions,	/* version table */
@@ -147,6 +176,26 @@
 				nfsd_program.pg_vers[i] = nfsd_version[i];
 		}
 
+
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+		found_one = 0;
+
+		for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) {
+			if (NFSCTL_VERISSET(nfsd_versbits, i)) {
+				nfsd_acl_program.pg_vers[i] =
+					nfsd_acl_version[i];
+				found_one = 1;
+			} else
+				nfsd_acl_program.pg_vers[i] = NULL;
+		}
+
+		if (!found_one) {
+			for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
+				nfsd_acl_program.pg_vers[i] =
+					nfsd_acl_version[i];
+		}
+#endif
+
 		atomic_set(&nfsd_busy, 0);
 		error = -ENOMEM;
 		nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE);
@@ -411,30 +460,3 @@
 	nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
 	return 1;
 }
-
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
-static struct svc_stat	nfsd_acl_svcstats;
-static struct svc_version *	nfsd_acl_version[] = {
-	[2] = &nfsd_acl_version2,
-	[3] = &nfsd_acl_version3,
-};
-
-#define NFSD_ACL_NRVERS		(sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0]))
-static struct svc_program	nfsd_acl_program = {
-	.pg_prog		= NFS_ACL_PROGRAM,
-	.pg_nvers		= NFSD_ACL_NRVERS,
-	.pg_vers		= nfsd_acl_version,
-	.pg_name		= "nfsd",
-	.pg_class		= "nfsd",
-	.pg_stats		= &nfsd_acl_svcstats,
-	.pg_authenticate	= &svc_set_client,
-};
-
-static struct svc_stat	nfsd_acl_svcstats = {
-	.program	= &nfsd_acl_program,
-};
-
-#define nfsd_acl_program_p	&nfsd_acl_program
-#else
-#define nfsd_acl_program_p	NULL
-#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index eef0576..5320e5a 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -710,14 +710,15 @@
 {
 	struct inode *inode = dp->d_inode;
 	int (*fsync) (struct file *, struct dentry *, int);
-	int err = nfs_ok;
+	int err;
 
-	filemap_fdatawrite(inode->i_mapping);
-	if (fop && (fsync = fop->fsync))
-		err=fsync(filp, dp, 0);
-	filemap_fdatawait(inode->i_mapping);
+	err = filemap_fdatawrite(inode->i_mapping);
+	if (err == 0 && fop && (fsync = fop->fsync))
+		err = fsync(filp, dp, 0);
+	if (err == 0)
+		err = filemap_fdatawait(inode->i_mapping);
 
-	return nfserrno(err);
+	return err;
 }
 	
 
@@ -734,10 +735,10 @@
 	return err;
 }
 
-void
+int
 nfsd_sync_dir(struct dentry *dp)
 {
-	nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
+	return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
 }
 
 /*
@@ -814,7 +815,7 @@
 	return size;
 }
 
-static inline int
+static int
 nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
               loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
 {
@@ -878,7 +879,7 @@
 	mutex_unlock(&dentry->d_inode->i_mutex);
 }
 
-static inline int
+static int
 nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 				loff_t offset, struct kvec *vec, int vlen,
 	   			unsigned long cnt, int *stablep)
@@ -890,9 +891,9 @@
 	int			err = 0;
 	int			stable = *stablep;
 
+#ifdef MSNFS
 	err = nfserr_perm;
 
-#ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 		(!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
 		goto out;
@@ -1064,7 +1065,7 @@
 		return err;
 	if (EX_ISSYNC(fhp->fh_export)) {
 		if (file->f_op && file->f_op->fsync) {
-			err = nfsd_sync(file);
+			err = nfserrno(nfsd_sync(file));
 		} else {
 			err = nfserr_notsupp;
 		}
@@ -1132,7 +1133,7 @@
 				"nfsd_create: parent %s/%s not locked!\n",
 				dentry->d_parent->d_name.name,
 				dentry->d_name.name);
-			err = -EIO;
+			err = nfserr_io;
 			goto out;
 		}
 	}
@@ -1175,7 +1176,7 @@
 		goto out_nfserr;
 
 	if (EX_ISSYNC(fhp->fh_export)) {
-		nfsd_sync_dir(dentry);
+		err = nfserrno(nfsd_sync_dir(dentry));
 		write_inode_now(dchild->d_inode, 1);
 	}
 
@@ -1185,9 +1186,11 @@
 	 * send along the gid when it tries to implement setgid
 	 * directories via NFS.
 	 */
-	err = 0;
-	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
-		err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
+		int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+		if (err2)
+			err = err2;
+	}
 	/*
 	 * Update the file handle to get the new inode info.
 	 */
@@ -1306,17 +1309,10 @@
 		goto out_nfserr;
 
 	if (EX_ISSYNC(fhp->fh_export)) {
-		nfsd_sync_dir(dentry);
+		err = nfserrno(nfsd_sync_dir(dentry));
 		/* setattr will sync the child (or not) */
 	}
 
-	/*
-	 * Update the filehandle to get the new inode info.
-	 */
-	err = fh_update(resfhp);
-	if (err)
-		goto out;
-
 	if (createmode == NFS3_CREATE_EXCLUSIVE) {
 		/* Cram the verifier into atime/mtime/mode */
 		iap->ia_valid = ATTR_MTIME|ATTR_ATIME
@@ -1337,8 +1333,17 @@
 	 * implement setgid directories via NFS. Clear out all that cruft.
 	 */
  set_attr:
-	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0)
- 		err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
+ 		int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+		if (err2)
+			err = err2;
+	}
+
+	/*
+	 * Update the filehandle to get the new inode info.
+	 */
+	if (!err)
+		err = fh_update(resfhp);
 
  out:
 	fh_unlock(fhp);
@@ -1447,10 +1452,10 @@
 	} else
 		err = vfs_symlink(dentry->d_inode, dnew, path, mode);
 
-	if (!err) {
+	if (!err)
 		if (EX_ISSYNC(fhp->fh_export))
-			nfsd_sync_dir(dentry);
-	} else
+			err = nfsd_sync_dir(dentry);
+	if (err)
 		err = nfserrno(err);
 	fh_unlock(fhp);
 
@@ -1506,7 +1511,7 @@
 	err = vfs_link(dold, dirp, dnew);
 	if (!err) {
 		if (EX_ISSYNC(ffhp->fh_export)) {
-			nfsd_sync_dir(ddir);
+			err = nfserrno(nfsd_sync_dir(ddir));
 			write_inode_now(dest, 1);
 		}
 	} else {
@@ -1590,13 +1595,14 @@
 	if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 		((atomic_read(&odentry->d_count) > 1)
 		 || (atomic_read(&ndentry->d_count) > 1))) {
-			err = nfserr_perm;
+			err = -EPERM;
 	} else
 #endif
 	err = vfs_rename(fdir, odentry, tdir, ndentry);
 	if (!err && EX_ISSYNC(tfhp->fh_export)) {
-		nfsd_sync_dir(tdentry);
-		nfsd_sync_dir(fdentry);
+		err = nfsd_sync_dir(tdentry);
+		if (!err)
+			err = nfsd_sync_dir(fdentry);
 	}
 
  out_dput_new:
@@ -1661,7 +1667,7 @@
 #ifdef MSNFS
 		if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 			(atomic_read(&rdentry->d_count) > 1)) {
-			err = nfserr_perm;
+			err = -EPERM;
 		} else
 #endif
 		err = vfs_unlink(dirp, rdentry);
@@ -1671,17 +1677,14 @@
 
 	dput(rdentry);
 
-	if (err)
-		goto out_nfserr;
-	if (EX_ISSYNC(fhp->fh_export)) 
-		nfsd_sync_dir(dentry);
-
-out:
-	return err;
+	if (err == 0 &&
+	    EX_ISSYNC(fhp->fh_export))
+			err = nfsd_sync_dir(dentry);
 
 out_nfserr:
 	err = nfserrno(err);
-	goto out;
+out:
+	return err;
 }
 
 /*
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c
index d424041..bae3d75 100644
--- a/fs/ocfs2/buffer_head_io.c
+++ b/fs/ocfs2/buffer_head_io.c
@@ -58,7 +58,7 @@
 		goto out;
 	}
 
-	down(&OCFS2_I(inode)->ip_io_sem);
+	mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
 
 	lock_buffer(bh);
 	set_buffer_uptodate(bh);
@@ -82,7 +82,7 @@
 		brelse(bh);
 	}
 
-	up(&OCFS2_I(inode)->ip_io_sem);
+	mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
 out:
 	mlog_exit(ret);
 	return ret;
@@ -125,13 +125,13 @@
 		flags &= ~OCFS2_BH_CACHED;
 
 	if (inode)
-		down(&OCFS2_I(inode)->ip_io_sem);
+		mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
 	for (i = 0 ; i < nr ; i++) {
 		if (bhs[i] == NULL) {
 			bhs[i] = sb_getblk(sb, block++);
 			if (bhs[i] == NULL) {
 				if (inode)
-					up(&OCFS2_I(inode)->ip_io_sem);
+					mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
 				status = -EIO;
 				mlog_errno(status);
 				goto bail;
@@ -220,7 +220,7 @@
 			ocfs2_set_buffer_uptodate(inode, bh);
 	}
 	if (inode)
-		up(&OCFS2_I(inode)->ip_io_sem);
+		mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
 
 	mlog(ML_BH_IO, "block=(%"MLFu64"), nr=(%d), cached=%s\n", block, nr,
 	     (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes");
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 7307ba5..d08971d 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -917,8 +917,9 @@
 		elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb);
 
 		mlog(0, "start = %lu.%lu, end = %lu.%lu, msec = %u\n",
-		     before_hb.tv_sec, before_hb.tv_usec,
-		     after_hb.tv_sec, after_hb.tv_usec, elapsed_msec);
+		     before_hb.tv_sec, (unsigned long) before_hb.tv_usec,
+		     after_hb.tv_sec, (unsigned long) after_hb.tv_usec,
+		     elapsed_msec);
 
 		if (elapsed_msec < reg->hr_timeout_ms) {
 			/* the kthread api has blocked signals for us so no
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 35d92c0..d22d4cf 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -1285,14 +1285,16 @@
 	mlog(ML_NOTICE, "here are some times that might help debug the "
 	     "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv "
 	     "%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n",
-	     sc->sc_tv_timer.tv_sec, sc->sc_tv_timer.tv_usec, 
-	     now.tv_sec, now.tv_usec,
-	     sc->sc_tv_data_ready.tv_sec, sc->sc_tv_data_ready.tv_usec, 
-	     sc->sc_tv_advance_start.tv_sec, sc->sc_tv_advance_start.tv_usec, 
-	     sc->sc_tv_advance_stop.tv_sec, sc->sc_tv_advance_stop.tv_usec, 
+	     sc->sc_tv_timer.tv_sec, (long) sc->sc_tv_timer.tv_usec, 
+	     now.tv_sec, (long) now.tv_usec,
+	     sc->sc_tv_data_ready.tv_sec, (long) sc->sc_tv_data_ready.tv_usec,
+	     sc->sc_tv_advance_start.tv_sec,
+	     (long) sc->sc_tv_advance_start.tv_usec,
+	     sc->sc_tv_advance_stop.tv_sec,
+	     (long) sc->sc_tv_advance_stop.tv_usec,
 	     sc->sc_msg_key, sc->sc_msg_type,
-	     sc->sc_tv_func_start.tv_sec, sc->sc_tv_func_start.tv_usec,
-	     sc->sc_tv_func_stop.tv_sec, sc->sc_tv_func_stop.tv_usec);
+	     sc->sc_tv_func_start.tv_sec, (long) sc->sc_tv_func_start.tv_usec,
+	     sc->sc_tv_func_stop.tv_sec, (long) sc->sc_tv_func_stop.tv_usec);
 
 	o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
 }
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index 3fecba0..42eb53b 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -657,6 +657,7 @@
 int dlm_launch_recovery_thread(struct dlm_ctxt *dlm);
 void dlm_complete_recovery_thread(struct dlm_ctxt *dlm);
 void dlm_wait_for_recovery(struct dlm_ctxt *dlm);
+int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node);
 
 void dlm_put(struct dlm_ctxt *dlm);
 struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm);
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index da3c220..6ee3083 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -573,8 +573,11 @@
 	spin_lock(&dlm_domain_lock);
 	dlm = __dlm_lookup_domain_full(query->domain, query->name_len);
 	/* Once the dlm ctxt is marked as leaving then we don't want
-	 * to be put in someone's domain map. */
+	 * to be put in someone's domain map. 
+	 * Also, explicitly disallow joining at certain troublesome
+	 * times (ie. during recovery). */
 	if (dlm && dlm->dlm_state != DLM_CTXT_LEAVING) {
+		int bit = query->node_idx;
 		spin_lock(&dlm->spinlock);
 
 		if (dlm->dlm_state == DLM_CTXT_NEW &&
@@ -586,6 +589,19 @@
 		} else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {
 			/* Disallow parallel joins. */
 			response = JOIN_DISALLOW;
+		} else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) {
+			mlog(ML_NOTICE, "node %u trying to join, but recovery "
+			     "is ongoing.\n", bit);
+			response = JOIN_DISALLOW;
+		} else if (test_bit(bit, dlm->recovery_map)) {
+			mlog(ML_NOTICE, "node %u trying to join, but it "
+			     "still needs recovery.\n", bit);
+			response = JOIN_DISALLOW;
+		} else if (test_bit(bit, dlm->domain_map)) {
+			mlog(ML_NOTICE, "node %u trying to join, but it "
+			     "is still in the domain! needs recovery?\n",
+			     bit);
+			response = JOIN_DISALLOW;
 		} else {
 			/* Alright we're fully a part of this domain
 			 * so we keep some state as to who's joining
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 27e984f..a3194fe 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -1050,17 +1050,10 @@
 	node = dlm_bitmap_diff_iter_next(&bdi, &sc);
 	while (node >= 0) {
 		if (sc == NODE_UP) {
-			/* a node came up.  easy.  might not even need
-			 * to talk to it if its node number is higher
-			 * or if we are already blocked. */
-			mlog(0, "node up! %d\n", node);
-			if (blocked)
-				goto next;
-
-			if (node > dlm->node_num) {
-				mlog(0, "node > this node. skipping.\n");
-				goto next;
-			}
+			/* a node came up.  clear any old vote from
+			 * the response map and set it in the vote map
+			 * then restart the mastery. */
+			mlog(ML_NOTICE, "node %d up while restarting\n", node);
 
 			/* redo the master request, but only for the new node */
 			mlog(0, "sending request to new node\n");
@@ -2005,6 +1998,15 @@
 				break;
 
 			mlog(0, "timed out during migration\n");
+			/* avoid hang during shutdown when migrating lockres 
+			 * to a node which also goes down */
+			if (dlm_is_node_dead(dlm, target)) {
+				mlog(0, "%s:%.*s: expected migration target %u "
+				     "is no longer up.  restarting.\n",
+				     dlm->name, res->lockname.len,
+				     res->lockname.name, target);
+				ret = -ERESTARTSYS;
+			}
 		}
 		if (ret == -ERESTARTSYS) {
 			/* migration failed, detach and clean up mle */
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 0c8eb10..186e9a7 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -39,6 +39,7 @@
 #include <linux/inet.h>
 #include <linux/timer.h>
 #include <linux/kthread.h>
+#include <linux/delay.h>
 
 
 #include "cluster/heartbeat.h"
@@ -256,6 +257,27 @@
 	return 0;
 }
 
+/* returns true when the recovery master has contacted us */
+static int dlm_reco_master_ready(struct dlm_ctxt *dlm)
+{
+	int ready;
+	spin_lock(&dlm->spinlock);
+	ready = (dlm->reco.new_master != O2NM_INVALID_NODE_NUM);
+	spin_unlock(&dlm->spinlock);
+	return ready;
+}
+
+/* returns true if node is no longer in the domain
+ * could be dead or just not joined */
+int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node)
+{
+	int dead;
+	spin_lock(&dlm->spinlock);
+	dead = test_bit(node, dlm->domain_map);
+	spin_unlock(&dlm->spinlock);
+	return dead;
+}
+
 /* callers of the top-level api calls (dlmlock/dlmunlock) should
  * block on the dlm->reco.event when recovery is in progress.
  * the dlm recovery thread will set this state when it begins
@@ -297,6 +319,7 @@
 static int dlm_do_recovery(struct dlm_ctxt *dlm)
 {
 	int status = 0;
+	int ret;
 
 	spin_lock(&dlm->spinlock);
 
@@ -343,10 +366,13 @@
 		goto master_here;
 
 	if (dlm->reco.new_master == O2NM_INVALID_NODE_NUM) {
-		/* choose a new master */
-		if (!dlm_pick_recovery_master(dlm)) {
+		/* choose a new master, returns 0 if this node
+		 * is the master, -EEXIST if it's another node.
+		 * this does not return until a new master is chosen
+		 * or recovery completes entirely. */
+		ret = dlm_pick_recovery_master(dlm);
+		if (!ret) {
 			/* already notified everyone.  go. */
-			dlm->reco.new_master = dlm->node_num;
 			goto master_here;
 		}
 		mlog(0, "another node will master this recovery session.\n");
@@ -371,8 +397,13 @@
 	if (status < 0) {
 		mlog(ML_ERROR, "error %d remastering locks for node %u, "
 		     "retrying.\n", status, dlm->reco.dead_node);
+		/* yield a bit to allow any final network messages
+		 * to get handled on remaining nodes */
+		msleep(100);
 	} else {
 		/* success!  see if any other nodes need recovery */
+		mlog(0, "DONE mastering recovery of %s:%u here(this=%u)!\n",
+		     dlm->name, dlm->reco.dead_node, dlm->node_num);
 		dlm_reset_recovery(dlm);
 	}
 	dlm_end_recovery(dlm);
@@ -477,7 +508,7 @@
 					BUG();
 					break;
 				case DLM_RECO_NODE_DATA_DEAD:
-					mlog(0, "node %u died after "
+					mlog(ML_NOTICE, "node %u died after "
 					     "requesting recovery info for "
 					     "node %u\n", ndata->node_num,
 					     dead_node);
@@ -485,6 +516,19 @@
 					// start all over
 					destroy = 1;
 					status = -EAGAIN;
+					/* instead of spinning like crazy here,
+					 * wait for the domain map to catch up
+					 * with the network state.  otherwise this
+					 * can be hit hundreds of times before
+					 * the node is really seen as dead. */
+					wait_event_timeout(dlm->dlm_reco_thread_wq,
+							   dlm_is_node_dead(dlm,
+								ndata->node_num),
+							   msecs_to_jiffies(1000));
+					mlog(0, "waited 1 sec for %u, "
+					     "dead? %s\n", ndata->node_num,
+					     dlm_is_node_dead(dlm, ndata->node_num) ?
+					     "yes" : "no");
 					goto leave;
 				case DLM_RECO_NODE_DATA_RECEIVING:
 				case DLM_RECO_NODE_DATA_REQUESTED:
@@ -678,11 +722,27 @@
 	dlm = item->dlm;
 	dead_node = item->u.ral.dead_node;
 	reco_master = item->u.ral.reco_master;
+	mres = (struct dlm_migratable_lockres *)data;
+
+	if (dead_node != dlm->reco.dead_node ||
+	    reco_master != dlm->reco.new_master) {
+		/* show extra debug info if the recovery state is messed */
+		mlog(ML_ERROR, "%s: bad reco state: reco(dead=%u, master=%u), "
+		     "request(dead=%u, master=%u)\n",
+		     dlm->name, dlm->reco.dead_node, dlm->reco.new_master,
+		     dead_node, reco_master);
+		mlog(ML_ERROR, "%s: name=%.*s master=%u locks=%u/%u flags=%u "
+		     "entry[0]={c=%"MLFu64",l=%u,f=%u,t=%d,ct=%d,hb=%d,n=%u}\n",
+		     dlm->name, mres->lockname_len, mres->lockname, mres->master,
+		     mres->num_locks, mres->total_locks, mres->flags,
+		     mres->ml[0].cookie, mres->ml[0].list, mres->ml[0].flags,
+		     mres->ml[0].type, mres->ml[0].convert_type,
+		     mres->ml[0].highest_blocked, mres->ml[0].node);
+		BUG();
+	}
 	BUG_ON(dead_node != dlm->reco.dead_node);
 	BUG_ON(reco_master != dlm->reco.new_master);
 
-	mres = (struct dlm_migratable_lockres *)data;
-
 	/* lock resources should have already been moved to the
  	 * dlm->reco.resources list.  now move items from that list
  	 * to a temp list if the dead owner matches.  note that the
@@ -757,15 +817,18 @@
 			continue;
 
 		switch (ndata->state) {
+			/* should have moved beyond INIT but not to FINALIZE yet */
 			case DLM_RECO_NODE_DATA_INIT:
 			case DLM_RECO_NODE_DATA_DEAD:
-			case DLM_RECO_NODE_DATA_DONE:
 			case DLM_RECO_NODE_DATA_FINALIZE_SENT:
 				mlog(ML_ERROR, "bad ndata state for node %u:"
 				     " state=%d\n", ndata->node_num,
 				     ndata->state);
 				BUG();
 				break;
+			/* these states are possible at this point, anywhere along
+			 * the line of recovery */
+			case DLM_RECO_NODE_DATA_DONE:
 			case DLM_RECO_NODE_DATA_RECEIVING:
 			case DLM_RECO_NODE_DATA_REQUESTED:
 			case DLM_RECO_NODE_DATA_REQUESTING:
@@ -799,13 +862,31 @@
 {
 	struct dlm_lock_resource *res;
 	struct list_head *iter, *iter2;
+	struct dlm_lock *lock;
 
 	spin_lock(&dlm->spinlock);
 	list_for_each_safe(iter, iter2, &dlm->reco.resources) {
 		res = list_entry (iter, struct dlm_lock_resource, recovering);
+		/* always prune any $RECOVERY entries for dead nodes,
+		 * otherwise hangs can occur during later recovery */
 		if (dlm_is_recovery_lock(res->lockname.name,
-					 res->lockname.len))
+					 res->lockname.len)) {
+			spin_lock(&res->spinlock);
+			list_for_each_entry(lock, &res->granted, list) {
+				if (lock->ml.node == dead_node) {
+					mlog(0, "AHA! there was "
+					     "a $RECOVERY lock for dead "
+					     "node %u (%s)!\n", 
+					     dead_node, dlm->name);
+					list_del_init(&lock->list);
+					dlm_lock_put(lock);
+					break;
+				}
+			}
+			spin_unlock(&res->spinlock);
 			continue;
+		}
+
 		if (res->owner == dead_node) {
 			mlog(0, "found lockres owned by dead node while "
 				  "doing recovery for node %u. sending it.\n",
@@ -1179,7 +1260,7 @@
 again:
 		ret = dlm_lockres_master_requery(dlm, res, &real_master);
 		if (ret < 0) {
-			mlog(0, "dlm_lockres_master_requery failure: %d\n",
+			mlog(0, "dlm_lockres_master_requery ret=%d\n",
 				  ret);
 			goto again;
 		}
@@ -1757,6 +1838,7 @@
 	struct dlm_lock_resource *res;
 	int i;
 	struct list_head *bucket;
+	struct dlm_lock *lock;
 
 
 	/* purge any stale mles */
@@ -1780,10 +1862,25 @@
 		bucket = &(dlm->resources[i]);
 		list_for_each(iter, bucket) {
 			res = list_entry (iter, struct dlm_lock_resource, list);
+ 			/* always prune any $RECOVERY entries for dead nodes,
+ 			 * otherwise hangs can occur during later recovery */
 			if (dlm_is_recovery_lock(res->lockname.name,
-						 res->lockname.len))
+						 res->lockname.len)) {
+				spin_lock(&res->spinlock);
+				list_for_each_entry(lock, &res->granted, list) {
+					if (lock->ml.node == dead_node) {
+						mlog(0, "AHA! there was "
+						     "a $RECOVERY lock for dead "
+						     "node %u (%s)!\n",
+						     dead_node, dlm->name);
+						list_del_init(&lock->list);
+						dlm_lock_put(lock);
+						break;
+					}
+				}
+				spin_unlock(&res->spinlock);
 				continue;
-			
+			}			
 			spin_lock(&res->spinlock);
 			/* zero the lvb if necessary */
 			dlm_revalidate_lvb(dlm, res, dead_node);
@@ -1869,12 +1966,9 @@
 		return;
 
 	spin_lock(&dlm->spinlock);
-
 	set_bit(idx, dlm->live_nodes_map);
-
-	/* notify any mles attached to the heartbeat events */
-	dlm_hb_event_notify_attached(dlm, idx, 1);
-
+	/* do NOT notify mle attached to the heartbeat events.
+	 * new nodes are not interesting in mastery until joined. */
 	spin_unlock(&dlm->spinlock);
 
 	dlm_put(dlm);
@@ -1897,7 +1991,18 @@
 	mlog(0, "unlockast for recovery lock fired!\n");
 }
 
-
+/*
+ * dlm_pick_recovery_master will continually attempt to use
+ * dlmlock() on the special "$RECOVERY" lockres with the
+ * LKM_NOQUEUE flag to get an EX.  every thread that enters
+ * this function on each node racing to become the recovery
+ * master will not stop attempting this until either:
+ * a) this node gets the EX (and becomes the recovery master),
+ * or b) dlm->reco.new_master gets set to some nodenum 
+ * != O2NM_INVALID_NODE_NUM (another node will do the reco).
+ * so each time a recovery master is needed, the entire cluster
+ * will sync at this point.  if the new master dies, that will
+ * be detected in dlm_do_recovery */
 static int dlm_pick_recovery_master(struct dlm_ctxt *dlm)
 {
 	enum dlm_status ret;
@@ -1906,23 +2011,45 @@
 
 	mlog(0, "starting recovery of %s at %lu, dead=%u, this=%u\n",
 	     dlm->name, jiffies, dlm->reco.dead_node, dlm->node_num);
-retry:
+again:	
 	memset(&lksb, 0, sizeof(lksb));
 
 	ret = dlmlock(dlm, LKM_EXMODE, &lksb, LKM_NOQUEUE|LKM_RECOVERY,
 		      DLM_RECOVERY_LOCK_NAME, dlm_reco_ast, dlm, dlm_reco_bast);
 
+	mlog(0, "%s: dlmlock($RECOVERY) returned %d, lksb=%d\n",
+	     dlm->name, ret, lksb.status);
+
 	if (ret == DLM_NORMAL) {
 		mlog(0, "dlm=%s dlmlock says I got it (this=%u)\n",
 		     dlm->name, dlm->node_num);
-		/* I am master, send message to all nodes saying
-		 * that I am beginning a recovery session */
-		status = dlm_send_begin_reco_message(dlm,
-					      dlm->reco.dead_node);
+		
+		/* got the EX lock.  check to see if another node 
+		 * just became the reco master */
+		if (dlm_reco_master_ready(dlm)) {
+			mlog(0, "%s: got reco EX lock, but %u will "
+			     "do the recovery\n", dlm->name,
+			     dlm->reco.new_master);
+			status = -EEXIST;
+		} else {
+			status = dlm_send_begin_reco_message(dlm,
+				      dlm->reco.dead_node);
+			/* this always succeeds */
+			BUG_ON(status);
+
+			/* set the new_master to this node */
+			spin_lock(&dlm->spinlock);
+			dlm->reco.new_master = dlm->node_num;
+			spin_unlock(&dlm->spinlock);
+		}
 
 		/* recovery lock is a special case.  ast will not get fired,
 		 * so just go ahead and unlock it. */
 		ret = dlmunlock(dlm, &lksb, 0, dlm_reco_unlock_ast, dlm);
+		if (ret == DLM_DENIED) {
+			mlog(0, "got DLM_DENIED, trying LKM_CANCEL\n");
+			ret = dlmunlock(dlm, &lksb, LKM_CANCEL, dlm_reco_unlock_ast, dlm);
+		}
 		if (ret != DLM_NORMAL) {
 			/* this would really suck. this could only happen
 			 * if there was a network error during the unlock
@@ -1930,20 +2057,42 @@
 			 * is actually "done" and the lock structure is
 			 * even freed.  we can continue, but only
 			 * because this specific lock name is special. */
-			mlog(0, "dlmunlock returned %d\n", ret);
-		}
-
-		if (status < 0) {
-			mlog(0, "failed to send recovery message. "
-				   "must retry with new node map.\n");
-			goto retry;
+			mlog(ML_ERROR, "dlmunlock returned %d\n", ret);
 		}
 	} else if (ret == DLM_NOTQUEUED) {
 		mlog(0, "dlm=%s dlmlock says another node got it (this=%u)\n",
 		     dlm->name, dlm->node_num);
 		/* another node is master. wait on
-		 * reco.new_master != O2NM_INVALID_NODE_NUM */
+		 * reco.new_master != O2NM_INVALID_NODE_NUM 
+		 * for at most one second */
+		wait_event_timeout(dlm->dlm_reco_thread_wq,
+					 dlm_reco_master_ready(dlm),
+					 msecs_to_jiffies(1000));
+		if (!dlm_reco_master_ready(dlm)) {
+			mlog(0, "%s: reco master taking awhile\n",
+			     dlm->name);
+			goto again;
+		}
+		/* another node has informed this one that it is reco master */
+		mlog(0, "%s: reco master %u is ready to recover %u\n",
+		     dlm->name, dlm->reco.new_master, dlm->reco.dead_node);
 		status = -EEXIST;
+	} else {
+		struct dlm_lock_resource *res;
+
+		/* dlmlock returned something other than NOTQUEUED or NORMAL */
+		mlog(ML_ERROR, "%s: got %s from dlmlock($RECOVERY), "
+		     "lksb.status=%s\n", dlm->name, dlm_errname(ret),
+		     dlm_errname(lksb.status));
+		res = dlm_lookup_lockres(dlm, DLM_RECOVERY_LOCK_NAME,
+					 DLM_RECOVERY_LOCK_NAME_LEN);
+		if (res) {
+			dlm_print_one_lock_resource(res);
+			dlm_lockres_put(res);
+		} else {
+			mlog(ML_ERROR, "recovery lock not found\n");
+		}
+		BUG();
 	}
 
 	return status;
@@ -1982,7 +2131,7 @@
 			mlog(0, "not sending begin reco to self\n");
 			continue;
 		}
-
+retry:
 		ret = -EINVAL;
 		mlog(0, "attempting to send begin reco msg to %d\n",
 			  nodenum);
@@ -1991,8 +2140,17 @@
 		/* negative status is handled ok by caller here */
 		if (ret >= 0)
 			ret = status;
+		if (dlm_is_host_down(ret)) {
+			/* node is down.  not involved in recovery
+			 * so just keep going */
+			mlog(0, "%s: node %u was down when sending "
+			     "begin reco msg (%d)\n", dlm->name, nodenum, ret);
+			ret = 0;
+		}
 		if (ret < 0) {
 			struct dlm_lock_resource *res;
+			/* this is now a serious problem, possibly ENOMEM 
+			 * in the network stack.  must retry */
 			mlog_errno(ret);
 			mlog(ML_ERROR, "begin reco of dlm %s to node %u "
 			    " returned %d\n", dlm->name, nodenum, ret);
@@ -2004,7 +2162,10 @@
 			} else {
 				mlog(ML_ERROR, "recovery lock not found\n");
 			}
-			break;
+			/* sleep for a bit in hopes that we can avoid 
+			 * another ENOMEM */
+			msleep(100);
+			goto retry;
 		}
 	}
 
@@ -2027,19 +2188,34 @@
 
 	spin_lock(&dlm->spinlock);
 	if (dlm->reco.new_master != O2NM_INVALID_NODE_NUM) {
-		mlog(0, "new_master already set to %u!\n",
-			  dlm->reco.new_master);
+		if (test_bit(dlm->reco.new_master, dlm->recovery_map)) {
+			mlog(0, "%s: new_master %u died, changing "
+			     "to %u\n", dlm->name, dlm->reco.new_master,
+			     br->node_idx);
+		} else {
+			mlog(0, "%s: new_master %u NOT DEAD, changing "
+			     "to %u\n", dlm->name, dlm->reco.new_master,
+			     br->node_idx);
+			/* may not have seen the new master as dead yet */
+		}
 	}
 	if (dlm->reco.dead_node != O2NM_INVALID_NODE_NUM) {
-		mlog(0, "dead_node already set to %u!\n",
-			  dlm->reco.dead_node);
+		mlog(ML_NOTICE, "%s: dead_node previously set to %u, "
+		     "node %u changing it to %u\n", dlm->name, 
+		     dlm->reco.dead_node, br->node_idx, br->dead_node);
 	}
 	dlm->reco.new_master = br->node_idx;
 	dlm->reco.dead_node = br->dead_node;
 	if (!test_bit(br->dead_node, dlm->recovery_map)) {
-		mlog(ML_ERROR, "recovery master %u sees %u as dead, but this "
+		mlog(0, "recovery master %u sees %u as dead, but this "
 		     "node has not yet.  marking %u as dead\n",
 		     br->node_idx, br->dead_node, br->dead_node);
+		if (!test_bit(br->dead_node, dlm->domain_map) ||
+		    !test_bit(br->dead_node, dlm->live_nodes_map))
+			mlog(0, "%u not in domain/live_nodes map "
+			     "so setting it in reco map manually\n",
+			     br->dead_node);
+		set_bit(br->dead_node, dlm->recovery_map);
 		__dlm_hb_node_down(dlm, br->dead_node);
 	}
 	spin_unlock(&dlm->spinlock);
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c
index cec2ce1..c95f08d 100644
--- a/fs/ocfs2/dlm/dlmunlock.c
+++ b/fs/ocfs2/dlm/dlmunlock.c
@@ -188,6 +188,19 @@
 			actions &= ~(DLM_UNLOCK_REMOVE_LOCK|
 				     DLM_UNLOCK_REGRANT_LOCK|
 				     DLM_UNLOCK_CLEAR_CONVERT_TYPE);
+		} else if (status == DLM_RECOVERING || 
+			   status == DLM_MIGRATING || 
+			   status == DLM_FORWARD) {
+			/* must clear the actions because this unlock
+			 * is about to be retried.  cannot free or do
+			 * any list manipulation. */
+			mlog(0, "%s:%.*s: clearing actions, %s\n",
+			     dlm->name, res->lockname.len,
+			     res->lockname.name,
+			     status==DLM_RECOVERING?"recovering":
+			     (status==DLM_MIGRATING?"migrating":
+			      "forward"));
+			actions = 0;
 		}
 		if (flags & LKM_CANCEL)
 			lock->cancel_pending = 0;
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c
index e1fdd28..c3764f4 100644
--- a/fs/ocfs2/dlm/userdlm.c
+++ b/fs/ocfs2/dlm/userdlm.c
@@ -27,7 +27,7 @@
  * Boston, MA 021110-1307, USA.
  */
 
-#include <asm/signal.h>
+#include <linux/signal.h>
 
 #include <linux/module.h>
 #include <linux/fs.h>
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index f2fb40c..b6ba292 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -262,8 +262,7 @@
 		el = &eb->h_list;
 	}
 
-	if (el->l_tree_depth)
-		BUG();
+	BUG_ON(el->l_tree_depth);
 
 	for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
 		rec = &el->l_recs[i];
@@ -364,8 +363,8 @@
 		return ret;
 	}
 
-	if (ent->e_tree_depth)
-		BUG();  /* FIXME: Make sure this isn't a corruption */
+	/* FIXME: Make sure this isn't a corruption */
+	BUG_ON(ent->e_tree_depth);
 
 	*ret_ent = ent;
 
@@ -423,8 +422,7 @@
 					  le32_to_cpu(rec->e_clusters), NULL,
 					  NULL);
 
-	if (!old_ent)
-		BUG();
+	BUG_ON(!old_ent);
 
 	ret = -EEXIST;
 	if (old_ent->e_tree_depth < tree_depth)
@@ -988,7 +986,7 @@
 	return 0;
 }
 
-void __exit exit_ocfs2_extent_maps(void)
+void exit_ocfs2_extent_maps(void)
 {
 	kmem_cache_destroy(ocfs2_em_ent_cachep);
 }
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index eaf33ca..1715bc9 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1022,8 +1022,9 @@
 		}
 		newsize = count + saved_pos;
 
-		mlog(0, "pos=%lld newsize=%"MLFu64" cursize=%lld\n",
-		     saved_pos, newsize, i_size_read(inode));
+		mlog(0, "pos=%lld newsize=%lld cursize=%lld\n",
+		     (long long) saved_pos, (long long) newsize,
+		     (long long) i_size_read(inode));
 
 		/* No need for a higher level metadata lock if we're
 		 * never going past i_size. */
@@ -1042,8 +1043,9 @@
 		spin_unlock(&OCFS2_I(inode)->ip_lock);
 
 		mlog(0, "Writing at EOF, may need more allocation: "
-		     "i_size = %lld, newsize = %"MLFu64", need %u clusters\n",
-		     i_size_read(inode), newsize, clusters);
+		     "i_size = %lld, newsize = %lld, need %u clusters\n",
+		     (long long) i_size_read(inode), (long long) newsize,
+		     clusters);
 
 		/* We only want to continue the rest of this loop if
 		 * our extend will actually require more
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index d4ecc06..8122489 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -903,10 +903,10 @@
 			"Clear inode of %"MLFu64", inode is locked\n",
 			oi->ip_blkno);
 
-	mlog_bug_on_msg(down_trylock(&oi->ip_io_sem),
-			"Clear inode of %"MLFu64", io_sem is locked\n",
+	mlog_bug_on_msg(!mutex_trylock(&oi->ip_io_mutex),
+			"Clear inode of %"MLFu64", io_mutex is locked\n",
 			oi->ip_blkno);
-	up(&oi->ip_io_sem);
+	mutex_unlock(&oi->ip_io_mutex);
 
 	/*
 	 * down_trylock() returns 0, down_write_trylock() returns 1
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 9b01774..84c5079 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -46,10 +46,10 @@
 	struct list_head		ip_io_markers;
 	int				ip_orphaned_slot;
 
-	struct semaphore		ip_io_sem;
+	struct mutex			ip_io_mutex;
 
 	/* Used by the journalling code to attach an inode to a
-	 * handle.  These are protected by ip_io_sem in order to lock
+	 * handle.  These are protected by ip_io_mutex in order to lock
 	 * out other I/O to the inode until we either commit or
 	 * abort. */
 	struct list_head		ip_handle_list;
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 303c8d9..fa0bcac 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -147,8 +147,7 @@
 
 	mlog_entry("(max_buffs = %d)\n", max_buffs);
 
-	if (!osb || !osb->journal->j_journal)
-		BUG();
+	BUG_ON(!osb || !osb->journal->j_journal);
 
 	if (ocfs2_is_hard_readonly(osb)) {
 		ret = -EROFS;
@@ -401,7 +400,7 @@
 	 * j_trans_barrier for us. */
 	ocfs2_set_inode_lock_trans(OCFS2_SB(inode->i_sb)->journal, inode);
 
-	down(&OCFS2_I(inode)->ip_io_sem);
+	mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
 	switch (type) {
 	case OCFS2_JOURNAL_ACCESS_CREATE:
 	case OCFS2_JOURNAL_ACCESS_WRITE:
@@ -416,7 +415,7 @@
 		status = -EINVAL;
 		mlog(ML_ERROR, "Uknown access type!\n");
 	}
-	up(&OCFS2_I(inode)->ip_io_sem);
+	mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
 
 	if (status < 0)
 		mlog(ML_ERROR, "Error %d getting %d access to buffer!\n",
@@ -561,7 +560,11 @@
 	SET_INODE_JOURNAL(inode);
 	OCFS2_I(inode)->ip_open_count++;
 
-	status = ocfs2_meta_lock(inode, NULL, &bh, 1);
+	/* Skip recovery waits here - journal inode metadata never
+	 * changes in a live cluster so it can be considered an
+	 * exception to the rule. */
+	status = ocfs2_meta_lock_full(inode, NULL, &bh, 1,
+				      OCFS2_META_LOCK_RECOVERY);
 	if (status < 0) {
 		if (status != -ERESTARTSYS)
 			mlog(ML_ERROR, "Could not get lock on journal!\n");
@@ -672,8 +675,7 @@
 
 	mlog_entry_void();
 
-	if (!osb)
-		BUG();
+	BUG_ON(!osb);
 
 	journal = osb->journal;
 	if (!journal)
@@ -805,8 +807,7 @@
 
 	mlog_entry_void();
 
-	if (!journal)
-		BUG();
+	BUG_ON(!journal);
 
 	status = journal_wipe(journal->j_journal, full);
 	if (status < 0) {
@@ -1072,10 +1073,10 @@
 					NULL);
 
 bail:
-	down(&osb->recovery_lock);
+	mutex_lock(&osb->recovery_lock);
 	if (!status &&
 	    !ocfs2_node_map_is_empty(osb, &osb->recovery_map)) {
-		up(&osb->recovery_lock);
+		mutex_unlock(&osb->recovery_lock);
 		goto restart;
 	}
 
@@ -1083,7 +1084,7 @@
 	mb(); /* sync with ocfs2_recovery_thread_running */
 	wake_up(&osb->recovery_event);
 
-	up(&osb->recovery_lock);
+	mutex_unlock(&osb->recovery_lock);
 
 	mlog_exit(status);
 	/* no one is callint kthread_stop() for us so the kthread() api
@@ -1098,7 +1099,7 @@
 	mlog_entry("(node_num=%d, osb->node_num = %d)\n",
 		   node_num, osb->node_num);
 
-	down(&osb->recovery_lock);
+	mutex_lock(&osb->recovery_lock);
 	if (osb->disable_recovery)
 		goto out;
 
@@ -1120,7 +1121,7 @@
 	}
 
 out:
-	up(&osb->recovery_lock);
+	mutex_unlock(&osb->recovery_lock);
 	wake_up(&osb->recovery_event);
 
 	mlog_exit_void();
@@ -1271,8 +1272,7 @@
 
 	/* Should not ever be called to recover ourselves -- in that
 	 * case we should've called ocfs2_journal_load instead. */
-	if (osb->node_num == node_num)
-		BUG();
+	BUG_ON(osb->node_num == node_num);
 
 	slot_num = ocfs2_node_num_to_slot(si, node_num);
 	if (slot_num == OCFS2_INVALID_SLOT) {
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index f468c60..8d8e477 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -33,6 +33,7 @@
 #include <linux/rbtree.h>
 #include <linux/workqueue.h>
 #include <linux/kref.h>
+#include <linux/mutex.h>
 
 #include "cluster/nodemanager.h"
 #include "cluster/heartbeat.h"
@@ -233,7 +234,7 @@
 	struct proc_dir_entry *proc_sub_dir; /* points to /proc/fs/ocfs2/<maj_min> */
 
 	atomic_t vol_state;
-	struct semaphore recovery_lock;
+	struct mutex recovery_lock;
 	struct task_struct *recovery_thread_task;
 	int disable_recovery;
 	wait_queue_head_t checkpoint_event;
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 364d64b..046824b 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -932,7 +932,7 @@
 		oi->ip_dir_start_lookup = 0;
 
 		init_rwsem(&oi->ip_alloc_sem);
-		init_MUTEX(&(oi->ip_io_sem));
+		mutex_init(&oi->ip_io_mutex);
 
 		oi->ip_blkno = 0ULL;
 		oi->ip_clusters = 0;
@@ -1137,9 +1137,9 @@
 
 	/* disable any new recovery threads and wait for any currently
 	 * running ones to exit. Do this before setting the vol_state. */
-	down(&osb->recovery_lock);
+	mutex_lock(&osb->recovery_lock);
 	osb->disable_recovery = 1;
-	up(&osb->recovery_lock);
+	mutex_unlock(&osb->recovery_lock);
 	wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb));
 
 	/* At this point, we know that no more recovery threads can be
@@ -1254,8 +1254,7 @@
 	osb->sb = sb;
 	/* Save off for ocfs2_rw_direct */
 	osb->s_sectsize_bits = blksize_bits(sector_size);
-	if (!osb->s_sectsize_bits)
-		BUG();
+	BUG_ON(!osb->s_sectsize_bits);
 
 	osb->net_response_ids = 0;
 	spin_lock_init(&osb->net_response_lock);
@@ -1283,7 +1282,7 @@
 	snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
 		 MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
 
-	init_MUTEX(&osb->recovery_lock);
+	mutex_init(&osb->recovery_lock);
 
 	osb->disable_recovery = 0;
 	osb->recovery_thread_task = NULL;
diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c
index 600a8bc..fc29cb7 100644
--- a/fs/ocfs2/sysfile.c
+++ b/fs/ocfs2/sysfile.c
@@ -77,8 +77,7 @@
 	if (arr && ((inode = *arr) != NULL)) {
 		/* get a ref in addition to the array ref */
 		inode = igrab(inode);
-		if (!inode)
-			BUG();
+		BUG_ON(!inode);
 
 		return inode;
 	}
@@ -89,8 +88,7 @@
 	/* add one more if putting into array for first time */
 	if (arr && inode) {
 		*arr = igrab(inode);
-		if (!*arr)
-			BUG();
+		BUG_ON(!*arr);
 	}
 	return inode;
 }
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c
index 3a0458f..300b5be 100644
--- a/fs/ocfs2/uptodate.c
+++ b/fs/ocfs2/uptodate.c
@@ -388,7 +388,7 @@
 	}
 }
 
-/* Item insertion is guarded by ip_io_sem, so the insertion path takes
+/* Item insertion is guarded by ip_io_mutex, so the insertion path takes
  * advantage of this by not rechecking for a duplicate insert during
  * the slow case. Additionally, if the cache needs to be bumped up to
  * a tree, the code will not recheck after acquiring the lock --
@@ -418,7 +418,7 @@
 	     (unsigned long long) bh->b_blocknr);
 
 	/* No need to recheck under spinlock - insertion is guarded by
-	 * ip_io_sem */
+	 * ip_io_mutex */
 	spin_lock(&oi->ip_lock);
 	if (ocfs2_insert_can_use_array(oi, ci)) {
 		/* Fast case - it's an array and there's a free
@@ -440,7 +440,7 @@
 
 /* Called against a newly allocated buffer. Most likely nobody should
  * be able to read this sort of metadata while it's still being
- * allocated, but this is careful to take ip_io_sem anyway. */
+ * allocated, but this is careful to take ip_io_mutex anyway. */
 void ocfs2_set_new_buffer_uptodate(struct inode *inode,
 				   struct buffer_head *bh)
 {
@@ -451,9 +451,9 @@
 
 	set_buffer_uptodate(bh);
 
-	down(&oi->ip_io_sem);
+	mutex_lock(&oi->ip_io_mutex);
 	ocfs2_set_buffer_uptodate(inode, bh);
-	up(&oi->ip_io_sem);
+	mutex_unlock(&oi->ip_io_mutex);
 }
 
 /* Requires ip_lock. */
@@ -537,7 +537,7 @@
 	return 0;
 }
 
-void __exit exit_ocfs2_uptodate_cache(void)
+void exit_ocfs2_uptodate_cache(void)
 {
 	if (ocfs2_uptodate_cachep)
 		kmem_cache_destroy(ocfs2_uptodate_cachep);
diff --git a/fs/ocfs2/uptodate.h b/fs/ocfs2/uptodate.h
index e5aacdf..01cd32d 100644
--- a/fs/ocfs2/uptodate.h
+++ b/fs/ocfs2/uptodate.h
@@ -27,7 +27,7 @@
 #define OCFS2_UPTODATE_H
 
 int __init init_ocfs2_uptodate_cache(void);
-void __exit exit_ocfs2_uptodate_cache(void);
+void exit_ocfs2_uptodate_cache(void);
 
 void ocfs2_metadata_cache_init(struct inode *inode);
 void ocfs2_metadata_cache_purge(struct inode *inode);
diff --git a/fs/open.c b/fs/open.c
index 8e20c1f..70e0230 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -20,6 +20,7 @@
 #include <linux/security.h>
 #include <linux/mount.h>
 #include <linux/vfs.h>
+#include <linux/fcntl.h>
 #include <asm/uaccess.h>
 #include <linux/fs.h>
 #include <linux/personality.h>
@@ -383,7 +384,7 @@
 
 		error = get_user(newattrs.ia_atime.tv_sec, &times->actime);
 		newattrs.ia_atime.tv_nsec = 0;
-		if (!error) 
+		if (!error)
 			error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime);
 		newattrs.ia_mtime.tv_nsec = 0;
 		if (error)
@@ -414,14 +415,14 @@
  * must be owner or have write permission.
  * Else, update from *times, must be owner or super user.
  */
-long do_utimes(char __user * filename, struct timeval * times)
+long do_utimes(int dfd, char __user *filename, struct timeval *times)
 {
 	int error;
 	struct nameidata nd;
 	struct inode * inode;
 	struct iattr newattrs;
 
-	error = user_path_walk(filename, &nd);
+	error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
 
 	if (error)
 		goto out;
@@ -461,13 +462,18 @@
 	return error;
 }
 
-asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utimes)
+asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes)
 {
 	struct timeval times[2];
 
 	if (utimes && copy_from_user(&times, utimes, sizeof(times)))
 		return -EFAULT;
-	return do_utimes(filename, utimes ? times : NULL);
+	return do_utimes(dfd, filename, utimes ? times : NULL);
+}
+
+asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes)
+{
+	return sys_futimesat(AT_FDCWD, filename, utimes);
 }
 
 
@@ -476,7 +482,7 @@
  * We do this by temporarily clearing all FS-related capabilities and
  * switching the fsuid/fsgid around to the real ones.
  */
-asmlinkage long sys_access(const char __user * filename, int mode)
+asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 {
 	struct nameidata nd;
 	int old_fsuid, old_fsgid;
@@ -506,7 +512,7 @@
 	else
 		current->cap_effective = current->cap_permitted;
 
-	res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
+	res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
 	if (!res) {
 		res = vfs_permission(&nd, mode);
 		/* SuS v2 requires we report a read only fs too */
@@ -523,6 +529,11 @@
 	return res;
 }
 
+asmlinkage long sys_access(const char __user *filename, int mode)
+{
+	return sys_faccessat(AT_FDCWD, filename, mode);
+}
+
 asmlinkage long sys_chdir(const char __user * filename)
 {
 	struct nameidata nd;
@@ -635,14 +646,15 @@
 	return err;
 }
 
-asmlinkage long sys_chmod(const char __user * filename, mode_t mode)
+asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
+			     mode_t mode)
 {
 	struct nameidata nd;
 	struct inode * inode;
 	int error;
 	struct iattr newattrs;
 
-	error = user_path_walk(filename, &nd);
+	error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
 	if (error)
 		goto out;
 	inode = nd.dentry->d_inode;
@@ -669,6 +681,11 @@
 	return error;
 }
 
+asmlinkage long sys_chmod(const char __user *filename, mode_t mode)
+{
+	return sys_fchmodat(AT_FDCWD, filename, mode);
+}
+
 static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
 {
 	struct inode * inode;
@@ -717,6 +734,26 @@
 	return error;
 }
 
+asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
+			     gid_t group, int flag)
+{
+	struct nameidata nd;
+	int error = -EINVAL;
+	int follow;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
+	error = __user_walk_fd(dfd, filename, follow, &nd);
+	if (!error) {
+		error = chown_common(nd.dentry, user, group);
+		path_release(&nd);
+	}
+out:
+	return error;
+}
+
 asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group)
 {
 	struct nameidata nd;
@@ -820,7 +857,8 @@
  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
  * used by symlinks.
  */
-struct file *filp_open(const char * filename, int flags, int mode)
+static struct file *do_filp_open(int dfd, const char *filename, int flags,
+				 int mode)
 {
 	int namei_flags, error;
 	struct nameidata nd;
@@ -829,12 +867,17 @@
 	if ((namei_flags+1) & O_ACCMODE)
 		namei_flags++;
 
-	error = open_namei(filename, namei_flags, mode, &nd);
+	error = open_namei(dfd, filename, namei_flags, mode, &nd);
 	if (!error)
 		return nameidata_to_filp(&nd, flags);
 
 	return ERR_PTR(error);
 }
+
+struct file *filp_open(const char *filename, int flags, int mode)
+{
+	return do_filp_open(AT_FDCWD, filename, flags, mode);
+}
 EXPORT_SYMBOL(filp_open);
 
 /**
@@ -991,7 +1034,7 @@
 EXPORT_SYMBOL(put_unused_fd);
 
 /*
- * Install a file pointer in the fd array.  
+ * Install a file pointer in the fd array.
  *
  * The VFS is full of places where we drop the files lock between
  * setting the open_fds bitmap and installing the file in the file
@@ -1016,7 +1059,7 @@
 
 EXPORT_SYMBOL(fd_install);
 
-long do_sys_open(const char __user *filename, int flags, int mode)
+long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
 {
 	char *tmp = getname(filename);
 	int fd = PTR_ERR(tmp);
@@ -1024,7 +1067,7 @@
 	if (!IS_ERR(tmp)) {
 		fd = get_unused_fd();
 		if (fd >= 0) {
-			struct file *f = filp_open(tmp, flags, mode);
+			struct file *f = do_filp_open(dfd, tmp, flags, mode);
 			if (IS_ERR(f)) {
 				put_unused_fd(fd);
 				fd = PTR_ERR(f);
@@ -1043,10 +1086,20 @@
 	if (force_o_largefile())
 		flags |= O_LARGEFILE;
 
-	return do_sys_open(filename, flags, mode);
+	return do_sys_open(AT_FDCWD, filename, flags, mode);
 }
 EXPORT_SYMBOL_GPL(sys_open);
 
+asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
+			   int mode)
+{
+	if (force_o_largefile())
+		flags |= O_LARGEFILE;
+
+	return do_sys_open(dfd, filename, flags, mode);
+}
+EXPORT_SYMBOL_GPL(sys_openat);
+
 #ifndef __alpha__
 
 /*
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 8f80142..1d24fea 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -548,7 +548,7 @@
 	}
 	seq_printf(p, "intr %llu", (unsigned long long)sum);
 
-#if !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA)
+#if !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA) && !defined(CONFIG_IA64)
 	for (i = 0; i < NR_IRQS; i++)
 		seq_printf(p, " %u", kstat_irqs(i));
 #endif
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index a4ef91b..b4199ec 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -35,7 +35,7 @@
  
 	size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
 	if (size != sizeof(struct v2_disk_dqheader)) {
-		printk("quota_v2: failed read expected=%d got=%d\n",
+		printk("quota_v2: failed read expected=%zd got=%zd\n",
 			sizeof(struct v2_disk_dqheader), size);
 		return 0;
 	}
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index 9dd71e8..d71ac65 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -150,18 +150,15 @@
 				if (d_reclen <= 32) {
 					local_buf = small_buf;
 				} else {
-					local_buf =
-					    reiserfs_kmalloc(d_reclen, GFP_NOFS,
-							     inode->i_sb);
+					local_buf = kmalloc(d_reclen,
+							    GFP_NOFS);
 					if (!local_buf) {
 						pathrelse(&path_to_entry);
 						ret = -ENOMEM;
 						goto out;
 					}
 					if (item_moved(&tmp_ih, &path_to_entry)) {
-						reiserfs_kfree(local_buf,
-							       d_reclen,
-							       inode->i_sb);
+						kfree(local_buf);
 						goto research;
 					}
 				}
@@ -174,15 +171,12 @@
 				    (dirent, local_buf, d_reclen, d_off, d_ino,
 				     DT_UNKNOWN) < 0) {
 					if (local_buf != small_buf) {
-						reiserfs_kfree(local_buf,
-							       d_reclen,
-							       inode->i_sb);
+						kfree(local_buf);
 					}
 					goto end;
 				}
 				if (local_buf != small_buf) {
-					reiserfs_kfree(local_buf, d_reclen,
-						       inode->i_sb);
+					kfree(local_buf);
 				}
 				// next entry should be looked for with such offset
 				next_pos = deh_offset(deh) + 1;
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index ad6fa96..f347317 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -192,6 +192,8 @@
 
 	allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) *
 				   sizeof(b_blocknr_t), GFP_NOFS);
+	if (!allocated_blocks)
+		return -ENOMEM;
 
 	/* First we compose a key to point at the writing position, we want to do
 	   that outside of any locking region. */
@@ -1285,6 +1287,23 @@
 	struct reiserfs_transaction_handle th;
 	th.t_trans_id = 0;
 
+	/* If a filesystem is converted from 3.5 to 3.6, we'll have v3.5 items
+	* lying around (most of the disk, in fact). Despite the filesystem
+	* now being a v3.6 format, the old items still can't support large
+	* file sizes. Catch this case here, as the rest of the VFS layer is
+	* oblivious to the different limitations between old and new items.
+	* reiserfs_setattr catches this for truncates. This chunk is lifted
+	* from generic_write_checks. */
+	if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 &&
+	    *ppos + count > MAX_NON_LFS) {
+		if (*ppos >= MAX_NON_LFS) {
+			send_sig(SIGXFSZ, current, 0);
+			return -EFBIG;
+		}
+		if (count > MAX_NON_LFS - (unsigned long)*ppos)
+			count = MAX_NON_LFS - (unsigned long)*ppos;
+	}
+
 	if (file->f_flags & O_DIRECT) {	// Direct IO needs treatment
 		ssize_t result, after_file_end = 0;
 		if ((*ppos + count >= inode->i_size)
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
index 4582988..aa22588 100644
--- a/fs/reiserfs/fix_node.c
+++ b/fs/reiserfs/fix_node.c
@@ -2021,38 +2021,6 @@
 	return CARRY_ON;
 }
 
-#ifdef CONFIG_REISERFS_CHECK
-void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s)
-{
-	void *vp;
-	static size_t malloced;
-
-	vp = kmalloc(size, flags);
-	if (vp) {
-		REISERFS_SB(s)->s_kmallocs += size;
-		if (REISERFS_SB(s)->s_kmallocs > malloced + 200000) {
-			reiserfs_warning(s,
-					 "vs-8301: reiserfs_kmalloc: allocated memory %d",
-					 REISERFS_SB(s)->s_kmallocs);
-			malloced = REISERFS_SB(s)->s_kmallocs;
-		}
-	}
-	return vp;
-}
-
-void reiserfs_kfree(const void *vp, size_t size, struct super_block *s)
-{
-	kfree(vp);
-
-	REISERFS_SB(s)->s_kmallocs -= size;
-	if (REISERFS_SB(s)->s_kmallocs < 0)
-		reiserfs_warning(s,
-				 "vs-8302: reiserfs_kfree: allocated memory %d",
-				 REISERFS_SB(s)->s_kmallocs);
-
-}
-#endif
-
 static int get_virtual_node_size(struct super_block *sb, struct buffer_head *bh)
 {
 	int max_num_of_items;
@@ -2086,7 +2054,7 @@
 		/* we have to allocate more memory for virtual node */
 		if (tb->vn_buf) {
 			/* free memory allocated before */
-			reiserfs_kfree(tb->vn_buf, tb->vn_buf_size, tb->tb_sb);
+			kfree(tb->vn_buf);
 			/* this is not needed if kfree is atomic */
 			check_fs = 1;
 		}
@@ -2095,24 +2063,15 @@
 		tb->vn_buf_size = size;
 
 		/* get memory for virtual item */
-		buf =
-		    reiserfs_kmalloc(size, GFP_ATOMIC | __GFP_NOWARN,
-				     tb->tb_sb);
+		buf = kmalloc(size, GFP_ATOMIC | __GFP_NOWARN);
 		if (!buf) {
 			/* getting memory with GFP_KERNEL priority may involve
 			   balancing now (due to indirect_to_direct conversion on
 			   dcache shrinking). So, release path and collected
 			   resources here */
 			free_buffers_in_tb(tb);
-			buf = reiserfs_kmalloc(size, GFP_NOFS, tb->tb_sb);
+			buf = kmalloc(size, GFP_NOFS);
 			if (!buf) {
-#ifdef CONFIG_REISERFS_CHECK
-				reiserfs_warning(tb->tb_sb,
-						 "vs-8345: get_mem_for_virtual_node: "
-						 "kmalloc failed. reiserfs kmalloced %d bytes",
-						 REISERFS_SB(tb->tb_sb)->
-						 s_kmallocs);
-#endif
 				tb->vn_buf_size = 0;
 			}
 			tb->vn_buf = buf;
@@ -2619,7 +2578,6 @@
 		}
 	}
 
-	if (tb->vn_buf)
-		reiserfs_kfree(tb->vn_buf, tb->vn_buf_size, tb->tb_sb);
+	kfree(tb->vn_buf);
 
 }
diff --git a/fs/reiserfs/hashes.c b/fs/reiserfs/hashes.c
index a3ec238..e664ac1 100644
--- a/fs/reiserfs/hashes.c
+++ b/fs/reiserfs/hashes.c
@@ -21,7 +21,6 @@
 #include <linux/kernel.h>
 #include <linux/reiserfs_fs.h>
 #include <asm/types.h>
-#include <asm/bug.h>
 
 #define DELTA 0x9E3779B9
 #define FULLROUNDS 10		/* 32 is overkill, 16 is strong crypto */
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index ffa34b8..b33d67b 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2363,6 +2363,13 @@
 	int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize;
 	th.t_trans_id = 0;
 
+	/* no logging allowed when nonblocking or from PF_MEMALLOC */
+	if (checked && (current->flags & PF_MEMALLOC)) {
+		redirty_page_for_writepage(wbc, page);
+		unlock_page(page);
+		return 0;
+	}
+
 	/* The page dirty bit is cleared before writepage is called, which
 	 * means we have to tell create_empty_buffers to make dirty buffers
 	 * The page really should be up to date at this point, so tossing
@@ -2743,6 +2750,7 @@
 	int ret = 1;
 	struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb);
 
+	lock_buffer(bh);
 	spin_lock(&j->j_dirty_buffers_lock);
 	if (!buffer_mapped(bh)) {
 		goto free_jh;
@@ -2758,7 +2766,7 @@
 		if (buffer_journaled(bh) || buffer_journal_dirty(bh)) {
 			ret = 0;
 		}
-	} else if (buffer_dirty(bh) || buffer_locked(bh)) {
+	} else  if (buffer_dirty(bh)) {
 		struct reiserfs_journal_list *jl;
 		struct reiserfs_jh *jh = bh->b_private;
 
@@ -2784,6 +2792,7 @@
 		reiserfs_free_jh(bh);
 	}
 	spin_unlock(&j->j_dirty_buffers_lock);
+	unlock_buffer(bh);
 	return ret;
 }
 
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 4491fcf..b7a1795 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -152,18 +152,16 @@
 	struct reiserfs_bitmap_node *bn;
 	static int id;
 
-	bn = reiserfs_kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS,
-			      p_s_sb);
+	bn = kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS);
 	if (!bn) {
 		return NULL;
 	}
-	bn->data = reiserfs_kmalloc(p_s_sb->s_blocksize, GFP_NOFS, p_s_sb);
+	bn->data = kzalloc(p_s_sb->s_blocksize, GFP_NOFS);
 	if (!bn->data) {
-		reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb);
+		kfree(bn);
 		return NULL;
 	}
 	bn->id = id++;
-	memset(bn->data, 0, p_s_sb->s_blocksize);
 	INIT_LIST_HEAD(&bn->list);
 	return bn;
 }
@@ -197,8 +195,8 @@
 	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
 	journal->j_used_bitmap_nodes--;
 	if (journal->j_free_bitmap_nodes > REISERFS_MAX_BITMAP_NODES) {
-		reiserfs_kfree(bn->data, p_s_sb->s_blocksize, p_s_sb);
-		reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb);
+		kfree(bn->data);
+		kfree(bn);
 	} else {
 		list_add(&bn->list, &journal->j_bitmap_nodes);
 		journal->j_free_bitmap_nodes++;
@@ -276,8 +274,8 @@
 	while (next != &journal->j_bitmap_nodes) {
 		bn = list_entry(next, struct reiserfs_bitmap_node, list);
 		list_del(next);
-		reiserfs_kfree(bn->data, p_s_sb->s_blocksize, p_s_sb);
-		reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb);
+		kfree(bn->data);
+		kfree(bn);
 		next = journal->j_bitmap_nodes.next;
 		journal->j_free_bitmap_nodes--;
 	}
@@ -581,7 +579,7 @@
 			       jl->j_trans_id, jl->j_refcount);
 	}
 	if (--jl->j_refcount == 0)
-		reiserfs_kfree(jl, sizeof(struct reiserfs_journal_list), s);
+		kfree(jl);
 }
 
 /*
@@ -848,6 +846,14 @@
 			spin_lock(lock);
 			goto loop_next;
 		}
+		/* in theory, dirty non-uptodate buffers should never get here,
+		 * but the upper layer io error paths still have a few quirks.
+		 * Handle them here as gracefully as we can
+		 */
+		if (!buffer_uptodate(bh) && buffer_dirty(bh)) {
+			clear_buffer_dirty(bh);
+			ret = -EIO;
+		}
 		if (buffer_dirty(bh)) {
 			list_del_init(&jh->list);
 			list_add(&jh->list, &tmp);
@@ -879,6 +885,19 @@
 		if (!buffer_uptodate(bh)) {
 			ret = -EIO;
 		}
+		/* ugly interaction with invalidatepage here.
+		 * reiserfs_invalidate_page will pin any buffer that has a valid
+		 * journal head from an older transaction.  If someone else sets
+		 * our buffer dirty after we write it in the first loop, and
+		 * then someone truncates the page away, nobody will ever write
+		 * the buffer. We're safe if we write the page one last time
+		 * after freeing the journal header.
+		 */
+		if (buffer_dirty(bh) && unlikely(bh->b_page->mapping == NULL)) {
+			spin_unlock(lock);
+			ll_rw_block(WRITE, 1, &bh);
+			spin_lock(lock);
+		}
 		put_bh(bh);
 		cond_resched_lock(lock);
 	}
@@ -977,6 +996,7 @@
 	struct reiserfs_journal *journal = SB_JOURNAL(s);
 	int barrier = 0;
 	int retval = 0;
+	int write_len;
 
 	reiserfs_check_lock_depth(s, "flush_commit_list");
 
@@ -1018,24 +1038,35 @@
 	}
 
 	if (!list_empty(&jl->j_bh_list)) {
+		int ret;
 		unlock_kernel();
-		write_ordered_buffers(&journal->j_dirty_buffers_lock,
-				      journal, jl, &jl->j_bh_list);
+		ret = write_ordered_buffers(&journal->j_dirty_buffers_lock,
+					    journal, jl, &jl->j_bh_list);
+		if (ret < 0 && retval == 0)
+			retval = ret;
 		lock_kernel();
 	}
 	BUG_ON(!list_empty(&jl->j_bh_list));
 	/*
 	 * for the description block and all the log blocks, submit any buffers
-	 * that haven't already reached the disk
+	 * that haven't already reached the disk.  Try to write at least 256
+	 * log blocks. later on, we will only wait on blocks that correspond
+	 * to this transaction, but while we're unplugging we might as well
+	 * get a chunk of data on there.
 	 */
 	atomic_inc(&journal->j_async_throttle);
-	for (i = 0; i < (jl->j_len + 1); i++) {
+	write_len = jl->j_len + 1;
+	if (write_len < 256)
+		write_len = 256;
+	for (i = 0 ; i < write_len ; i++) {
 		bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + (jl->j_start + i) %
 		    SB_ONDISK_JOURNAL_SIZE(s);
 		tbh = journal_find_get_block(s, bn);
-		if (buffer_dirty(tbh))	/* redundant, ll_rw_block() checks */
-			ll_rw_block(SWRITE, 1, &tbh);
-		put_bh(tbh);
+		if (tbh) {
+			if (buffer_dirty(tbh))
+			    ll_rw_block(WRITE, 1, &tbh) ;
+			put_bh(tbh) ;
+		}
 	}
 	atomic_dec(&journal->j_async_throttle);
 
@@ -1818,8 +1849,7 @@
 static void free_journal_ram(struct super_block *p_s_sb)
 {
 	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
-	reiserfs_kfree(journal->j_current_jl,
-		       sizeof(struct reiserfs_journal_list), p_s_sb);
+	kfree(journal->j_current_jl);
 	journal->j_num_lists--;
 
 	vfree(journal->j_cnode_free_orig);
@@ -2093,21 +2123,15 @@
 	}
 	trans_id = get_desc_trans_id(desc);
 	/* now we know we've got a good transaction, and it was inside the valid time ranges */
-	log_blocks =
-	    reiserfs_kmalloc(get_desc_trans_len(desc) *
-			     sizeof(struct buffer_head *), GFP_NOFS, p_s_sb);
-	real_blocks =
-	    reiserfs_kmalloc(get_desc_trans_len(desc) *
-			     sizeof(struct buffer_head *), GFP_NOFS, p_s_sb);
+	log_blocks = kmalloc(get_desc_trans_len(desc) *
+			     sizeof(struct buffer_head *), GFP_NOFS);
+	real_blocks = kmalloc(get_desc_trans_len(desc) *
+			      sizeof(struct buffer_head *), GFP_NOFS);
 	if (!log_blocks || !real_blocks) {
 		brelse(c_bh);
 		brelse(d_bh);
-		reiserfs_kfree(log_blocks,
-			       get_desc_trans_len(desc) *
-			       sizeof(struct buffer_head *), p_s_sb);
-		reiserfs_kfree(real_blocks,
-			       get_desc_trans_len(desc) *
-			       sizeof(struct buffer_head *), p_s_sb);
+		kfree(log_blocks);
+		kfree(real_blocks);
 		reiserfs_warning(p_s_sb,
 				 "journal-1169: kmalloc failed, unable to mount FS");
 		return -1;
@@ -2145,12 +2169,8 @@
 			brelse_array(real_blocks, i);
 			brelse(c_bh);
 			brelse(d_bh);
-			reiserfs_kfree(log_blocks,
-				       get_desc_trans_len(desc) *
-				       sizeof(struct buffer_head *), p_s_sb);
-			reiserfs_kfree(real_blocks,
-				       get_desc_trans_len(desc) *
-				       sizeof(struct buffer_head *), p_s_sb);
+			kfree(log_blocks);
+			kfree(real_blocks);
 			return -1;
 		}
 	}
@@ -2166,12 +2186,8 @@
 			brelse_array(real_blocks, get_desc_trans_len(desc));
 			brelse(c_bh);
 			brelse(d_bh);
-			reiserfs_kfree(log_blocks,
-				       get_desc_trans_len(desc) *
-				       sizeof(struct buffer_head *), p_s_sb);
-			reiserfs_kfree(real_blocks,
-				       get_desc_trans_len(desc) *
-				       sizeof(struct buffer_head *), p_s_sb);
+			kfree(log_blocks);
+			kfree(real_blocks);
 			return -1;
 		}
 		memcpy(real_blocks[i]->b_data, log_blocks[i]->b_data,
@@ -2193,12 +2209,8 @@
 				     get_desc_trans_len(desc) - i);
 			brelse(c_bh);
 			brelse(d_bh);
-			reiserfs_kfree(log_blocks,
-				       get_desc_trans_len(desc) *
-				       sizeof(struct buffer_head *), p_s_sb);
-			reiserfs_kfree(real_blocks,
-				       get_desc_trans_len(desc) *
-				       sizeof(struct buffer_head *), p_s_sb);
+			kfree(log_blocks);
+			kfree(real_blocks);
 			return -1;
 		}
 		brelse(real_blocks[i]);
@@ -2217,12 +2229,8 @@
 	journal->j_trans_id = trans_id + 1;
 	brelse(c_bh);
 	brelse(d_bh);
-	reiserfs_kfree(log_blocks,
-		       le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *),
-		       p_s_sb);
-	reiserfs_kfree(real_blocks,
-		       le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *),
-		       p_s_sb);
+	kfree(log_blocks);
+	kfree(real_blocks);
 	return 0;
 }
 
@@ -2471,14 +2479,8 @@
 static struct reiserfs_journal_list *alloc_journal_list(struct super_block *s)
 {
 	struct reiserfs_journal_list *jl;
-      retry:
-	jl = reiserfs_kmalloc(sizeof(struct reiserfs_journal_list), GFP_NOFS,
-			      s);
-	if (!jl) {
-		yield();
-		goto retry;
-	}
-	memset(jl, 0, sizeof(*jl));
+	jl = kzalloc(sizeof(struct reiserfs_journal_list),
+		     GFP_NOFS | __GFP_NOFAIL);
 	INIT_LIST_HEAD(&jl->j_list);
 	INIT_LIST_HEAD(&jl->j_working_list);
 	INIT_LIST_HEAD(&jl->j_tail_bh_list);
@@ -2821,6 +2823,9 @@
 	    journal->j_cnode_free < (journal->j_trans_max * 3)) {
 		return 1;
 	}
+	/* protected by the BKL here */
+	journal->j_len_alloc += new_alloc;
+	th->t_blocks_allocated += new_alloc ;
 	return 0;
 }
 
@@ -3042,14 +3047,12 @@
 		}
 		return th;
 	}
-	th = reiserfs_kmalloc(sizeof(struct reiserfs_transaction_handle),
-			      GFP_NOFS, s);
+	th = kmalloc(sizeof(struct reiserfs_transaction_handle), GFP_NOFS);
 	if (!th)
 		return NULL;
 	ret = journal_begin(th, s, nblocks);
 	if (ret) {
-		reiserfs_kfree(th, sizeof(struct reiserfs_transaction_handle),
-			       s);
+		kfree(th);
 		return NULL;
 	}
 
@@ -3067,8 +3070,7 @@
 		ret = -EIO;
 	if (th->t_refcount == 0) {
 		SB_JOURNAL(s)->j_persistent_trans--;
-		reiserfs_kfree(th, sizeof(struct reiserfs_transaction_handle),
-			       s);
+		kfree(th);
 	}
 	return ret;
 }
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 8f8d8d0..c812330 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -456,7 +456,7 @@
 	/* get memory for composing the entry */
 	buflen = DEH_SIZE + ROUND_UP(namelen);
 	if (buflen > sizeof(small_buf)) {
-		buffer = reiserfs_kmalloc(buflen, GFP_NOFS, dir->i_sb);
+		buffer = kmalloc(buflen, GFP_NOFS);
 		if (buffer == 0)
 			return -ENOMEM;
 	} else
@@ -490,7 +490,7 @@
 	retval = reiserfs_find_entry(dir, name, namelen, &path, &de);
 	if (retval != NAME_NOT_FOUND) {
 		if (buffer != small_buf)
-			reiserfs_kfree(buffer, buflen, dir->i_sb);
+			kfree(buffer);
 		pathrelse(&path);
 
 		if (retval == IO_ERROR) {
@@ -515,7 +515,7 @@
 		reiserfs_warning(dir->i_sb,
 				 "reiserfs_add_entry: Congratulations! we have got hash function screwed up");
 		if (buffer != small_buf)
-			reiserfs_kfree(buffer, buflen, dir->i_sb);
+			kfree(buffer);
 		pathrelse(&path);
 		return -EBUSY;
 	}
@@ -535,7 +535,7 @@
 					 &entry_key);
 
 			if (buffer != small_buf)
-				reiserfs_kfree(buffer, buflen, dir->i_sb);
+				kfree(buffer);
 			pathrelse(&path);
 			return -EBUSY;
 		}
@@ -546,7 +546,7 @@
 	    reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer,
 				     paste_size);
 	if (buffer != small_buf)
-		reiserfs_kfree(buffer, buflen, dir->i_sb);
+		kfree(buffer);
 	if (retval) {
 		reiserfs_check_path(&path);
 		return retval;
@@ -1065,7 +1065,7 @@
 		goto out_failed;
 	}
 
-	name = reiserfs_kmalloc(item_len, GFP_NOFS, parent_dir->i_sb);
+	name = kmalloc(item_len, GFP_NOFS);
 	if (!name) {
 		drop_new_inode(inode);
 		retval = -ENOMEM;
@@ -1079,14 +1079,14 @@
 	retval = journal_begin(&th, parent_dir->i_sb, jbegin_count);
 	if (retval) {
 		drop_new_inode(inode);
-		reiserfs_kfree(name, item_len, parent_dir->i_sb);
+		kfree(name);
 		goto out_failed;
 	}
 
 	retval =
 	    reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname),
 			       dentry, inode);
-	reiserfs_kfree(name, item_len, parent_dir->i_sb);
+	kfree(name);
 	if (retval) {		/* reiserfs_new_inode iputs for us */
 		goto out_failed;
 	}
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index fc2f43c..ef6caed 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -88,7 +88,6 @@
 	seq_printf(m, "state: \t%s\n"
 		   "mount options: \t%s%s%s%s%s%s%s%s%s%s%s\n"
 		   "gen. counter: \t%i\n"
-		   "s_kmallocs: \t%i\n"
 		   "s_disk_reads: \t%i\n"
 		   "s_disk_writes: \t%i\n"
 		   "s_fix_nodes: \t%i\n"
@@ -128,7 +127,7 @@
 		   "SMALL_TAILS " : "NO_TAILS ",
 		   replay_only(sb) ? "REPLAY_ONLY " : "",
 		   convert_reiserfs(sb) ? "CONV " : "",
-		   atomic_read(&r->s_generation_counter), SF(s_kmallocs),
+		   atomic_read(&r->s_generation_counter),
 		   SF(s_disk_reads), SF(s_disk_writes), SF(s_fix_nodes),
 		   SF(s_do_balance), SF(s_unneeded_left_neighbor),
 		   SF(s_good_search_by_key_reada), SF(s_bmaps),
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 397d959..d63da75 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -472,12 +472,6 @@
 
 	print_statistics(s);
 
-	if (REISERFS_SB(s)->s_kmallocs != 0) {
-		reiserfs_warning(s,
-				 "vs-2004: reiserfs_put_super: allocated memory left %d",
-				 REISERFS_SB(s)->s_kmallocs);
-	}
-
 	if (REISERFS_SB(s)->reserved_blocks != 0) {
 		reiserfs_warning(s,
 				 "green-2005: reiserfs_put_super: reserved blocks left %d",
@@ -1130,8 +1124,6 @@
 					 "reiserfs: cannot support attributes until flag is set in super-block");
 			REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS);
 		}
-	} else if (le32_to_cpu(rs->s_flags) & reiserfs_attrs_cleared) {
-		REISERFS_SB(s)->s_mount_opt |= REISERFS_ATTRS;
 	}
 }
 
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index cc061bf..ffb79c4 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -368,15 +368,13 @@
 		if (d_reclen <= 32) {
 			local_buf = small_buf;
 		} else {
-			local_buf =
-			    reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb);
+			local_buf = kmalloc(d_reclen, GFP_NOFS);
 			if (!local_buf) {
 				pathrelse(&path_to_entry);
 				return -ENOMEM;
 			}
 			if (item_moved(&tmp_ih, &path_to_entry)) {
-				reiserfs_kfree(local_buf, d_reclen,
-					       inode->i_sb);
+				kfree(local_buf);
 
 				/* sigh, must retry.  Do this same offset again */
 				next_pos = d_off;
@@ -399,13 +397,12 @@
 		if (filldir(dirent, local_buf, d_reclen, d_off, d_ino,
 			    DT_UNKNOWN) < 0) {
 			if (local_buf != small_buf) {
-				reiserfs_kfree(local_buf, d_reclen,
-					       inode->i_sb);
+				kfree(local_buf);
 			}
 			goto end;
 		}
 		if (local_buf != small_buf) {
-			reiserfs_kfree(local_buf, d_reclen, inode->i_sb);
+			kfree(local_buf);
 		}
 	}			/* while */
 
@@ -1322,109 +1319,44 @@
 	return err;
 }
 
-static int
-__reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd,
-		      int need_lock)
+static int reiserfs_check_acl(struct inode *inode, int mask)
 {
-	umode_t mode = inode->i_mode;
+	struct posix_acl *acl;
+	int error = -EAGAIN; /* do regular unix permission checks by default */
 
-	if (mask & MAY_WRITE) {
-		/*
-		 * Nobody gets write access to a read-only fs.
-		 */
-		if (IS_RDONLY(inode) &&
-		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-			return -EROFS;
+	reiserfs_read_lock_xattr_i(inode);
+	reiserfs_read_lock_xattrs(inode->i_sb);
 
-		/*
-		 * Nobody gets write access to an immutable file.
-		 */
-		if (IS_IMMUTABLE(inode))
-			return -EACCES;
-	}
+	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
 
-	/* We don't do permission checks on the internal objects.
-	 * Permissions are determined by the "owning" object. */
-	if (is_reiserfs_priv_object(inode))
-		return 0;
+	reiserfs_read_unlock_xattrs(inode->i_sb);
+	reiserfs_read_unlock_xattr_i(inode);
 
-	if (current->fsuid == inode->i_uid) {
-		mode >>= 6;
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
-	} else if (reiserfs_posixacl(inode->i_sb) &&
-		   get_inode_sd_version(inode) != STAT_DATA_V1) {
-		struct posix_acl *acl;
-
-		/* ACL can't contain additional permissions if
-		   the ACL_MASK entry is 0 */
-		if (!(mode & S_IRWXG))
-			goto check_groups;
-
-		if (need_lock) {
-			reiserfs_read_lock_xattr_i(inode);
-			reiserfs_read_lock_xattrs(inode->i_sb);
-		}
-		acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
-		if (need_lock) {
-			reiserfs_read_unlock_xattrs(inode->i_sb);
-			reiserfs_read_unlock_xattr_i(inode);
-		}
-		if (IS_ERR(acl)) {
-			if (PTR_ERR(acl) == -ENODATA)
-				goto check_groups;
-			return PTR_ERR(acl);
-		}
-
-		if (acl) {
-			int err = posix_acl_permission(inode, acl, mask);
+	if (acl) {
+		if (!IS_ERR(acl)) {
+			error = posix_acl_permission(inode, acl, mask);
 			posix_acl_release(acl);
-			if (err == -EACCES) {
-				goto check_capabilities;
-			}
-			return err;
-		} else {
-			goto check_groups;
-		}
-#endif
-	} else {
-	      check_groups:
-		if (in_group_p(inode->i_gid))
-			mode >>= 3;
+		} else if (PTR_ERR(acl) != -ENODATA)
+			error = PTR_ERR(acl);
 	}
 
-	/*
-	 * If the DACs are ok we don't need any capability check.
-	 */
-	if (((mode & mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == mask))
-		return 0;
-
-      check_capabilities:
-	/*
-	 * Read/write DACs are always overridable.
-	 * Executable DACs are overridable if at least one exec bit is set.
-	 */
-	if (!(mask & MAY_EXEC) ||
-	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
-		if (capable(CAP_DAC_OVERRIDE))
-			return 0;
-
-	/*
-	 * Searching includes executable on directories, else just read.
-	 */
-	if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
-		if (capable(CAP_DAC_READ_SEARCH))
-			return 0;
-
-	return -EACCES;
+	return error;
 }
 
 int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
-	return __reiserfs_permission(inode, mask, nd, 1);
-}
+	/*
+	 * We don't do permission checks on the internal objects.
+	 * Permissions are determined by the "owning" object.
+	 */
+	if (is_reiserfs_priv_object(inode))
+		return 0;
 
-int
-reiserfs_permission_locked(struct inode *inode, int mask, struct nameidata *nd)
-{
-	return __reiserfs_permission(inode, mask, nd, 0);
+	/*
+	 * Stat data v1 doesn't support ACLs.
+	 */
+	if (get_inode_sd_version(inode) == STAT_DATA_V1)
+		return generic_permission(inode, mask, NULL);
+	else
+		return generic_permission(inode, mask, reiserfs_check_acl);
 }
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 43de3ba..ab8894c 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -228,7 +228,8 @@
 		acl = ERR_PTR(retval);
 	} else {
 		acl = posix_acl_from_disk(value, retval);
-		*p_acl = posix_acl_dup(acl);
+		if (!IS_ERR(acl))
+			*p_acl = posix_acl_dup(acl);
 	}
 
 	kfree(value);
diff --git a/fs/select.c b/fs/select.c
index f10a103..6ce68a9 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -179,12 +179,11 @@
 #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
 #define POLLEX_SET (POLLPRI)
 
-int do_select(int n, fd_set_bits *fds, long *timeout)
+int do_select(int n, fd_set_bits *fds, s64 *timeout)
 {
 	struct poll_wqueues table;
 	poll_table *wait;
 	int retval, i;
-	long __timeout = *timeout;
 
 	rcu_read_lock();
 	retval = max_select_fd(n, fds);
@@ -196,11 +195,12 @@
 
 	poll_initwait(&table);
 	wait = &table.pt;
-	if (!__timeout)
+	if (!*timeout)
 		wait = NULL;
 	retval = 0;
 	for (;;) {
 		unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
+		long __timeout;
 
 		set_current_state(TASK_INTERRUPTIBLE);
 
@@ -255,22 +255,32 @@
 				*rexp = res_ex;
 		}
 		wait = NULL;
-		if (retval || !__timeout || signal_pending(current))
+		if (retval || !*timeout || signal_pending(current))
 			break;
 		if(table.error) {
 			retval = table.error;
 			break;
 		}
+
+		if (*timeout < 0) {
+			/* Wait indefinitely */
+			__timeout = MAX_SCHEDULE_TIMEOUT;
+		} else if (unlikely(*timeout >= (s64)MAX_SCHEDULE_TIMEOUT - 1)) {
+			/* Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in a loop */
+			__timeout = MAX_SCHEDULE_TIMEOUT - 1;
+			*timeout -= __timeout;
+		} else {
+			__timeout = *timeout;
+			*timeout = 0;
+		}
 		__timeout = schedule_timeout(__timeout);
+		if (*timeout >= 0)
+			*timeout += __timeout;
 	}
 	__set_current_state(TASK_RUNNING);
 
 	poll_freewait(&table);
 
-	/*
-	 * Up-to-date the caller timeout.
-	 */
-	*timeout = __timeout;
 	return retval;
 }
 
@@ -295,36 +305,14 @@
 #define MAX_SELECT_SECONDS \
 	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
 
-asmlinkage long
-sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
+static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+			   fd_set __user *exp, s64 *timeout)
 {
 	fd_set_bits fds;
 	char *bits;
-	long timeout;
 	int ret, size, max_fdset;
 	struct fdtable *fdt;
 
-	timeout = MAX_SCHEDULE_TIMEOUT;
-	if (tvp) {
-		time_t sec, usec;
-
-		if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
-		    || __get_user(sec, &tvp->tv_sec)
-		    || __get_user(usec, &tvp->tv_usec)) {
-			ret = -EFAULT;
-			goto out_nofds;
-		}
-
-		ret = -EINVAL;
-		if (sec < 0 || usec < 0)
-			goto out_nofds;
-
-		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
-			timeout = ROUND_UP(usec, 1000000/HZ);
-			timeout += sec * (unsigned long) HZ;
-		}
-	}
-
 	ret = -EINVAL;
 	if (n < 0)
 		goto out_nofds;
@@ -362,18 +350,7 @@
 	zero_fd_set(n, fds.res_out);
 	zero_fd_set(n, fds.res_ex);
 
-	ret = do_select(n, &fds, &timeout);
-
-	if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
-		time_t sec = 0, usec = 0;
-		if (timeout) {
-			sec = timeout / HZ;
-			usec = timeout % HZ;
-			usec *= (1000000/HZ);
-		}
-		put_user(sec, &tvp->tv_sec);
-		put_user(usec, &tvp->tv_usec);
-	}
+	ret = do_select(n, &fds, timeout);
 
 	if (ret < 0)
 		goto out;
@@ -395,6 +372,163 @@
 	return ret;
 }
 
+asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+			fd_set __user *exp, struct timeval __user *tvp)
+{
+	s64 timeout = -1;
+	struct timeval tv;
+	int ret;
+
+	if (tvp) {
+		if (copy_from_user(&tv, tvp, sizeof(tv)))
+			return -EFAULT;
+
+		if (tv.tv_sec < 0 || tv.tv_usec < 0)
+			return -EINVAL;
+
+		/* Cast to u64 to make GCC stop complaining */
+		if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
+			timeout = -1;	/* infinite */
+		else {
+			timeout = ROUND_UP(tv.tv_usec, USEC_PER_SEC/HZ);
+			timeout += tv.tv_sec * HZ;
+		}
+	}
+
+	ret = core_sys_select(n, inp, outp, exp, &timeout);
+
+	if (tvp) {
+		struct timeval rtv;
+
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
+		rtv.tv_sec = timeout;
+		if (timeval_compare(&rtv, &tv) < 0)
+			rtv = tv;
+		if (copy_to_user(tvp, &rtv, sizeof(rtv))) {
+sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND)
+				ret = -EINTR;
+		}
+	}
+
+	return ret;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
+		fd_set __user *exp, struct timespec __user *tsp,
+		const sigset_t __user *sigmask, size_t sigsetsize)
+{
+	s64 timeout = MAX_SCHEDULE_TIMEOUT;
+	sigset_t ksigmask, sigsaved;
+	struct timespec ts;
+	int ret;
+
+	if (tsp) {
+		if (copy_from_user(&ts, tsp, sizeof(ts)))
+			return -EFAULT;
+
+		if (ts.tv_sec < 0 || ts.tv_nsec < 0)
+			return -EINVAL;
+
+		/* Cast to u64 to make GCC stop complaining */
+		if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS)
+			timeout = -1;	/* infinite */
+		else {
+			timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
+			timeout += ts.tv_sec * HZ;
+		}
+	}
+
+	if (sigmask) {
+		/* XXX: Don't preclude handling different sized sigset_t's.  */
+		if (sigsetsize != sizeof(sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+			return -EFAULT;
+
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	ret = core_sys_select(n, inp, outp, exp, &timeout);
+
+	if (tsp) {
+		struct timespec rts;
+
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) *
+						1000;
+		rts.tv_sec = timeout;
+		if (timespec_compare(&rts, &ts) < 0)
+			rts = ts;
+		if (copy_to_user(tsp, &rts, sizeof(rts))) {
+sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND)
+				ret = -EINTR;
+		}
+	}
+
+	if (ret == -ERESTARTNOHAND) {
+		/*
+		 * Don't restore the signal mask yet. Let do_signal() deliver
+		 * the signal on the way back to userspace, before the signal
+		 * mask is restored.
+		 */
+		if (sigmask) {
+			memcpy(&current->saved_sigmask, &sigsaved,
+					sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+	} else if (sigmask)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	return ret;
+}
+
+/*
+ * Most architectures can't handle 7-argument syscalls. So we provide a
+ * 6-argument version where the sixth argument is a pointer to a structure
+ * which has a pointer to the sigset_t itself followed by a size_t containing
+ * the sigset size.
+ */
+asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp,
+	fd_set __user *exp, struct timespec __user *tsp, void __user *sig)
+{
+	size_t sigsetsize = 0;
+	sigset_t __user *up = NULL;
+
+	if (sig) {
+		if (!access_ok(VERIFY_READ, sig, sizeof(void *)+sizeof(size_t))
+		    || __get_user(up, (sigset_t __user * __user *)sig)
+		    || __get_user(sigsetsize,
+				(size_t __user *)(sig+sizeof(void *))))
+			return -EFAULT;
+	}
+
+	return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize);
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
 struct poll_list {
 	struct poll_list *next;
 	int len;
@@ -436,16 +570,19 @@
 }
 
 static int do_poll(unsigned int nfds,  struct poll_list *list,
-			struct poll_wqueues *wait, long timeout)
+		   struct poll_wqueues *wait, s64 *timeout)
 {
 	int count = 0;
 	poll_table* pt = &wait->pt;
 
-	if (!timeout)
+	/* Optimise the no-wait case */
+	if (!(*timeout))
 		pt = NULL;
  
 	for (;;) {
 		struct poll_list *walk;
+		long __timeout;
+
 		set_current_state(TASK_INTERRUPTIBLE);
 		walk = list;
 		while(walk != NULL) {
@@ -453,18 +590,36 @@
 			walk = walk->next;
 		}
 		pt = NULL;
-		if (count || !timeout || signal_pending(current))
+		if (count || !*timeout || signal_pending(current))
 			break;
 		count = wait->error;
 		if (count)
 			break;
-		timeout = schedule_timeout(timeout);
+
+		if (*timeout < 0) {
+			/* Wait indefinitely */
+			__timeout = MAX_SCHEDULE_TIMEOUT;
+		} else if (unlikely(*timeout >= (s64)MAX_SCHEDULE_TIMEOUT-1)) {
+			/*
+			 * Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in
+			 * a loop
+			 */
+			__timeout = MAX_SCHEDULE_TIMEOUT - 1;
+			*timeout -= __timeout;
+		} else {
+			__timeout = *timeout;
+			*timeout = 0;
+		}
+
+		__timeout = schedule_timeout(__timeout);
+		if (*timeout >= 0)
+			*timeout += __timeout;
 	}
 	__set_current_state(TASK_RUNNING);
 	return count;
 }
 
-asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout)
+int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
 {
 	struct poll_wqueues table;
  	int fdcount, err;
@@ -482,14 +637,6 @@
 	if (nfds > max_fdset && nfds > OPEN_MAX)
 		return -EINVAL;
 
-	if (timeout) {
-		/* Careful about overflow in the intermediate values */
-		if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)
-			timeout = (unsigned long)(timeout*HZ+999)/1000+1;
-		else /* Negative or overflow */
-			timeout = MAX_SCHEDULE_TIMEOUT;
-	}
-
 	poll_initwait(&table);
 
 	head = NULL;
@@ -519,6 +666,7 @@
 		}
 		i -= pp->len;
 	}
+
 	fdcount = do_poll(nfds, head, &table, timeout);
 
 	/* OK, now copy the revents fields back to user space. */
@@ -547,3 +695,103 @@
 	poll_freewait(&table);
 	return err;
 }
+
+asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
+			long timeout_msecs)
+{
+	s64 timeout_jiffies = 0;
+
+	if (timeout_msecs) {
+#if HZ > 1000
+		/* We can only overflow if HZ > 1000 */
+		if (timeout_msecs / 1000 > (s64)0x7fffffffffffffffULL / (s64)HZ)
+			timeout_jiffies = -1;
+		else
+#endif
+			timeout_jiffies = msecs_to_jiffies(timeout_msecs);
+	}
+
+	return do_sys_poll(ufds, nfds, &timeout_jiffies);
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
+	struct timespec __user *tsp, const sigset_t __user *sigmask,
+	size_t sigsetsize)
+{
+	sigset_t ksigmask, sigsaved;
+	struct timespec ts;
+	s64 timeout = -1;
+	int ret;
+
+	if (tsp) {
+		if (copy_from_user(&ts, tsp, sizeof(ts)))
+			return -EFAULT;
+
+		/* Cast to u64 to make GCC stop complaining */
+		if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS)
+			timeout = -1;	/* infinite */
+		else {
+			timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
+			timeout += ts.tv_sec * HZ;
+		}
+	}
+
+	if (sigmask) {
+		/* XXX: Don't preclude handling different sized sigset_t's.  */
+		if (sigsetsize != sizeof(sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+			return -EFAULT;
+
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	ret = do_sys_poll(ufds, nfds, &timeout);
+
+	/* We can restart this syscall, usually */
+	if (ret == -EINTR) {
+		/*
+		 * Don't restore the signal mask yet. Let do_signal() deliver
+		 * the signal on the way back to userspace, before the signal
+		 * mask is restored.
+		 */
+		if (sigmask) {
+			memcpy(&current->saved_sigmask, &sigsaved,
+					sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+		ret = -ERESTARTNOHAND;
+	} else if (sigmask)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	if (tsp && timeout >= 0) {
+		struct timespec rts;
+
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		/* Yes, we know it's actually an s64, but it's also positive. */
+		rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) *
+						1000;
+		rts.tv_sec = timeout;
+		if (timespec_compare(&rts, &ts) < 0)
+			rts = ts;
+		if (copy_to_user(tsp, &rts, sizeof(rts))) {
+		sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND && timeout >= 0)
+				ret = -EINTR;
+		}
+	}
+
+	return ret;
+}
+#endif /* TIF_RESTORE_SIGMASK */
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index c6c33e1..0424d06 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -209,6 +209,8 @@
 	ctl.valid  = 1;
 read_really:
 	result = server->ops->readdir(filp, dirent, filldir, &ctl);
+	if (result == -ERESTARTSYS && page)
+		ClearPageUptodate(page);
 	if (ctl.idx == -1)
 		goto invalid_cache;	/* retry */
 	ctl.head.end = ctl.fpos - 1;
@@ -217,7 +219,8 @@
 	if (page) {
 		cache->head = ctl.head;
 		kunmap(page);
-		SetPageUptodate(page);
+		if (result != -ERESTARTSYS)
+			SetPageUptodate(page);
 		unlock_page(page);
 		page_cache_release(page);
 	}
diff --git a/fs/stat.c b/fs/stat.c
index b8a0e51..9948cc1 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -63,12 +63,12 @@
 
 EXPORT_SYMBOL(vfs_getattr);
 
-int vfs_stat(char __user *name, struct kstat *stat)
+int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
 {
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk(name, &nd);
+	error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
 	if (!error) {
 		error = vfs_getattr(nd.mnt, nd.dentry, stat);
 		path_release(&nd);
@@ -76,14 +76,19 @@
 	return error;
 }
 
+int vfs_stat(char __user *name, struct kstat *stat)
+{
+	return vfs_stat_fd(AT_FDCWD, name, stat);
+}
+
 EXPORT_SYMBOL(vfs_stat);
 
-int vfs_lstat(char __user *name, struct kstat *stat)
+int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
 {
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk_link(name, &nd);
+	error = __user_walk_fd(dfd, name, 0, &nd);
 	if (!error) {
 		error = vfs_getattr(nd.mnt, nd.dentry, stat);
 		path_release(&nd);
@@ -91,6 +96,11 @@
 	return error;
 }
 
+int vfs_lstat(char __user *name, struct kstat *stat)
+{
+	return vfs_lstat_fd(AT_FDCWD, name, stat);
+}
+
 EXPORT_SYMBOL(vfs_lstat);
 
 int vfs_fstat(unsigned int fd, struct kstat *stat)
@@ -151,7 +161,7 @@
 asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf)
 {
 	struct kstat stat;
-	int error = vfs_stat(filename, &stat);
+	int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
 
 	if (!error)
 		error = cp_old_stat(&stat, statbuf);
@@ -161,7 +171,7 @@
 asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf)
 {
 	struct kstat stat;
-	int error = vfs_lstat(filename, &stat);
+	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
 
 	if (!error)
 		error = cp_old_stat(&stat, statbuf);
@@ -229,27 +239,52 @@
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-asmlinkage long sys_newstat(char __user * filename, struct stat __user * statbuf)
+asmlinkage long sys_newstat(char __user *filename, struct stat __user *statbuf)
 {
 	struct kstat stat;
-	int error = vfs_stat(filename, &stat);
+	int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
 
 	if (!error)
 		error = cp_new_stat(&stat, statbuf);
 
 	return error;
 }
-asmlinkage long sys_newlstat(char __user * filename, struct stat __user * statbuf)
+
+asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
 {
 	struct kstat stat;
-	int error = vfs_lstat(filename, &stat);
+	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
 
 	if (!error)
 		error = cp_new_stat(&stat, statbuf);
 
 	return error;
 }
-asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf)
+
+#ifndef __ARCH_WANT_STAT64
+asmlinkage long sys_newfstatat(int dfd, char __user *filename,
+				struct stat __user *statbuf, int flag)
+{
+	struct kstat stat;
+	int error = -EINVAL;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat_fd(dfd, filename, &stat);
+	else
+		error = vfs_stat_fd(dfd, filename, &stat);
+
+	if (!error)
+		error = cp_new_stat(&stat, statbuf);
+
+out:
+	return error;
+}
+#endif
+
+asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
 {
 	struct kstat stat;
 	int error = vfs_fstat(fd, &stat);
@@ -260,7 +295,8 @@
 	return error;
 }
 
-asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bufsiz)
+asmlinkage long sys_readlinkat(int dfd, const char __user *path,
+				char __user *buf, int bufsiz)
 {
 	struct nameidata nd;
 	int error;
@@ -268,7 +304,7 @@
 	if (bufsiz <= 0)
 		return -EINVAL;
 
-	error = user_path_walk_link(path, &nd);
+	error = __user_walk_fd(dfd, path, 0, &nd);
 	if (!error) {
 		struct inode * inode = nd.dentry->d_inode;
 
@@ -285,6 +321,12 @@
 	return error;
 }
 
+asmlinkage long sys_readlink(const char __user *path, char __user *buf,
+				int bufsiz)
+{
+	return sys_readlinkat(AT_FDCWD, path, buf, bufsiz);
+}
+
 
 /* ---------- LFS-64 ----------- */
 #ifdef __ARCH_WANT_STAT64
@@ -355,6 +397,26 @@
 	return error;
 }
 
+asmlinkage long sys_fstatat64(int dfd, char __user *filename,
+			       struct stat64 __user *statbuf, int flag)
+{
+	struct kstat stat;
+	int error = -EINVAL;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat_fd(dfd, filename, &stat);
+	else
+		error = vfs_stat_fd(dfd, filename, &stat);
+
+	if (!error)
+		error = cp_new_stat64(&stat, statbuf);
+
+out:
+	return error;
+}
 #endif /* __ARCH_WANT_STAT64 */
 
 void inode_add_bytes(struct inode *inode, loff_t bytes)
diff --git a/fs/super.c b/fs/super.c
index c177b92..3029421 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -247,8 +247,9 @@
 
 		/* Forget any remaining inodes */
 		if (invalidate_inodes(sb)) {
-			printk("VFS: Busy inodes after unmount. "
-			   "Self-destruct in 5 seconds.  Have a nice day...\n");
+			printk("VFS: Busy inodes after unmount of %s. "
+			   "Self-destruct in 5 seconds.  Have a nice day...\n",
+			   sb->s_id);
 		}
 
 		unlock_kernel();
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 4fae57d..201049a 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -579,10 +579,9 @@
 			{
 				loffset = nextoffset;
 				aed->lengthAllocDescs = cpu_to_le32(adsize);
-				if (obh)
-					sptr = UDF_I_DATA(inode) + nextoffset -  udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode) - adsize;
-				else
-					sptr = obh->b_data + nextoffset - adsize;
+				sptr = UDF_I_DATA(inode) + nextoffset -
+					udf_file_entry_alloc_offset(inode) +
+					UDF_I_LENEATTR(inode) - adsize;
 				dptr = nbh->b_data + sizeof(struct allocExtDesc);
 				memcpy(dptr, sptr, adsize);
 				nextoffset = sizeof(struct allocExtDesc) + adsize;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index ca732e7..ab9a762 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -296,7 +296,7 @@
 udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = NULL;
-	struct fileIdentDesc cfi, *fi;
+	struct fileIdentDesc cfi;
 	struct udf_fileident_bh fibh;
 
 	if (dentry->d_name.len > UDF_NAME_LEN-2)
@@ -318,7 +318,7 @@
 	else
 #endif /* UDF_RECOVERY */
 
-	if ((fi = udf_find_entry(dir, dentry, &fibh, &cfi)))
+	if (udf_find_entry(dir, dentry, &fibh, &cfi))
 	{
 		if (fibh.sbh != fibh.ebh)
 			udf_release_data(fibh.ebh);
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index e0c04e3..3c3f62c 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -376,7 +376,7 @@
  * This function gets the block which contains the fragment.
  */
 
-static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
+int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
 {
 	struct super_block * sb = inode->i_sb;
 	struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi;
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index d4aacee..e9055ef 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -388,7 +388,8 @@
 /*
  * Read on-disk structures associated with cylinder groups
  */
-static int ufs_read_cylinder_structures (struct super_block *sb) {
+static int ufs_read_cylinder_structures (struct super_block *sb)
+{
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block *usb;
@@ -415,6 +416,7 @@
 	base = space = kmalloc(size, GFP_KERNEL);
 	if (!base)
 		goto failed; 
+	sbi->s_csp = (struct ufs_csum *)space;
 	for (i = 0; i < blks; i += uspi->s_fpb) {
 		size = uspi->s_bsize;
 		if (i + uspi->s_fpb > blks)
@@ -430,7 +432,6 @@
 			goto failed;
 
 		ubh_ubhcpymem (space, ubh, size);
-		sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
 
 		space += size;
 		ubh_brelse (ubh);
@@ -486,7 +487,8 @@
  * Put on-disk structures associated with cylinder groups and 
  * write them back to disk
  */
-static void ufs_put_cylinder_structures (struct super_block *sb) {
+static void ufs_put_cylinder_structures (struct super_block *sb)
+{
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * ubh;
@@ -499,7 +501,7 @@
 
 	size = uspi->s_cssize;
 	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
-	base = space = (char*) sbi->s_csp[0];
+	base = space = (char*) sbi->s_csp;
 	for (i = 0; i < blks; i += uspi->s_fpb) {
 		size = uspi->s_bsize;
 		if (i + uspi->s_fpb > blks)
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index 61d2e35..02e8629 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -29,6 +29,11 @@
  * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr>
  */
 
+/*
+ * Modified to avoid infinite loop on 2006 by
+ * Evgeniy Dushistov <dushistov@mail.ru>
+ */
+
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
@@ -65,19 +70,16 @@
 #define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift)
 #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
 
-#define DATA_BUFFER_USED(bh) \
-	(atomic_read(&bh->b_count)>1 || buffer_locked(bh))
 
 static int ufs_trunc_direct (struct inode * inode)
 {
 	struct ufs_inode_info *ufsi = UFS_I(inode);
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct buffer_head * bh;
 	__fs32 * p;
 	unsigned frag1, frag2, frag3, frag4, block1, block2;
 	unsigned frag_to_free, free_count;
-	unsigned i, j, tmp;
+	unsigned i, tmp;
 	int retry;
 	
 	UFSD(("ENTER\n"))
@@ -117,15 +119,7 @@
 		ufs_panic (sb, "ufs_trunc_direct", "internal error");
 	frag1 = ufs_fragnum (frag1);
 	frag2 = ufs_fragnum (frag2);
-	for (j = frag1; j < frag2; j++) {
-		bh = sb_find_get_block (sb, tmp + j);
-		if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) {
-			retry = 1;
-			brelse (bh);
-			goto next1;
-		}
-		bforget (bh);
-	}
+
 	inode->i_blocks -= (frag2-frag1) << uspi->s_nspfshift;
 	mark_inode_dirty(inode);
 	ufs_free_fragments (inode, tmp + frag1, frag2 - frag1);
@@ -140,15 +134,7 @@
 		tmp = fs32_to_cpu(sb, *p);
 		if (!tmp)
 			continue;
-		for (j = 0; j < uspi->s_fpb; j++) {
-			bh = sb_find_get_block(sb, tmp + j);
-			if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) {
-				retry = 1;
-				brelse (bh);
-				goto next2;
-			}
-			bforget (bh);
-		}
+
 		*p = 0;
 		inode->i_blocks -= uspi->s_nspb;
 		mark_inode_dirty(inode);
@@ -162,7 +148,6 @@
 			frag_to_free = tmp;
 			free_count = uspi->s_fpb;
 		}
-next2:;
 	}
 	
 	if (free_count > 0)
@@ -179,15 +164,7 @@
 	if (!tmp )
 		ufs_panic(sb, "ufs_truncate_direct", "internal error");
 	frag4 = ufs_fragnum (frag4);
-	for (j = 0; j < frag4; j++) {
-		bh = sb_find_get_block (sb, tmp + j);
-		if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) {
-			retry = 1;
-			brelse (bh);
-			goto next1;
-		}
-		bforget (bh);
-	}
+
 	*p = 0;
 	inode->i_blocks -= frag4 << uspi->s_nspfshift;
 	mark_inode_dirty(inode);
@@ -204,9 +181,8 @@
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * ind_ubh;
-	struct buffer_head * bh;
 	__fs32 * ind;
-	unsigned indirect_block, i, j, tmp;
+	unsigned indirect_block, i, tmp;
 	unsigned frag_to_free, free_count;
 	int retry;
 
@@ -238,15 +214,7 @@
 		tmp = fs32_to_cpu(sb, *ind);
 		if (!tmp)
 			continue;
-		for (j = 0; j < uspi->s_fpb; j++) {
-			bh = sb_find_get_block(sb, tmp + j);
-			if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *ind)) {
-				retry = 1;
-				brelse (bh);
-				goto next;
-			}
-			bforget (bh);
-		}	
+
 		*ind = 0;
 		ubh_mark_buffer_dirty(ind_ubh);
 		if (free_count == 0) {
@@ -261,7 +229,6 @@
 		}
 		inode->i_blocks -= uspi->s_nspb;
 		mark_inode_dirty(inode);
-next:;
 	}
 
 	if (free_count > 0) {
@@ -430,9 +397,7 @@
 	struct ufs_inode_info *ufsi = UFS_I(inode);
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct buffer_head * bh;
-	unsigned offset;
-	int err, retry;
+	int retry;
 	
 	UFSD(("ENTER\n"))
 	sb = inode->i_sb;
@@ -442,6 +407,9 @@
 		return;
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		return;
+
+	block_truncate_page(inode->i_mapping,	inode->i_size, ufs_getfrag_block);
+
 	lock_kernel();
 	while (1) {
 		retry = ufs_trunc_direct(inode);
@@ -457,15 +425,7 @@
 		blk_run_address_space(inode->i_mapping);
 		yield();
 	}
-	offset = inode->i_size & uspi->s_fshift;
-	if (offset) {
-		bh = ufs_bread (inode, inode->i_size >> uspi->s_fshift, 0, &err);
-		if (bh) {
-			memset (bh->b_data + offset, 0, uspi->s_fsize - offset);
-			mark_buffer_dirty (bh);
-			brelse (bh);
-		}
-	}
+
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
 	ufsi->i_lastfrag = DIRECT_FRAGMENT;
 	unlock_kernel();
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 1206267..8f2beec 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -747,10 +747,11 @@
 			struct backing_dev_info *bdi;
 
 			bdi = inode->i_mapping->backing_dev_info;
+			wbc->nr_to_write--;
 			if (bdi_write_congested(bdi)) {
 				wbc->encountered_congestion = 1;
 				done = 1;
-			} else if (--wbc->nr_to_write <= 0) {
+			} else if (wbc->nr_to_write <= 0) {
 				done = 1;
 			}
 		}
@@ -1462,4 +1463,5 @@
 	.commit_write		= generic_commit_write,
 	.bmap			= linvfs_bmap,
 	.direct_IO		= linvfs_direct_IO,
+	.migratepage		= buffer_migrate_page,
 };
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index e44b7c1..bfb4f29 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -822,6 +822,13 @@
 
 	XB_TRACE(bp, "rele", bp->b_relse);
 
+	if (unlikely(!hash)) {
+		ASSERT(!bp->b_relse);
+		if (atomic_dec_and_test(&bp->b_hold))
+			xfs_buf_free(bp);
+		return;
+	}
+
 	if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) {
 		if (bp->b_relse) {
 			atomic_inc(&bp->b_hold);
@@ -1514,6 +1521,7 @@
 	struct address_space	*mapping;
 	static struct address_space_operations mapping_aops = {
 		.sync_page = block_sync_page,
+		.migratepage = fail_migrate_page,
 	};
 
 	inode = new_inode(bdev->bd_inode->i_sb);
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 76c6df3..d7f6f2d 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -262,6 +262,31 @@
 	return (task->fs != init_task.fs);
 }
 
+STATIC inline void
+cleanup_inode(
+	vnode_t		*dvp,
+	vnode_t		*vp,
+	struct dentry	*dentry,	
+	int		mode)
+{
+	struct dentry   teardown = {};
+	int             err2;
+
+	/* Oh, the horror.
+	 * If we can't add the ACL or we fail in 
+	 * linvfs_init_security we must back out.
+	 * ENOSPC can hit here, among other things.
+	 */
+	teardown.d_inode = LINVFS_GET_IP(vp);
+	teardown.d_name = dentry->d_name;
+
+	if (S_ISDIR(mode))
+	  	VOP_RMDIR(dvp, &teardown, NULL, err2);
+	else
+		VOP_REMOVE(dvp, &teardown, NULL, err2);
+	VN_RELE(vp);
+}
+
 STATIC int
 linvfs_mknod(
 	struct inode	*dir,
@@ -316,30 +341,19 @@
 	}
 
 	if (!error)
+	{
 		error = linvfs_init_security(vp, dir);
+		if (error)
+			cleanup_inode(dvp, vp, dentry, mode);
+	}
 
 	if (default_acl) {
 		if (!error) {
 			error = _ACL_INHERIT(vp, &va, default_acl);
-			if (!error) {
+			if (!error) 
 				VMODIFY(vp);
-			} else {
-				struct dentry	teardown = {};
-				int		err2;
-
-				/* Oh, the horror.
-				 * If we can't add the ACL we must back out.
-				 * ENOSPC can hit here, among other things.
-				 */
-				teardown.d_inode = ip = LINVFS_GET_IP(vp);
-				teardown.d_name = dentry->d_name;
-
-				if (S_ISDIR(mode))
-					VOP_RMDIR(dvp, &teardown, NULL, err2);
-				else
-					VOP_REMOVE(dvp, &teardown, NULL, err2);
-				VN_RELE(vp);
-			}
+			else
+				cleanup_inode(dvp, vp, dentry, mode);
 		}
 		_ACL_FREE(default_acl);
 	}
@@ -659,6 +673,8 @@
 	if (ia_valid & ATTR_ATIME) {
 		vattr.va_mask |= XFS_AT_ATIME;
 		vattr.va_atime = attr->ia_atime;
+		if (ia_valid & ATTR_ATIME_SET)
+			inode->i_atime = attr->ia_atime;
 	}
 	if (ia_valid & ATTR_MTIME) {
 		vattr.va_mask |= XFS_AT_MTIME;
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 427cff1..e27dc8f 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -61,9 +61,9 @@
  *
  */
 
-/* Version string */
+/* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20050902
+#define ACPI_CA_VERSION                 0x20060127
 
 /*
  * OS name, used for the _OS object.  The _OS object is essentially obsolete,
@@ -83,7 +83,7 @@
 #define ACPI_MAX_OBJECT_CACHE_DEPTH     96	/* Interpreter operand objects */
 
 /*
- * Should the subystem abort the loading of an ACPI table if the
+ * Should the subsystem abort the loading of an ACPI table if the
  * table checksum is incorrect?
  */
 #define ACPI_CHECKSUM_ABORT             FALSE
@@ -98,11 +98,6 @@
 
 #define ACPI_CA_SUPPORT_LEVEL           3
 
-/* String size constants */
-
-#define ACPI_MAX_STRING_LENGTH          512
-#define ACPI_PATHNAME_MAX               256	/* A full namespace pathname */
-
 /* Maximum count for a semaphore object */
 
 #define ACPI_MAX_SEMAPHORE_COUNT        256
@@ -115,6 +110,10 @@
 
 #define ACPI_SYSMEM_REGION_WINDOW_SIZE  4096
 
+/* owner_id tracking. 8 entries allows for 255 owner_ids */
+
+#define ACPI_NUM_OWNERID_MASKS          8
+
 /******************************************************************************
  *
  * ACPI Specification constants (Do not change unless the specification changes)
@@ -134,14 +133,11 @@
 #define ACPI_METHOD_NUM_ARGS            7
 #define ACPI_METHOD_MAX_ARG             6
 
-/* Maximum length of resulting string when converting from a buffer */
-
-#define ACPI_MAX_STRING_CONVERSION      200
-
-/* Length of _HID, _UID, and _CID values */
+/* Length of _HID, _UID, _CID, and UUID values */
 
 #define ACPI_DEVICE_ID_LENGTH           0x09
 #define ACPI_MAX_CID_LENGTH             48
+#define ACPI_UUID_LENGTH                16
 
 /*
  * Operand Stack (in WALK_STATE), Must be large enough to contain METHOD_MAX_ARG
diff --git a/include/acpi/acdebug.h b/include/acpi/acdebug.h
index 70ce3b4..d816709 100644
--- a/include/acpi/acdebug.h
+++ b/include/acpi/acdebug.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
index 3d96dcb..11a8fe3 100644
--- a/include/acpi/acdisasm.h
+++ b/include/acpi/acdisasm.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -57,26 +57,11 @@
 };
 
 extern struct acpi_external_list *acpi_gbl_external_list;
-extern const char *acpi_gbl_io_decode[2];
-extern const char *acpi_gbl_word_decode[4];
-extern const char *acpi_gbl_consume_decode[2];
-extern const char *acpi_gbl_min_decode[2];
-extern const char *acpi_gbl_max_decode[2];
-extern const char *acpi_gbl_DECdecode[2];
-extern const char *acpi_gbl_RNGdecode[4];
-extern const char *acpi_gbl_MEMdecode[4];
-extern const char *acpi_gbl_RWdecode[2];
-extern const char *acpi_gbl_irq_decode[2];
-extern const char *acpi_gbl_HEdecode[2];
-extern const char *acpi_gbl_LLdecode[2];
-extern const char *acpi_gbl_SHRdecode[2];
-extern const char *acpi_gbl_TYPdecode[4];
-extern const char *acpi_gbl_BMdecode[2];
-extern const char *acpi_gbl_SIZdecode[4];
-extern const char *acpi_gbl_TTPdecode[2];
-extern const char *acpi_gbl_MTPdecode[4];
-extern const char *acpi_gbl_TRSdecode[2];
 
+/* Strings used for decoding flags to ASL keywords */
+
+extern const char *acpi_gbl_word_decode[4];
+extern const char *acpi_gbl_irq_decode[2];
 extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES];
 extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES];
 extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES];
@@ -171,11 +156,19 @@
 /*
  * dmresrc
  */
-void
-acpi_dm_resource_descriptor(struct acpi_op_walk_info *info,
-			    u8 * byte_data, u32 byte_count);
+void acpi_dm_dump_integer8(u8 value, char *name);
 
-u8 acpi_dm_is_resource_descriptor(union acpi_parse_object *op);
+void acpi_dm_dump_integer16(u16 value, char *name);
+
+void acpi_dm_dump_integer32(u32 value, char *name);
+
+void acpi_dm_dump_integer64(u64 value, char *name);
+
+void
+acpi_dm_resource_template(struct acpi_op_walk_info *info,
+			  u8 * byte_data, u32 byte_count);
+
+u8 acpi_dm_is_resource_template(union acpi_parse_object *op);
 
 void acpi_dm_indent(u32 level);
 
@@ -187,73 +180,69 @@
  * dmresrcl
  */
 void
-acpi_dm_word_descriptor(struct asl_word_address_desc *resource,
-			u32 length, u32 level);
+acpi_dm_word_descriptor(union aml_resource *resource, u32 length, u32 level);
 
 void
-acpi_dm_dword_descriptor(struct asl_dword_address_desc *resource,
-			 u32 length, u32 level);
+acpi_dm_dword_descriptor(union aml_resource *resource, u32 length, u32 level);
 
 void
-acpi_dm_extended_descriptor(struct asl_extended_address_desc *resource,
+acpi_dm_extended_descriptor(union aml_resource *resource,
 			    u32 length, u32 level);
 
 void
-acpi_dm_qword_descriptor(struct asl_qword_address_desc *resource,
-			 u32 length, u32 level);
+acpi_dm_qword_descriptor(union aml_resource *resource, u32 length, u32 level);
 
 void
-acpi_dm_memory24_descriptor(struct asl_memory_24_desc *resource,
+acpi_dm_memory24_descriptor(union aml_resource *resource,
 			    u32 length, u32 level);
 
 void
-acpi_dm_memory32_descriptor(struct asl_memory_32_desc *resource,
+acpi_dm_memory32_descriptor(union aml_resource *resource,
 			    u32 length, u32 level);
 
 void
-acpi_dm_fixed_mem32_descriptor(struct asl_fixed_memory_32_desc *resource,
-			       u32 length, u32 level);
+acpi_dm_fixed_memory32_descriptor(union aml_resource *resource,
+				  u32 length, u32 level);
 
 void
-acpi_dm_generic_register_descriptor(struct asl_general_register_desc *resource,
+acpi_dm_generic_register_descriptor(union aml_resource *resource,
 				    u32 length, u32 level);
 
 void
-acpi_dm_interrupt_descriptor(struct asl_extended_xrupt_desc *resource,
+acpi_dm_interrupt_descriptor(union aml_resource *resource,
 			     u32 length, u32 level);
 
 void
-acpi_dm_vendor_large_descriptor(struct asl_large_vendor_desc *resource,
+acpi_dm_vendor_large_descriptor(union aml_resource *resource,
 				u32 length, u32 level);
 
+void acpi_dm_vendor_common(char *name, u8 * byte_data, u32 length, u32 level);
+
 /*
  * dmresrcs
  */
 void
-acpi_dm_irq_descriptor(struct asl_irq_format_desc *resource,
-		       u32 length, u32 level);
+acpi_dm_irq_descriptor(union aml_resource *resource, u32 length, u32 level);
 
 void
-acpi_dm_dma_descriptor(struct asl_dma_format_desc *resource,
-		       u32 length, u32 level);
+acpi_dm_dma_descriptor(union aml_resource *resource, u32 length, u32 level);
+
+void acpi_dm_io_descriptor(union aml_resource *resource, u32 length, u32 level);
 
 void
-acpi_dm_io_descriptor(struct asl_io_port_desc *resource, u32 length, u32 level);
-
-void
-acpi_dm_fixed_io_descriptor(struct asl_fixed_io_port_desc *resource,
+acpi_dm_fixed_io_descriptor(union aml_resource *resource,
 			    u32 length, u32 level);
 
 void
-acpi_dm_start_dependent_descriptor(struct asl_start_dependent_desc *resource,
+acpi_dm_start_dependent_descriptor(union aml_resource *resource,
 				   u32 length, u32 level);
 
 void
-acpi_dm_end_dependent_descriptor(struct asl_start_dependent_desc *resource,
+acpi_dm_end_dependent_descriptor(union aml_resource *resource,
 				 u32 length, u32 level);
 
 void
-acpi_dm_vendor_small_descriptor(struct asl_small_vendor_desc *resource,
+acpi_dm_vendor_small_descriptor(union aml_resource *resource,
 				u32 length, u32 level);
 
 /*
diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h
index 065f24a..c41a926 100644
--- a/include/acpi/acdispat.h
+++ b/include/acpi/acdispat.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -201,6 +201,9 @@
 			       union acpi_operand_object *obj_desc,
 			       struct acpi_namespace_node *calling_method_node);
 
+acpi_status
+acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state);
+
 /*
  * dsinit
  */
diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h
index bfa5460..f2717be 100644
--- a/include/acpi/acevents.h
+++ b/include/acpi/acevents.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -51,6 +51,8 @@
 
 acpi_status acpi_ev_install_xrupt_handlers(void);
 
+acpi_status acpi_ev_install_fadt_gpes(void);
+
 u32 acpi_ev_fixed_event_detect(void);
 
 /*
@@ -105,6 +107,10 @@
 			 u32 interrupt_number,
 			 struct acpi_gpe_block_info **return_gpe_block);
 
+acpi_status
+acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
+			     struct acpi_gpe_block_info *gpe_block);
+
 acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block);
 
 u32
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 4f005eb..dc768aa 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h
index 4ab2ca1..734cc77 100644
--- a/include/acpi/acglobal.h
+++ b/include/acpi/acglobal.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -80,6 +80,15 @@
 
 extern u32 acpi_gbl_nesting_level;
 
+/* Support for dynamic control method tracing mechanism */
+
+ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
+ACPI_EXTERN u32 acpi_gbl_original_dbg_layer;
+ACPI_EXTERN acpi_name acpi_gbl_trace_method_name;
+ACPI_EXTERN u32 acpi_gbl_trace_dbg_level;
+ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
+ACPI_EXTERN u32 acpi_gbl_trace_flags;
+
 /*****************************************************************************
  *
  * Runtime configuration (static defaults that can be overriden at runtime)
@@ -89,11 +98,15 @@
 /*
  * Enable "slack" in the AML interpreter?  Default is FALSE, and the
  * interpreter strictly follows the ACPI specification.  Setting to TRUE
- * allows the interpreter to forgive certain bad AML constructs.  Currently:
+ * allows the interpreter to ignore certain errors and/or bad AML constructs.
+ *
+ * Currently, these features are enabled by this flag:
+ *
  * 1) Allow "implicit return" of last value in a control method
- * 2) Allow access beyond end of operation region
+ * 2) Allow access beyond the end of an operation region
  * 3) Allow access to uninitialized locals/args (auto-init to integer 0)
  * 4) Allow ANY object type to be a source operand for the Store() operator
+ * 5) Allow unresolved references (invalid target name) in package objects
  */
 ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
 
@@ -211,9 +224,11 @@
 ACPI_EXTERN u32 acpi_gbl_rsdp_original_location;
 ACPI_EXTERN u32 acpi_gbl_ns_lookup_count;
 ACPI_EXTERN u32 acpi_gbl_ps_find_count;
-ACPI_EXTERN u64 acpi_gbl_owner_id_mask;
+ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS];
 ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save;
 ACPI_EXTERN u16 acpi_gbl_global_lock_handle;
+ACPI_EXTERN u8 acpi_gbl_last_owner_id_index;
+ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset;
 ACPI_EXTERN u8 acpi_gbl_debugger_configuration;
 ACPI_EXTERN u8 acpi_gbl_global_lock_acquired;
 ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
diff --git a/include/acpi/achware.h b/include/acpi/achware.h
index 3644d72..29b60a8 100644
--- a/include/acpi/achware.h
+++ b/include/acpi/achware.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index 2c9c1a1..9f22cfc 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,49 @@
 #ifndef __ACINTERP_H__
 #define __ACINTERP_H__
 
-#define ACPI_WALK_OPERANDS       (&(walk_state->operands [walk_state->num_operands -1]))
+#define ACPI_WALK_OPERANDS          (&(walk_state->operands [walk_state->num_operands -1]))
+
+/* Macros for tables used for debug output */
+
+#define ACPI_EXD_OFFSET(f)          (u8) ACPI_OFFSET (union acpi_operand_object,f)
+#define ACPI_EXD_NSOFFSET(f)        (u8) ACPI_OFFSET (struct acpi_namespace_node,f)
+#define ACPI_EXD_TABLE_SIZE(name)   (sizeof(name) / sizeof (struct acpi_exdump_info))
+
+/*
+ * If possible, pack the following structure to byte alignment, since we
+ * don't care about performance for debug output
+ */
+#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
+#pragma pack(1)
+#endif
+
+typedef const struct acpi_exdump_info {
+	u8 opcode;
+	u8 offset;
+	char *name;
+
+} acpi_exdump_info;
+
+/* Values for the Opcode field above */
+
+#define ACPI_EXD_INIT                   0
+#define ACPI_EXD_TYPE                   1
+#define ACPI_EXD_UINT8                  2
+#define ACPI_EXD_UINT16                 3
+#define ACPI_EXD_UINT32                 4
+#define ACPI_EXD_UINT64                 5
+#define ACPI_EXD_LITERAL                6
+#define ACPI_EXD_POINTER                7
+#define ACPI_EXD_ADDRESS                8
+#define ACPI_EXD_STRING                 9
+#define ACPI_EXD_BUFFER                 10
+#define ACPI_EXD_PACKAGE                11
+#define ACPI_EXD_FIELD                  12
+#define ACPI_EXD_REFERENCE              13
+
+/* restore default alignment */
+
+#pragma pack()
 
 /*
  * exconvrt - object conversion
@@ -327,7 +369,7 @@
 void
 acpi_ex_dump_object_descriptor(union acpi_operand_object *object, u32 flags);
 
-void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags);
+void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags);
 #endif				/* ACPI_FUTURE_USAGE */
 
 /*
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index 9fba0fd..8361820 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -276,6 +276,37 @@
 	u8 field_type;
 };
 
+/*
+ * Bitmapped ACPI types.  Used internally only
+ */
+#define ACPI_BTYPE_ANY                  0x00000000
+#define ACPI_BTYPE_INTEGER              0x00000001
+#define ACPI_BTYPE_STRING               0x00000002
+#define ACPI_BTYPE_BUFFER               0x00000004
+#define ACPI_BTYPE_PACKAGE              0x00000008
+#define ACPI_BTYPE_FIELD_UNIT           0x00000010
+#define ACPI_BTYPE_DEVICE               0x00000020
+#define ACPI_BTYPE_EVENT                0x00000040
+#define ACPI_BTYPE_METHOD               0x00000080
+#define ACPI_BTYPE_MUTEX                0x00000100
+#define ACPI_BTYPE_REGION               0x00000200
+#define ACPI_BTYPE_POWER                0x00000400
+#define ACPI_BTYPE_PROCESSOR            0x00000800
+#define ACPI_BTYPE_THERMAL              0x00001000
+#define ACPI_BTYPE_BUFFER_FIELD         0x00002000
+#define ACPI_BTYPE_DDB_HANDLE           0x00004000
+#define ACPI_BTYPE_DEBUG_OBJECT         0x00008000
+#define ACPI_BTYPE_REFERENCE            0x00010000
+#define ACPI_BTYPE_RESOURCE             0x00020000
+
+#define ACPI_BTYPE_COMPUTE_DATA         (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER)
+
+#define ACPI_BTYPE_DATA                 (ACPI_BTYPE_COMPUTE_DATA  | ACPI_BTYPE_PACKAGE)
+#define ACPI_BTYPE_DATA_REFERENCE       (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE)
+#define ACPI_BTYPE_DEVICE_OBJECTS       (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR)
+#define ACPI_BTYPE_OBJECTS_AND_REFS     0x0001FFFF	/* ARG or LOCAL */
+#define ACPI_BTYPE_ALL_OBJECTS          0x0000FFFF
+
 /*****************************************************************************
  *
  * Event typedefs and structs
@@ -385,13 +416,13 @@
 #define ACPI_CONTROL_PREDICATE_FALSE         0xC3
 #define ACPI_CONTROL_PREDICATE_TRUE          0xC4
 
-#define ACPI_STATE_COMMON                  /* Two 32-bit fields and a pointer */\
-	u8                                  data_type;          /* To differentiate various internal objs */\
+#define ACPI_STATE_COMMON   /* Two 32-bit fields and a pointer */\
+	u8                                  data_type;  /* To differentiate various internal objs */\
 	u8                                  flags;      \
 	u16                                 value;      \
 	u16                                 state;      \
 	u16                                 reserved;   \
-	void                                *next;      \
+	void                                *next;
 
 struct acpi_common_state {
 ACPI_STATE_COMMON};
@@ -544,8 +575,7 @@
 	char                                aml_op_name[16]) /* Op name (debug only) */\
 			   /* NON-DEBUG members below: */\
 	struct acpi_namespace_node          *node;          /* For use by interpreter */\
-	union acpi_parse_value              value;          /* Value or args associated with the opcode */\
-
+	union acpi_parse_value              value;	/* Value or args associated with the opcode */
 
 #define ACPI_DASM_BUFFER        0x00
 #define ACPI_DASM_RESOURCE      0x01
@@ -573,6 +603,8 @@
 
 /* The parse node is the fundamental element of the parse tree */
 
+#define ACPI_MAX_PARSEOP_NAME   20
+
 struct acpi_parse_obj_asl {
 	ACPI_PARSE_COMMON union acpi_parse_object *child;
 	union acpi_parse_object *parent_method;
@@ -597,7 +629,7 @@
 	u8 aml_opcode_length;
 	u8 aml_pkg_len_bytes;
 	u8 extra;
-	char parse_op_name[12];
+	char parse_op_name[ACPI_MAX_PARSEOP_NAME];
 };
 
 union acpi_parse_object {
@@ -735,44 +767,52 @@
 
 /* resource_type values */
 
-#define ACPI_RESOURCE_TYPE_MEMORY_RANGE         0
-#define ACPI_RESOURCE_TYPE_IO_RANGE             1
-#define ACPI_RESOURCE_TYPE_BUS_NUMBER_RANGE     2
+#define ACPI_ADDRESS_TYPE_MEMORY_RANGE          0
+#define ACPI_ADDRESS_TYPE_IO_RANGE              1
+#define ACPI_ADDRESS_TYPE_BUS_NUMBER_RANGE      2
 
 /* Resource descriptor types and masks */
 
-#define ACPI_RDESC_TYPE_LARGE                   0x80
-#define ACPI_RDESC_TYPE_SMALL                   0x00
+#define ACPI_RESOURCE_NAME_LARGE                0x80
+#define ACPI_RESOURCE_NAME_SMALL                0x00
 
-#define ACPI_RDESC_TYPE_MASK                    0x80
-#define ACPI_RDESC_SMALL_MASK                   0x78	/* Only bits 6:3 contain the type */
+#define ACPI_RESOURCE_NAME_SMALL_MASK           0x78	/* Bits 6:3 contain the type */
+#define ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK    0x07	/* Bits 2:0 contain the length */
+#define ACPI_RESOURCE_NAME_LARGE_MASK           0x7F	/* Bits 6:0 contain the type */
 
 /*
- * Small resource descriptor types
- * Note: The 3 length bits (2:0) must be zero
+ * Small resource descriptor "names" as defined by the ACPI specification.
+ * Note: Bits 2:0 are used for the descriptor length
  */
-#define ACPI_RDESC_TYPE_IRQ_FORMAT              0x20
-#define ACPI_RDESC_TYPE_DMA_FORMAT              0x28
-#define ACPI_RDESC_TYPE_START_DEPENDENT         0x30
-#define ACPI_RDESC_TYPE_END_DEPENDENT           0x38
-#define ACPI_RDESC_TYPE_IO_PORT                 0x40
-#define ACPI_RDESC_TYPE_FIXED_IO_PORT           0x48
-#define ACPI_RDESC_TYPE_SMALL_VENDOR            0x70
-#define ACPI_RDESC_TYPE_END_TAG                 0x78
+#define ACPI_RESOURCE_NAME_IRQ                  0x20
+#define ACPI_RESOURCE_NAME_DMA                  0x28
+#define ACPI_RESOURCE_NAME_START_DEPENDENT      0x30
+#define ACPI_RESOURCE_NAME_END_DEPENDENT        0x38
+#define ACPI_RESOURCE_NAME_IO                   0x40
+#define ACPI_RESOURCE_NAME_FIXED_IO             0x48
+#define ACPI_RESOURCE_NAME_RESERVED_S1          0x50
+#define ACPI_RESOURCE_NAME_RESERVED_S2          0x58
+#define ACPI_RESOURCE_NAME_RESERVED_S3          0x60
+#define ACPI_RESOURCE_NAME_RESERVED_S4          0x68
+#define ACPI_RESOURCE_NAME_VENDOR_SMALL         0x70
+#define ACPI_RESOURCE_NAME_END_TAG              0x78
 
 /*
- * Large resource descriptor types
+ * Large resource descriptor "names" as defined by the ACPI specification.
+ * Note: includes the Large Descriptor bit in bit[7]
  */
-#define ACPI_RDESC_TYPE_MEMORY_24               0x81
-#define ACPI_RDESC_TYPE_GENERAL_REGISTER        0x82
-#define ACPI_RDESC_TYPE_LARGE_VENDOR            0x84
-#define ACPI_RDESC_TYPE_MEMORY_32               0x85
-#define ACPI_RDESC_TYPE_FIXED_MEMORY_32         0x86
-#define ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE     0x87
-#define ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE      0x88
-#define ACPI_RDESC_TYPE_EXTENDED_XRUPT          0x89
-#define ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE     0x8A
-#define ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE  0x8B
+#define ACPI_RESOURCE_NAME_MEMORY24             0x81
+#define ACPI_RESOURCE_NAME_GENERIC_REGISTER     0x82
+#define ACPI_RESOURCE_NAME_RESERVED_L1          0x83
+#define ACPI_RESOURCE_NAME_VENDOR_LARGE         0x84
+#define ACPI_RESOURCE_NAME_MEMORY32             0x85
+#define ACPI_RESOURCE_NAME_FIXED_MEMORY32       0x86
+#define ACPI_RESOURCE_NAME_ADDRESS32            0x87
+#define ACPI_RESOURCE_NAME_ADDRESS16            0x88
+#define ACPI_RESOURCE_NAME_EXTENDED_IRQ         0x89
+#define ACPI_RESOURCE_NAME_ADDRESS64            0x8A
+#define ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64   0x8B
+#define ACPI_RESOURCE_NAME_LARGE_MAX            0x8B
 
 /*****************************************************************************
  *
@@ -780,7 +820,7 @@
  *
  ****************************************************************************/
 
-#define ACPI_ASCII_ZERO                      0x30
+#define ACPI_ASCII_ZERO                         0x30
 
 /*****************************************************************************
  *
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
index 702cc4e..f2be2a8 100644
--- a/include/acpi/acmacros.h
+++ b/include/acpi/acmacros.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -60,7 +60,7 @@
 
 /*
  * For 16-bit addresses, we have to assume that the upper 32 bits
- * are zero.
+ * (out of 64) are zero.
  */
 #define ACPI_LODWORD(l)                 ((u32)(l))
 #define ACPI_HIDWORD(l)                 ((u32)(0))
@@ -104,30 +104,38 @@
 #define ACPI_FORMAT_UINT64(i)           ACPI_HIDWORD(i),ACPI_LODWORD(i)
 
 /*
- * Extract a byte of data using a pointer.  Any more than a byte and we
- * get into potential aligment issues -- see the STORE macros below
+ * Extract data using a pointer.  Any more than a byte and we
+ * get into potential aligment issues -- see the STORE macros below.
+ * Use with care.
  */
-#define ACPI_GET8(addr)                 (*(u8*)(addr))
+#define ACPI_GET8(ptr)                  *ACPI_CAST_PTR (u8, ptr)
+#define ACPI_GET16(ptr)                 *ACPI_CAST_PTR (u16, ptr)
+#define ACPI_GET32(ptr)                 *ACPI_CAST_PTR (u32, ptr)
+#define ACPI_GET64(ptr)                 *ACPI_CAST_PTR (u64, ptr)
+#define ACPI_SET8(ptr)                  *ACPI_CAST_PTR (u8, ptr)
+#define ACPI_SET16(ptr)                 *ACPI_CAST_PTR (u16, ptr)
+#define ACPI_SET32(ptr)                 *ACPI_CAST_PTR (u32, ptr)
+#define ACPI_SET64(ptr)                 *ACPI_CAST_PTR (u64, ptr)
 
-/* Pointer arithmetic */
-
-#define ACPI_PTR_ADD(t,a,b)             (t *) (void *)((char *)(a) + (acpi_native_uint)(b))
-#define ACPI_PTR_DIFF(a,b)              (acpi_native_uint) ((char *)(a) - (char *)(b))
+/*
+ * Pointer manipulation
+ */
+#define ACPI_CAST_PTR(t, p)             ((t *) (acpi_uintptr_t) (p))
+#define ACPI_CAST_INDIRECT_PTR(t, p)    ((t **) (acpi_uintptr_t) (p))
+#define ACPI_ADD_PTR(t,a,b)             ACPI_CAST_PTR (t, (ACPI_CAST_PTR (u8,(a)) + (acpi_native_uint)(b)))
+#define ACPI_PTR_DIFF(a,b)              (acpi_native_uint) (ACPI_CAST_PTR (u8,(a)) - ACPI_CAST_PTR (u8,(b)))
 
 /* Pointer/Integer type conversions */
 
-#define ACPI_TO_POINTER(i)              ACPI_PTR_ADD (void, (void *) NULL,(acpi_native_uint)i)
+#define ACPI_TO_POINTER(i)              ACPI_ADD_PTR (void,(void *) NULL,(acpi_native_uint) i)
 #define ACPI_TO_INTEGER(p)              ACPI_PTR_DIFF (p,(void *) NULL)
 #define ACPI_OFFSET(d,f)                (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f),(void *) NULL)
 #define ACPI_FADT_OFFSET(f)             ACPI_OFFSET (FADT_DESCRIPTOR, f)
 
-#define ACPI_CAST_PTR(t, p)             ((t *)(void *)(p))
-#define ACPI_CAST_INDIRECT_PTR(t, p)    ((t **)(void *)(p))
-
 #if ACPI_MACHINE_WIDTH == 16
 #define ACPI_STORE_POINTER(d,s)         ACPI_MOVE_32_TO_32(d,s)
 #define ACPI_PHYSADDR_TO_PTR(i)         (void *)(i)
-#define ACPI_PTR_TO_PHYSADDR(i)         (u32) (char *)(i)
+#define ACPI_PTR_TO_PHYSADDR(i)         (u32) ACPI_CAST_PTR (u8,(i))
 #else
 #define ACPI_PHYSADDR_TO_PTR(i)         ACPI_TO_POINTER(i)
 #define ACPI_PTR_TO_PHYSADDR(i)         ACPI_TO_INTEGER(i)
@@ -202,7 +210,7 @@
 
 #define ACPI_BUFFER_INDEX(buf_len,buf_offset,byte_gran) (buf_offset)
 
-#ifdef ACPI_MISALIGNED_TRANSFERS
+#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
 
 /* The hardware supports unaligned transfers, just do the little-endian move */
 
@@ -326,11 +334,19 @@
 #define ACPI_MUL_16(a)                  _ACPI_MUL(a,4)
 #define ACPI_MOD_16(a)                  _ACPI_MOD(a,16)
 
+#define ACPI_DIV_32(a)                  _ACPI_DIV(a,5)
+#define ACPI_MUL_32(a)                  _ACPI_MUL(a,5)
+#define ACPI_MOD_32(a)                  _ACPI_MOD(a,32)
+
 /*
  * Rounding macros (Power of two boundaries only)
  */
-#define ACPI_ROUND_DOWN(value,boundary)      (((acpi_native_uint)(value)) & (~(((acpi_native_uint) boundary)-1)))
-#define ACPI_ROUND_UP(value,boundary)        ((((acpi_native_uint)(value)) + (((acpi_native_uint) boundary)-1)) & (~(((acpi_native_uint) boundary)-1)))
+#define ACPI_ROUND_DOWN(value,boundary)      (((acpi_native_uint)(value)) & \
+												(~(((acpi_native_uint) boundary)-1)))
+
+#define ACPI_ROUND_UP(value,boundary)        ((((acpi_native_uint)(value)) + \
+												(((acpi_native_uint) boundary)-1)) & \
+												(~(((acpi_native_uint) boundary)-1)))
 
 #define ACPI_ROUND_DOWN_TO_32_BITS(a)        ACPI_ROUND_DOWN(a,4)
 #define ACPI_ROUND_DOWN_TO_64_BITS(a)        ACPI_ROUND_DOWN(a,8)
@@ -365,6 +381,14 @@
 #define ACPI_REGISTER_PREPARE_BITS(val, pos, mask)      ((val << pos) & mask)
 #define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val)  reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask)
 
+/* Generate a UUID */
+
+#define ACPI_INIT_UUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
+	(a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \
+	(b) & 0xFF, ((b) >> 8) & 0xFF, \
+	(c) & 0xFF, ((c) >> 8) & 0xFF, \
+	(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)
+
 /*
  * An struct acpi_namespace_node * can appear in some contexts,
  * where a pointer to an union acpi_operand_object    can also
@@ -423,57 +447,52 @@
 #define GET_CURRENT_ARG_TYPE(list)      (list & ((u32) 0x1F))
 #define INCREMENT_ARG_LIST(list)        (list >>= ((u32) ARG_TYPE_WIDTH))
 
+#if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES)
 /*
- * Reporting macros that are never compiled out
+ * Module name is include in both debug and non-debug versions primarily for
+ * error messages. The __FILE__ macro is not very useful for this, because it
+ * often includes the entire pathname to the module
  */
-#define ACPI_PARAM_LIST(pl)                 pl
+#define ACPI_MODULE_NAME(name)          static char ACPI_UNUSED_VAR *_acpi_module_name = name;
+#else
+#define ACPI_MODULE_NAME(name)
+#endif
 
 /*
- * Error reporting.  These versions add callers module and line#.
- *
- * Since _acpi_module_name gets compiled out when ACPI_DEBUG_OUTPUT
- * isn't defined, only use it in debug mode.
+ * Ascii error messages can be configured out
  */
-#ifdef ACPI_DEBUG_OUTPUT
+#ifndef ACPI_NO_ERROR_MESSAGES
+#define AE_INFO                         _acpi_module_name, __LINE__
 
-#define ACPI_REPORT_INFO(fp)                {acpi_ut_report_info(_acpi_module_name,__LINE__,_COMPONENT); \
-												acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define ACPI_REPORT_ERROR(fp)               {acpi_ut_report_error(_acpi_module_name,__LINE__,_COMPONENT); \
-												acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define ACPI_REPORT_WARNING(fp)             {acpi_ut_report_warning(_acpi_module_name,__LINE__,_COMPONENT); \
-												acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define ACPI_REPORT_NSERROR(s,e)            acpi_ns_report_error(_acpi_module_name,__LINE__,_COMPONENT, s, e);
-
-#define ACPI_REPORT_METHOD_ERROR(s,n,p,e)   acpi_ns_report_method_error(_acpi_module_name,__LINE__,_COMPONENT, s, n, p, e);
+/*
+ * Error reporting. Callers module and line number are inserted by AE_INFO,
+ * the plist contains a set of parens to allow variable-length lists.
+ * These macros are used for both the debug and non-debug versions of the code.
+ */
+#define ACPI_INFO(plist)                acpi_ut_info plist
+#define ACPI_WARNING(plist)             acpi_ut_warning plist
+#define ACPI_EXCEPTION(plist)           acpi_ut_exception plist
+#define ACPI_ERROR(plist)               acpi_ut_error plist
+#define ACPI_ERROR_NAMESPACE(s,e)       acpi_ns_report_error (AE_INFO, s, e);
+#define ACPI_ERROR_METHOD(s,n,p,e)      acpi_ns_report_method_error (AE_INFO, s, n, p, e);
 
 #else
 
-#define ACPI_REPORT_INFO(fp)                {acpi_ut_report_info("ACPI",__LINE__,_COMPONENT); \
-												acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define ACPI_REPORT_ERROR(fp)               {acpi_ut_report_error("ACPI",__LINE__,_COMPONENT); \
-												acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define ACPI_REPORT_WARNING(fp)             {acpi_ut_report_warning("ACPI",__LINE__,_COMPONENT); \
-												acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define ACPI_REPORT_NSERROR(s,e)            acpi_ns_report_error("ACPI",__LINE__,_COMPONENT, s, e);
+/* No error messages */
 
-#define ACPI_REPORT_METHOD_ERROR(s,n,p,e)   acpi_ns_report_method_error("ACPI",__LINE__,_COMPONENT, s, n, p, e);
+#define ACPI_INFO(plist)
+#define ACPI_WARNING(plist)
+#define ACPI_EXCEPTION(plist)
+#define ACPI_ERROR(plist)
+#define ACPI_ERROR_NAMESPACE(s,e)
+#define ACPI_ERROR_METHOD(s,n,p,e)
 
 #endif
 
-/* Error reporting.  These versions pass thru the module and line# */
-
-#define _ACPI_REPORT_INFO(a,b,c,fp)         {acpi_ut_report_info(a,b,c); \
-												acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define _ACPI_REPORT_ERROR(a,b,c,fp)        {acpi_ut_report_error(a,b,c); \
-												acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define _ACPI_REPORT_WARNING(a,b,c,fp)      {acpi_ut_report_warning(a,b,c); \
-												acpi_os_printf ACPI_PARAM_LIST(fp);}
-
 /*
  * Debug macros that are conditionally compiled
  */
 #ifdef ACPI_DEBUG_OUTPUT
-#define ACPI_MODULE_NAME(name)          static char ACPI_UNUSED_VAR *_acpi_module_name = name;
 
 /*
  * Common parameters used for debug output functions:
@@ -509,7 +528,7 @@
 #endif
 
 #define ACPI_FUNCTION_TRACE(a)          ACPI_FUNCTION_NAME(a) \
-											acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
+									  acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
 #define ACPI_FUNCTION_TRACE_PTR(a,b)    ACPI_FUNCTION_NAME(a) \
 											acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS,(void *)b)
 #define ACPI_FUNCTION_TRACE_U32(a,b)    ACPI_FUNCTION_NAME(a) \
@@ -525,6 +544,9 @@
  * bad form, but having a separate exit macro is very ugly and difficult to maintain.
  * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros
  * so that "_acpi_function_name" is defined.
+ *
+ * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining
+ * about these constructs.
  */
 #ifdef ACPI_USE_DO_WHILE_0
 #define ACPI_DO_WHILE0(a)               do a while(0)
@@ -532,10 +554,55 @@
 #define ACPI_DO_WHILE0(a)               a
 #endif
 
-#define return_VOID                     ACPI_DO_WHILE0 ({acpi_ut_exit(ACPI_DEBUG_PARAMETERS);return;})
-#define return_ACPI_STATUS(s)           ACPI_DO_WHILE0 ({acpi_ut_status_exit(ACPI_DEBUG_PARAMETERS,(s));return((s));})
-#define return_VALUE(s)                 ACPI_DO_WHILE0 ({acpi_ut_value_exit(ACPI_DEBUG_PARAMETERS,(acpi_integer)(s));return((s));})
-#define return_PTR(s)                   ACPI_DO_WHILE0 ({acpi_ut_ptr_exit(ACPI_DEBUG_PARAMETERS,(u8 *)(s));return((s));})
+#define return_VOID                     ACPI_DO_WHILE0 ({ \
+											acpi_ut_exit (ACPI_DEBUG_PARAMETERS); \
+											return;})
+/*
+ * There are two versions of most of the return macros. The default version is
+ * safer, since it avoids side-effects by guaranteeing that the argument will
+ * not be evaluated twice.
+ *
+ * A less-safe version of the macros is provided for optional use if the
+ * compiler uses excessive CPU stack (for example, this may happen in the
+ * debug case if code optimzation is disabled.)
+ */
+#ifndef ACPI_SIMPLE_RETURN_MACROS
+
+#define return_ACPI_STATUS(s)           ACPI_DO_WHILE0 ({ \
+											register acpi_status _s = (s); \
+											acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, _s); \
+											return (_s); })
+#define return_PTR(s)                   ACPI_DO_WHILE0 ({ \
+											register void *_s = (void *) (s); \
+											acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) _s); \
+											return (_s); })
+#define return_VALUE(s)                 ACPI_DO_WHILE0 ({ \
+											register acpi_integer _s = (s); \
+											acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, _s); \
+											return (_s); })
+#define return_UINT8(s)                 ACPI_DO_WHILE0 ({ \
+											register u8 _s = (u8) (s); \
+											acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (acpi_integer) _s); \
+											return (_s); })
+#define return_UINT32(s)                ACPI_DO_WHILE0 ({ \
+											register u32 _s = (u32) (s); \
+											acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (acpi_integer) _s); \
+											return (_s); })
+#else				/* Use original less-safe macros */
+
+#define return_ACPI_STATUS(s)           ACPI_DO_WHILE0 ({ \
+											acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, (s)); \
+											return((s)); })
+#define return_PTR(s)                   ACPI_DO_WHILE0 ({ \
+											acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) (s)); \
+											return((s)); })
+#define return_VALUE(s)                 ACPI_DO_WHILE0 ({ \
+											acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (acpi_integer) (s)); \
+											return((s)); })
+#define return_UINT8(s)                 return_VALUE(s)
+#define return_UINT32(s)                return_VALUE(s)
+
+#endif				/* ACPI_SIMPLE_RETURN_MACROS */
 
 /* Conditional execution */
 
@@ -555,18 +622,6 @@
 #define ACPI_DUMP_PATHNAME(a,b,c,d)     acpi_ns_dump_pathname(a,b,c,d)
 #define ACPI_DUMP_RESOURCE_LIST(a)      acpi_rs_dump_resource_list(a)
 #define ACPI_DUMP_BUFFER(a,b)           acpi_ut_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT)
-#define ACPI_BREAK_MSG(a)               acpi_os_signal (ACPI_SIGNAL_BREAKPOINT,(a))
-
-/*
- * Generate INT3 on ACPI_ERROR (Debug only!)
- */
-#define ACPI_ERROR_BREAK
-#ifdef  ACPI_ERROR_BREAK
-#define ACPI_BREAK_ON_ERROR(lvl)        if ((lvl)&ACPI_ERROR) \
-											acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,"Fatal error encountered\n")
-#else
-#define ACPI_BREAK_ON_ERROR(lvl)
-#endif
 
 /*
  * Master debug print macros
@@ -574,17 +629,14 @@
  *    1) Debug print for the current component is enabled
  *    2) Debug error level or trace level for the print statement is enabled
  */
-#define ACPI_DEBUG_PRINT(pl)            acpi_ut_debug_print ACPI_PARAM_LIST(pl)
-#define ACPI_DEBUG_PRINT_RAW(pl)        acpi_ut_debug_print_raw ACPI_PARAM_LIST(pl)
+#define ACPI_DEBUG_PRINT(plist)         acpi_ut_debug_print plist
+#define ACPI_DEBUG_PRINT_RAW(plist)     acpi_ut_debug_print_raw plist
 
 #else
 /*
  * This is the non-debug case -- make everything go away,
  * leaving no executable debug code!
  */
-#define ACPI_MODULE_NAME(name)
-#define _acpi_module_name ""
-
 #define ACPI_DEBUG_EXEC(a)
 #define ACPI_NORMAL_EXEC(a)             a;
 
@@ -607,11 +659,12 @@
 #define ACPI_DUMP_BUFFER(a,b)
 #define ACPI_DEBUG_PRINT(pl)
 #define ACPI_DEBUG_PRINT_RAW(pl)
-#define ACPI_BREAK_MSG(a)
 
 #define return_VOID                     return
 #define return_ACPI_STATUS(s)           return(s)
 #define return_VALUE(s)                 return(s)
+#define return_UINT8(s)                 return(s)
+#define return_UINT32(s)                return(s)
 #define return_PTR(s)                   return(s)
 
 #endif
diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h
index 4f9063f..b67da36 100644
--- a/include/acpi/acnames.h
+++ b/include/acpi/acnames.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
index dd3501f..b667a80 100644
--- a/include/acpi/acnamesp.h
+++ b/include/acpi/acnamesp.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -263,13 +263,11 @@
 void
 acpi_ns_report_error(char *module_name,
 		     u32 line_number,
-		     u32 component_id,
 		     char *internal_name, acpi_status lookup_status);
 
 void
 acpi_ns_report_method_error(char *module_name,
 			    u32 line_number,
-			    u32 component_id,
 			    char *message,
 			    struct acpi_namespace_node *node,
 			    char *path, acpi_status lookup_status);
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index 4a326ba..d130cfe 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -69,7 +69,7 @@
 	u8                                      type;               /* acpi_object_type */\
 	u16                                     reference_count;    /* For object deletion management */\
 	union acpi_operand_object               *next_object;       /* Objects linked to parent NS node */\
-	u8                                      flags; \
+	u8                                      flags;
 
 /* Values for flag byte above */
 
diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h
index 64da429..e6d78bd 100644
--- a/include/acpi/acopcode.h
+++ b/include/acpi/acopcode.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 68d7edf..7785d48 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -137,13 +137,19 @@
 
 /* Exception level -- used in the global "debug_level" */
 
-#define ACPI_DB_ERROR               ACPI_DEBUG_LEVEL (ACPI_LV_ERROR)
-#define ACPI_DB_WARN                ACPI_DEBUG_LEVEL (ACPI_LV_WARN)
 #define ACPI_DB_INIT                ACPI_DEBUG_LEVEL (ACPI_LV_INIT)
 #define ACPI_DB_DEBUG_OBJECT        ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT)
 #define ACPI_DB_INFO                ACPI_DEBUG_LEVEL (ACPI_LV_INFO)
 #define ACPI_DB_ALL_EXCEPTIONS      ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS)
 
+/*
+ * These two levels are essentially obsolete, all instances in the
+ * ACPICA core code have been replaced by REPORT_ERROR and REPORT_WARNING
+ * (Kept here because some drivers may still use them)
+ */
+#define ACPI_DB_ERROR               ACPI_DEBUG_LEVEL (ACPI_LV_ERROR)
+#define ACPI_DB_WARN                ACPI_DEBUG_LEVEL (ACPI_LV_WARN)
+
 /* Trace level -- also used in the global "debug_level" */
 
 #define ACPI_DB_INIT_NAMES          ACPI_DEBUG_LEVEL (ACPI_LV_INIT_NAMES)
diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h
index d352d40..5a1ff48 100644
--- a/include/acpi/acparser.h
+++ b/include/acpi/acparser.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acpi.h b/include/acpi/acpi.h
index ccf34f9..b9a39d1 100644
--- a/include/acpi/acpi.h
+++ b/include/acpi/acpi.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index c1b4e1f..b425f9b 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -52,8 +52,8 @@
 /* ACPI PCI Interrupt Link (pci_link.c) */
 
 int acpi_irq_penalty_init(void);
-int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *edge_level,
-			       int *active_high_low, char **name);
+int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
+			       int *polarity, char **name);
 int acpi_pci_link_free_irq(acpi_handle handle);
 
 /* ACPI PCI Interrupt Routing (pci_irq.c) */
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 98e0b8c..970e9a6 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -8,7 +8,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -108,9 +108,9 @@
 
 void acpi_os_delete_lock(acpi_handle handle);
 
-unsigned long acpi_os_acquire_lock(acpi_handle handle);
+acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle);
 
-void acpi_os_release_lock(acpi_handle handle, unsigned long flags);
+void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags);
 
 /*
  * Memory allocation and mapping
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 2a9dbc1..66cf2ec 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -149,6 +149,9 @@
 acpi_status
 acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data);
 
+acpi_status
+acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags);
+
 /*
  * Object manipulation and enumeration
  */
@@ -269,6 +272,12 @@
 					   void *context);
 
 acpi_status
+acpi_get_vendor_resource(acpi_handle device_handle,
+			 char *name,
+			 struct acpi_vendor_uuid *uuid,
+			 struct acpi_buffer *ret_buffer);
+
+acpi_status
 acpi_get_current_resources(acpi_handle device_handle,
 			   struct acpi_buffer *ret_buffer);
 
@@ -280,7 +289,7 @@
 
 acpi_status
 acpi_walk_resources(acpi_handle device_handle,
-		    char *path,
+		    char *name,
 		    ACPI_WALK_RESOURCE_CALLBACK user_function, void *context);
 
 acpi_status
diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h
index 38e798b..fa02e80 100644
--- a/include/acpi/acresrc.h
+++ b/include/acpi/acresrc.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,8 +44,125 @@
 #ifndef __ACRESRC_H__
 #define __ACRESRC_H__
 
+/* Need the AML resource descriptor structs */
+
+#include "amlresrc.h"
+
 /*
- *  Function prototypes called from Acpi* APIs
+ * If possible, pack the following structures to byte alignment, since we
+ * don't care about performance for debug output
+ */
+#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
+#pragma pack(1)
+#endif
+
+/*
+ * Individual entry for the resource conversion tables
+ */
+typedef const struct acpi_rsconvert_info {
+	u8 opcode;
+	u8 resource_offset;
+	u8 aml_offset;
+	u8 value;
+
+} acpi_rsconvert_info;
+
+/* Resource conversion opcodes */
+
+#define ACPI_RSC_INITGET                0
+#define ACPI_RSC_INITSET                1
+#define ACPI_RSC_FLAGINIT               2
+#define ACPI_RSC_1BITFLAG               3
+#define ACPI_RSC_2BITFLAG               4
+#define ACPI_RSC_COUNT                  5
+#define ACPI_RSC_COUNT16                6
+#define ACPI_RSC_LENGTH                 7
+#define ACPI_RSC_MOVE8                  8
+#define ACPI_RSC_MOVE16                 9
+#define ACPI_RSC_MOVE32                 10
+#define ACPI_RSC_MOVE64                 11
+#define ACPI_RSC_SET8                   12
+#define ACPI_RSC_DATA8                  13
+#define ACPI_RSC_ADDRESS                14
+#define ACPI_RSC_SOURCE                 15
+#define ACPI_RSC_SOURCEX                16
+#define ACPI_RSC_BITMASK                17
+#define ACPI_RSC_BITMASK16              18
+#define ACPI_RSC_EXIT_NE                19
+#define ACPI_RSC_EXIT_LE                20
+
+/* Resource Conversion sub-opcodes */
+
+#define ACPI_RSC_COMPARE_AML_LENGTH     0
+#define ACPI_RSC_COMPARE_VALUE          1
+
+#define ACPI_RSC_TABLE_SIZE(d)          (sizeof (d) / sizeof (struct acpi_rsconvert_info))
+
+#define ACPI_RS_OFFSET(f)               (u8) ACPI_OFFSET (struct acpi_resource,f)
+#define AML_OFFSET(f)                   (u8) ACPI_OFFSET (union aml_resource,f)
+
+typedef const struct acpi_rsdump_info {
+	u8 opcode;
+	u8 offset;
+	char *name;
+	const char **pointer;
+
+} acpi_rsdump_info;
+
+/* Values for the Opcode field above */
+
+#define ACPI_RSD_TITLE                  0
+#define ACPI_RSD_LITERAL                1
+#define ACPI_RSD_STRING                 2
+#define ACPI_RSD_UINT8                  3
+#define ACPI_RSD_UINT16                 4
+#define ACPI_RSD_UINT32                 5
+#define ACPI_RSD_UINT64                 6
+#define ACPI_RSD_1BITFLAG               7
+#define ACPI_RSD_2BITFLAG               8
+#define ACPI_RSD_SHORTLIST              9
+#define ACPI_RSD_LONGLIST               10
+#define ACPI_RSD_DWORDLIST              11
+#define ACPI_RSD_ADDRESS                12
+#define ACPI_RSD_SOURCE                 13
+
+/* restore default alignment */
+
+#pragma pack()
+
+/* Resource tables indexed by internal resource type */
+
+extern const u8 acpi_gbl_aml_resource_sizes[];
+extern struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[];
+
+/* Resource tables indexed by raw AML resource descriptor type */
+
+extern const u8 acpi_gbl_resource_struct_sizes[];
+extern struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[];
+
+struct acpi_vendor_walk_info {
+	struct acpi_vendor_uuid *uuid;
+	struct acpi_buffer *buffer;
+	acpi_status status;
+};
+
+/*
+ * rscreate
+ */
+acpi_status
+acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
+			     struct acpi_buffer *output_buffer);
+
+acpi_status
+acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
+			     struct acpi_buffer *output_buffer);
+
+acpi_status
+acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
+				 struct acpi_buffer *output_buffer);
+
+/*
+ * rsutils
  */
 acpi_status
 acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
@@ -65,195 +182,146 @@
 acpi_status
 acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
 
-acpi_status
-acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer,
-			     struct acpi_buffer *output_buffer);
-
-acpi_status
-acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer,
-			   struct acpi_buffer *output_buffer);
-
-acpi_status
-acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
-				 struct acpi_buffer *output_buffer);
-
-/*
- * rsdump
- */
-#ifdef	ACPI_FUTURE_USAGE
-void acpi_rs_dump_resource_list(struct acpi_resource *resource);
-
-void acpi_rs_dump_irq_list(u8 * route_table);
-#endif				/* ACPI_FUTURE_USAGE */
-
 /*
  * rscalc
  */
 acpi_status
-acpi_rs_get_byte_stream_start(u8 * byte_stream_buffer,
-			      u8 ** byte_stream_start, u32 * size);
+acpi_rs_get_list_length(u8 * aml_buffer,
+			u32 aml_buffer_length, acpi_size * size_needed);
 
 acpi_status
-acpi_rs_get_list_length(u8 * byte_stream_buffer,
-			u32 byte_stream_buffer_length, acpi_size * size_needed);
-
-acpi_status
-acpi_rs_get_byte_stream_length(struct acpi_resource *linked_list_buffer,
-			       acpi_size * size_needed);
+acpi_rs_get_aml_length(struct acpi_resource *linked_list_buffer,
+		       acpi_size * size_needed);
 
 acpi_status
 acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
 				     acpi_size * buffer_size_needed);
 
 acpi_status
-acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer,
-			    u32 byte_stream_buffer_length, u8 * output_buffer);
+acpi_rs_convert_aml_to_resources(u8 * aml_buffer,
+				 u32 aml_buffer_length, u8 * output_buffer);
 
 acpi_status
-acpi_rs_list_to_byte_stream(struct acpi_resource *linked_list,
-			    acpi_size byte_stream_size_needed,
-			    u8 * output_buffer);
+acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
+				 acpi_size aml_size_needed, u8 * output_buffer);
+
+/*
+ * rsaddr
+ */
+void
+acpi_rs_set_address_common(union aml_resource *aml,
+			   struct acpi_resource *resource);
+
+u8
+acpi_rs_get_address_common(struct acpi_resource *resource,
+			   union aml_resource *aml);
+
+/*
+ * rsmisc
+ */
+acpi_status
+acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
+				union aml_resource *aml,
+				struct acpi_rsconvert_info *info);
 
 acpi_status
-acpi_rs_io_resource(u8 * byte_stream_buffer,
-		    acpi_size * bytes_consumed,
-		    u8 ** output_buffer, acpi_size * structure_size);
+acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
+				union aml_resource *aml,
+				struct acpi_rsconvert_info *info);
 
-acpi_status
-acpi_rs_fixed_io_resource(u8 * byte_stream_buffer,
-			  acpi_size * bytes_consumed,
-			  u8 ** output_buffer, acpi_size * structure_size);
+/*
+ * rsutils
+ */
+void
+acpi_rs_move_data(void *destination,
+		  void *source, u16 item_count, u8 move_type);
 
-acpi_status
-acpi_rs_io_stream(struct acpi_resource *linked_list,
-		  u8 ** output_buffer, acpi_size * bytes_consumed);
+u8 acpi_rs_decode_bitmask(u16 mask, u8 * list);
 
-acpi_status
-acpi_rs_fixed_io_stream(struct acpi_resource *linked_list,
-			u8 ** output_buffer, acpi_size * bytes_consumed);
+u16 acpi_rs_encode_bitmask(u8 * list, u8 count);
 
-acpi_status
-acpi_rs_irq_resource(u8 * byte_stream_buffer,
-		     acpi_size * bytes_consumed,
-		     u8 ** output_buffer, acpi_size * structure_size);
+acpi_rs_length
+acpi_rs_get_resource_source(acpi_rs_length resource_length,
+			    acpi_rs_length minimum_length,
+			    struct acpi_resource_source *resource_source,
+			    union aml_resource *aml, char *string_ptr);
 
-acpi_status
-acpi_rs_irq_stream(struct acpi_resource *linked_list,
-		   u8 ** output_buffer, acpi_size * bytes_consumed);
+acpi_rsdesc_size
+acpi_rs_set_resource_source(union aml_resource *aml,
+			    acpi_rs_length minimum_length,
+			    struct acpi_resource_source *resource_source);
 
-acpi_status
-acpi_rs_dma_resource(u8 * byte_stream_buffer,
-		     acpi_size * bytes_consumed,
-		     u8 ** output_buffer, acpi_size * structure_size);
+void
+acpi_rs_set_resource_header(u8 descriptor_type,
+			    acpi_rsdesc_size total_length,
+			    union aml_resource *aml);
 
-acpi_status
-acpi_rs_dma_stream(struct acpi_resource *linked_list,
-		   u8 ** output_buffer, acpi_size * bytes_consumed);
+void
+acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
+			    union aml_resource *aml);
 
-acpi_status
-acpi_rs_address16_resource(u8 * byte_stream_buffer,
-			   acpi_size * bytes_consumed,
-			   u8 ** output_buffer, acpi_size * structure_size);
+/*
+ * rsdump
+ */
+void acpi_rs_dump_resource_list(struct acpi_resource *resource);
 
-acpi_status
-acpi_rs_address16_stream(struct acpi_resource *linked_list,
-			 u8 ** output_buffer, acpi_size * bytes_consumed);
+void acpi_rs_dump_irq_list(u8 * route_table);
 
-acpi_status
-acpi_rs_address32_resource(u8 * byte_stream_buffer,
-			   acpi_size * bytes_consumed,
-			   u8 ** output_buffer, acpi_size * structure_size);
+/*
+ * Resource conversion tables
+ */
+extern struct acpi_rsconvert_info acpi_rs_convert_dma[];
+extern struct acpi_rsconvert_info acpi_rs_convert_end_dpf[];
+extern struct acpi_rsconvert_info acpi_rs_convert_io[];
+extern struct acpi_rsconvert_info acpi_rs_convert_fixed_io[];
+extern struct acpi_rsconvert_info acpi_rs_convert_end_tag[];
+extern struct acpi_rsconvert_info acpi_rs_convert_memory24[];
+extern struct acpi_rsconvert_info acpi_rs_convert_generic_reg[];
+extern struct acpi_rsconvert_info acpi_rs_convert_memory32[];
+extern struct acpi_rsconvert_info acpi_rs_convert_fixed_memory32[];
+extern struct acpi_rsconvert_info acpi_rs_convert_address32[];
+extern struct acpi_rsconvert_info acpi_rs_convert_address16[];
+extern struct acpi_rsconvert_info acpi_rs_convert_ext_irq[];
+extern struct acpi_rsconvert_info acpi_rs_convert_address64[];
+extern struct acpi_rsconvert_info acpi_rs_convert_ext_address64[];
 
-acpi_status
-acpi_rs_address32_stream(struct acpi_resource *linked_list,
-			 u8 ** output_buffer, acpi_size * bytes_consumed);
+/* These resources require separate get/set tables */
 
-acpi_status
-acpi_rs_address64_resource(u8 * byte_stream_buffer,
-			   acpi_size * bytes_consumed,
-			   u8 ** output_buffer, acpi_size * structure_size);
+extern struct acpi_rsconvert_info acpi_rs_get_irq[];
+extern struct acpi_rsconvert_info acpi_rs_get_start_dpf[];
+extern struct acpi_rsconvert_info acpi_rs_get_vendor_small[];
+extern struct acpi_rsconvert_info acpi_rs_get_vendor_large[];
 
-acpi_status
-acpi_rs_address64_stream(struct acpi_resource *linked_list,
-			 u8 ** output_buffer, acpi_size * bytes_consumed);
+extern struct acpi_rsconvert_info acpi_rs_set_irq[];
+extern struct acpi_rsconvert_info acpi_rs_set_start_dpf[];
+extern struct acpi_rsconvert_info acpi_rs_set_vendor[];
 
-acpi_status
-acpi_rs_start_depend_fns_resource(u8 * byte_stream_buffer,
-				  acpi_size * bytes_consumed,
-				  u8 ** output_buffer,
-				  acpi_size * structure_size);
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+/*
+ * rsinfo
+ */
+extern struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[];
 
-acpi_status
-acpi_rs_end_depend_fns_resource(u8 * byte_stream_buffer,
-				acpi_size * bytes_consumed,
-				u8 ** output_buffer,
-				acpi_size * structure_size);
-
-acpi_status
-acpi_rs_start_depend_fns_stream(struct acpi_resource *linked_list,
-				u8 ** output_buffer,
-				acpi_size * bytes_consumed);
-
-acpi_status
-acpi_rs_end_depend_fns_stream(struct acpi_resource *linked_list,
-			      u8 ** output_buffer, acpi_size * bytes_consumed);
-
-acpi_status
-acpi_rs_memory24_resource(u8 * byte_stream_buffer,
-			  acpi_size * bytes_consumed,
-			  u8 ** output_buffer, acpi_size * structure_size);
-
-acpi_status
-acpi_rs_memory24_stream(struct acpi_resource *linked_list,
-			u8 ** output_buffer, acpi_size * bytes_consumed);
-
-acpi_status
-acpi_rs_memory32_range_resource(u8 * byte_stream_buffer,
-				acpi_size * bytes_consumed,
-				u8 ** output_buffer,
-				acpi_size * structure_size);
-
-acpi_status
-acpi_rs_fixed_memory32_resource(u8 * byte_stream_buffer,
-				acpi_size * bytes_consumed,
-				u8 ** output_buffer,
-				acpi_size * structure_size);
-
-acpi_status
-acpi_rs_memory32_range_stream(struct acpi_resource *linked_list,
-			      u8 ** output_buffer, acpi_size * bytes_consumed);
-
-acpi_status
-acpi_rs_fixed_memory32_stream(struct acpi_resource *linked_list,
-			      u8 ** output_buffer, acpi_size * bytes_consumed);
-
-acpi_status
-acpi_rs_extended_irq_resource(u8 * byte_stream_buffer,
-			      acpi_size * bytes_consumed,
-			      u8 ** output_buffer, acpi_size * structure_size);
-
-acpi_status
-acpi_rs_extended_irq_stream(struct acpi_resource *linked_list,
-			    u8 ** output_buffer, acpi_size * bytes_consumed);
-
-acpi_status
-acpi_rs_end_tag_resource(u8 * byte_stream_buffer,
-			 acpi_size * bytes_consumed,
-			 u8 ** output_buffer, acpi_size * structure_size);
-
-acpi_status
-acpi_rs_end_tag_stream(struct acpi_resource *linked_list,
-		       u8 ** output_buffer, acpi_size * bytes_consumed);
-
-acpi_status
-acpi_rs_vendor_resource(u8 * byte_stream_buffer,
-			acpi_size * bytes_consumed,
-			u8 ** output_buffer, acpi_size * structure_size);
-
-acpi_status
-acpi_rs_vendor_stream(struct acpi_resource *linked_list,
-		      u8 ** output_buffer, acpi_size * bytes_consumed);
-
-u8 acpi_rs_get_resource_type(u8 resource_start_byte);
+/*
+ * rsdump
+ */
+extern struct acpi_rsdump_info acpi_rs_dump_irq[];
+extern struct acpi_rsdump_info acpi_rs_dump_dma[];
+extern struct acpi_rsdump_info acpi_rs_dump_start_dpf[];
+extern struct acpi_rsdump_info acpi_rs_dump_end_dpf[];
+extern struct acpi_rsdump_info acpi_rs_dump_io[];
+extern struct acpi_rsdump_info acpi_rs_dump_fixed_io[];
+extern struct acpi_rsdump_info acpi_rs_dump_vendor[];
+extern struct acpi_rsdump_info acpi_rs_dump_end_tag[];
+extern struct acpi_rsdump_info acpi_rs_dump_memory24[];
+extern struct acpi_rsdump_info acpi_rs_dump_memory32[];
+extern struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[];
+extern struct acpi_rsdump_info acpi_rs_dump_address16[];
+extern struct acpi_rsdump_info acpi_rs_dump_address32[];
+extern struct acpi_rsdump_info acpi_rs_dump_address64[];
+extern struct acpi_rsdump_info acpi_rs_dump_ext_address64[];
+extern struct acpi_rsdump_info acpi_rs_dump_ext_irq[];
+extern struct acpi_rsdump_info acpi_rs_dump_generic_reg[];
+#endif
 
 #endif				/* __ACRESRC_H__ */
diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h
index 99d2353..d8c1c2c 100644
--- a/include/acpi/acstruct.h
+++ b/include/acpi/acstruct.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/actables.h b/include/acpi/actables.h
index f92c185..30a4754 100644
--- a/include/acpi/actables.h
+++ b/include/acpi/actables.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index a46f406..ed53f84 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,12 @@
 #define __ACTBL_H__
 
 /*
+ * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
+ * This is the only type that is even remotely portable. Anything else is not
+ * portable, so do not use any other bitfield types.
+ */
+
+/*
  *  Values for description table header signatures
  */
 #define RSDP_NAME               "RSDP"
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index 67312c3..cd428d5 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 50305ce..dfc7ac1 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 6213b27..7ca89cd 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,15 @@
 #ifndef __ACTYPES_H__
 #define __ACTYPES_H__
 
-/*! [Begin] no source code translation (keep the typedefs) */
+/*
+ * ACPI_MACHINE_WIDTH must be specified in an OS- or compiler-dependent header
+ * and must be either 16, 32, or 64
+ */
+#ifndef ACPI_MACHINE_WIDTH
+#error ACPI_MACHINE_WIDTH not defined
+#endif
+
+/*! [Begin] no source code translation */
 
 /*
  * Data type ranges
@@ -58,87 +66,150 @@
 #define ACPI_UINT64_MAX                 (UINT64)(~((UINT64) 0))	/* 0xFFFFFFFFFFFFFFFF */
 #define ACPI_ASCII_MAX                  0x7F
 
-#ifdef DEFINE_ALTERNATE_TYPES
 /*
- * Types used only in translated source, defined here to enable
- * cross-platform compilation only.
- */
-typedef int s32;
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-typedef COMPILER_DEPENDENT_UINT64 u64;
-
-#endif
-
-/*
- * Data types - Fixed across all compilation models (16/32/64)
+ * Architecture-specific ACPICA Subsystem Data Types
  *
- * BOOLEAN          Logical Boolean.
- * INT8             8-bit  (1 byte) signed value
- * UINT8            8-bit  (1 byte) unsigned value
- * INT16            16-bit (2 byte) signed value
- * UINT16           16-bit (2 byte) unsigned value
- * INT32            32-bit (4 byte) signed value
- * UINT32           32-bit (4 byte) unsigned value
- * INT64            64-bit (8 byte) signed value
- * UINT64           64-bit (8 byte) unsigned value
- * ACPI_NATIVE_INT  32-bit on IA-32, 64-bit on IA-64 signed value
- * ACPI_NATIVE_UINT 32-bit on IA-32, 64-bit on IA-64 unsigned value
+ * The goal of these types is to provide source code portability across
+ * 16-bit, 32-bit, and 64-bit targets.
+ *
+ * 1) The following types are of fixed size for all targets (16/32/64):
+ *
+ * BOOLEAN      Logical boolean
+ *
+ * UINT8        8-bit  (1 byte) unsigned value
+ * UINT16       16-bit (2 byte) unsigned value
+ * UINT32       32-bit (4 byte) unsigned value
+ * UINT64       64-bit (8 byte) unsigned value
+ *
+ * INT16        16-bit (2 byte) signed value
+ * INT32        32-bit (4 byte) signed value
+ * INT64        64-bit (8 byte) signed value
+ *
+ * COMPILER_DEPENDENT_UINT64/INT64 - These types are defined in the
+ * compiler-dependent header(s) and were introduced because there is no common
+ * 64-bit integer type across the various compilation models, as shown in
+ * the table below.
+ *
+ * Datatype  LP64 ILP64 LLP64 ILP32 LP32 16bit
+ * char      8    8     8     8     8    8
+ * short     16   16    16    16    16   16
+ * _int32         32
+ * int       32   64    32    32    16   16
+ * long      64   64    32    32    32   32
+ * long long            64    64
+ * pointer   64   64    64    32    32   32
+ *
+ * Note: ILP64 and LP32 are currently not supported.
+ *
+ *
+ * 2) These types represent the native word size of the target mode of the
+ * processor, and may be 16-bit, 32-bit, or 64-bit as required. They are
+ * usually used for memory allocation, efficient loop counters, and array
+ * indexes. The types are similar to the size_t type in the C library and are
+ * required because there is no C type that consistently represents the native
+ * data width.
+ *
+ * ACPI_SIZE        16/32/64-bit unsigned value
+ * ACPI_NATIVE_UINT 16/32/64-bit unsigned value
+ * ACPI_NATIVE_INT  16/32/64-bit signed value
+ *
  */
 
-#ifndef ACPI_MACHINE_WIDTH
-#error ACPI_MACHINE_WIDTH not defined
-#endif
+/*******************************************************************************
+ *
+ * Common types for all compilers, all targets
+ *
+ ******************************************************************************/
 
-#if ACPI_MACHINE_WIDTH == 64
-
-/*! [Begin] no source code translation (keep the typedefs) */
-
-/*
- * 64-bit type definitions
- */
-typedef unsigned char UINT8;
 typedef unsigned char BOOLEAN;
+typedef unsigned char UINT8;
 typedef unsigned short UINT16;
-typedef int INT32;
-typedef unsigned int UINT32;
-typedef COMPILER_DEPENDENT_INT64 INT64;
 typedef COMPILER_DEPENDENT_UINT64 UINT64;
+typedef COMPILER_DEPENDENT_INT64 INT64;
 
 /*! [End] no source code translation !*/
 
-typedef s64 acpi_native_int;
+/*******************************************************************************
+ *
+ * Types specific to 64-bit targets
+ *
+ ******************************************************************************/
+
+#if ACPI_MACHINE_WIDTH == 64
+
+/*! [Begin] no source code translation (keep the typedefs as-is) */
+
+typedef unsigned int UINT32;
+typedef int INT32;
+
+/*! [End] no source code translation !*/
+
 typedef u64 acpi_native_uint;
+typedef s64 acpi_native_int;
 
 typedef u64 acpi_table_ptr;
 typedef u64 acpi_io_address;
 typedef u64 acpi_physical_address;
-typedef u64 acpi_size;
 
-#define ALIGNED_ADDRESS_BOUNDARY        0x00000008	/* No hardware alignment support in IA64 */
-#define ACPI_USE_NATIVE_DIVIDE	/* Native 64-bit integer support */
 #define ACPI_MAX_PTR                    ACPI_UINT64_MAX
 #define ACPI_SIZE_MAX                   ACPI_UINT64_MAX
 
-#elif ACPI_MACHINE_WIDTH == 16
-
-/*! [Begin] no source code translation (keep the typedefs) */
+#define ALIGNED_ADDRESS_BOUNDARY        0x00000008
+#define ACPI_USE_NATIVE_DIVIDE	/* Has native 64-bit integer support */
 
 /*
- * 16-bit type definitions
+ * In the case of the Itanium Processor Family (IPF), the hardware does not
+ * support misaligned memory transfers. Set the MISALIGNMENT_NOT_SUPPORTED flag
+ * to indicate that special precautions must be taken to avoid alignment faults.
+ * (IA64 or ia64 is currently used by existing compilers to indicate IPF.)
+ *
+ * Note: Em64_t and other X86-64 processors support misaligned transfers,
+ * so there is no need to define this flag.
  */
-typedef unsigned char UINT8;
-typedef unsigned char BOOLEAN;
-typedef unsigned int UINT16;
-typedef long INT32;
-typedef int INT16;
-typedef unsigned long UINT32;
+#if defined (__IA64__) || defined (__ia64__)
+#define ACPI_MISALIGNMENT_NOT_SUPPORTED
+#endif
 
-struct {
-	UINT32 Lo;
-	UINT32 Hi;
-};
+/*******************************************************************************
+ *
+ * Types specific to 32-bit targets
+ *
+ ******************************************************************************/
+
+#elif ACPI_MACHINE_WIDTH == 32
+
+/*! [Begin] no source code translation (keep the typedefs as-is) */
+
+typedef unsigned int UINT32;
+typedef int INT32;
+
+/*! [End] no source code translation !*/
+
+typedef u32 acpi_native_uint;
+typedef s32 acpi_native_int;
+
+typedef u64 acpi_table_ptr;
+typedef u32 acpi_io_address;
+typedef u64 acpi_physical_address;
+
+#define ACPI_MAX_PTR                    ACPI_UINT32_MAX
+#define ACPI_SIZE_MAX                   ACPI_UINT32_MAX
+
+#define ALIGNED_ADDRESS_BOUNDARY        0x00000004
+
+/*******************************************************************************
+ *
+ * Types specific to 16-bit targets
+ *
+ ******************************************************************************/
+
+#elif ACPI_MACHINE_WIDTH == 16
+
+/*! [Begin] no source code translation (keep the typedefs as-is) */
+
+typedef unsigned long UINT32;
+typedef short INT16;
+typedef long INT32;
 
 /*! [End] no source code translation !*/
 
@@ -148,61 +219,84 @@
 typedef u32 acpi_table_ptr;
 typedef u32 acpi_io_address;
 typedef char *acpi_physical_address;
-typedef u16 acpi_size;
 
-#define ALIGNED_ADDRESS_BOUNDARY        0x00000002
-#define ACPI_MISALIGNED_TRANSFERS
-#define ACPI_USE_NATIVE_DIVIDE	/* No 64-bit integers, ok to use native divide */
 #define ACPI_MAX_PTR                    ACPI_UINT16_MAX
 #define ACPI_SIZE_MAX                   ACPI_UINT16_MAX
 
-/*
- * (16-bit only) internal integers must be 32-bits, so
- * 64-bit integers cannot be supported
- */
+#define ALIGNED_ADDRESS_BOUNDARY        0x00000002
+#define ACPI_USE_NATIVE_DIVIDE	/* No 64-bit integers, ok to use native divide */
+
+/* 64-bit integers cannot be supported */
+
 #define ACPI_NO_INTEGER64_SUPPORT
 
-#elif ACPI_MACHINE_WIDTH == 32
-
-/*! [Begin] no source code translation (keep the typedefs) */
-
-/*
- * 32-bit type definitions (default)
- */
-typedef unsigned char UINT8;
-typedef unsigned char BOOLEAN;
-typedef unsigned short UINT16;
-typedef int INT32;
-typedef unsigned int UINT32;
-typedef COMPILER_DEPENDENT_INT64 INT64;
-typedef COMPILER_DEPENDENT_UINT64 UINT64;
-
-/*! [End] no source code translation !*/
-
-typedef s32 acpi_native_int;
-typedef u32 acpi_native_uint;
-
-typedef u64 acpi_table_ptr;
-typedef u32 acpi_io_address;
-typedef u64 acpi_physical_address;
-typedef u32 acpi_size;
-
-#define ALIGNED_ADDRESS_BOUNDARY        0x00000004
-#define ACPI_MISALIGNED_TRANSFERS
-#define ACPI_MAX_PTR                    ACPI_UINT32_MAX
-#define ACPI_SIZE_MAX                   ACPI_UINT32_MAX
-
 #else
+
+/* ACPI_MACHINE_WIDTH must be either 64, 32, or 16 */
+
 #error unknown ACPI_MACHINE_WIDTH
 #endif
 
+/* Variable-width type, used instead of clib size_t */
+
+typedef acpi_native_uint acpi_size;
+
+/*******************************************************************************
+ *
+ * OS- or compiler-dependent types
+ *
+ * If the defaults below are not appropriate for the host system, they can
+ * be defined in the compiler-specific or OS-specific header, and this will
+ * take precedence.
+ *
+ ******************************************************************************/
+
+/* Use C99 uintptr_t for pointer casting if available, "void *" otherwise */
+
+#ifndef acpi_uintptr_t
+#define acpi_uintptr_t                          void *
+#endif
+
 /*
- * This type is used for bitfields in ACPI tables. The only type that is
- * even remotely portable is u8. Anything else is not portable, so
- * do not add any more bitfield types.
+ * If acpi_cache_t was not defined in the OS-dependent header,
+ * define it now. This is typically the case where the local cache
+ * manager implementation is to be used (ACPI_USE_LOCAL_CACHE)
  */
-typedef u8 UINT8_BIT;
-typedef acpi_native_uint ACPI_PTRDIFF;
+#ifndef acpi_cache_t
+#define acpi_cache_t                            struct acpi_memory_list
+#endif
+
+/*
+ * Allow the CPU flags word to be defined per-OS to simplify the use of the
+ * lock and unlock OSL interfaces.
+ */
+#ifndef acpi_cpu_flags
+#define acpi_cpu_flags                          acpi_native_uint
+#endif
+
+/*
+ * ACPI_PRINTF_LIKE is used to tag functions as "printf-like" because
+ * some compilers can catch printf format string problems
+ */
+#ifndef ACPI_PRINTF_LIKE
+#define ACPI_PRINTF_LIKE(c)
+#endif
+
+/*
+ * Some compilers complain about unused variables. Sometimes we don't want to
+ * use all the variables (for example, _acpi_module_name). This allows us
+ * to to tell the compiler in a per-variable manner that a variable
+ * is unused
+ */
+#ifndef ACPI_UNUSED_VAR
+#define ACPI_UNUSED_VAR
+#endif
+
+/*******************************************************************************
+ *
+ * Independent types
+ *
+ ******************************************************************************/
 
 /*
  * Pointer overlays to avoid lots of typecasting for
@@ -234,18 +328,8 @@
 #define ACPI_LOGMODE_PHYSPTR            ACPI_LOGICAL_ADDRESSING  | ACPI_PHYSICAL_POINTER
 #define ACPI_LOGMODE_LOGPTR             ACPI_LOGICAL_ADDRESSING  | ACPI_LOGICAL_POINTER
 
-/*
- * If acpi_cache_t was not defined in the OS-dependent header,
- * define it now. This is typically the case where the local cache
- * manager implementation is to be used (ACPI_USE_LOCAL_CACHE)
- */
-#ifndef acpi_cache_t
-#define acpi_cache_t                            struct acpi_memory_list
-#endif
+/* Logical defines and NULL */
 
-/*
- * Useful defines
- */
 #ifdef FALSE
 #undef FALSE
 #endif
@@ -261,12 +345,12 @@
 #endif
 
 /*
- * Local datatypes
+ * Mescellaneous types
  */
 typedef u32 acpi_status;	/* All ACPI Exceptions */
 typedef u32 acpi_name;		/* 4-byte ACPI name */
 typedef char *acpi_string;	/* Null terminated ASCII string */
-typedef void *acpi_handle;	/* Actually a ptr to an Node */
+typedef void *acpi_handle;	/* Actually a ptr to a NS Node */
 
 struct uint64_struct {
 	u32 lo;
@@ -323,7 +407,7 @@
 /*
  * Constants with special meanings
  */
-#define ACPI_ROOT_OBJECT                (acpi_handle) ACPI_PTR_ADD (char, NULL, ACPI_MAX_PTR)
+#define ACPI_ROOT_OBJECT                ACPI_ADD_PTR (acpi_handle, NULL, ACPI_MAX_PTR)
 
 /*
  * Initialization sequence
@@ -470,37 +554,6 @@
 #define ACPI_TYPE_NOT_FOUND             0xFF
 
 /*
- * Bitmapped ACPI types.  Used internally only
- */
-#define ACPI_BTYPE_ANY                  0x00000000
-#define ACPI_BTYPE_INTEGER              0x00000001
-#define ACPI_BTYPE_STRING               0x00000002
-#define ACPI_BTYPE_BUFFER               0x00000004
-#define ACPI_BTYPE_PACKAGE              0x00000008
-#define ACPI_BTYPE_FIELD_UNIT           0x00000010
-#define ACPI_BTYPE_DEVICE               0x00000020
-#define ACPI_BTYPE_EVENT                0x00000040
-#define ACPI_BTYPE_METHOD               0x00000080
-#define ACPI_BTYPE_MUTEX                0x00000100
-#define ACPI_BTYPE_REGION               0x00000200
-#define ACPI_BTYPE_POWER                0x00000400
-#define ACPI_BTYPE_PROCESSOR            0x00000800
-#define ACPI_BTYPE_THERMAL              0x00001000
-#define ACPI_BTYPE_BUFFER_FIELD         0x00002000
-#define ACPI_BTYPE_DDB_HANDLE           0x00004000
-#define ACPI_BTYPE_DEBUG_OBJECT         0x00008000
-#define ACPI_BTYPE_REFERENCE            0x00010000
-#define ACPI_BTYPE_RESOURCE             0x00020000
-
-#define ACPI_BTYPE_COMPUTE_DATA         (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER)
-
-#define ACPI_BTYPE_DATA                 (ACPI_BTYPE_COMPUTE_DATA  | ACPI_BTYPE_PACKAGE)
-#define ACPI_BTYPE_DATA_REFERENCE       (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE)
-#define ACPI_BTYPE_DEVICE_OBJECTS       (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR)
-#define ACPI_BTYPE_OBJECTS_AND_REFS     0x0001FFFF	/* ARG or LOCAL */
-#define ACPI_BTYPE_ALL_OBJECTS          0x0000FFFF
-
-/*
  * All I/O
  */
 #define ACPI_READ                       0
@@ -853,6 +906,14 @@
 #define ACPI_VALID_CID                  0x0010
 #define ACPI_VALID_SXDS                 0x0020
 
+/* Flags for _STA method */
+
+#define ACPI_STA_DEVICE_PRESENT         0x01
+#define ACPI_STA_DEVICE_ENABLED         0x02
+#define ACPI_STA_DEVICE_UI              0x04
+#define ACPI_STA_DEVICE_OK              0x08
+#define ACPI_STA_BATTERY_PRESENT        0x10
+
 #define ACPI_COMMON_OBJ_INFO \
 	acpi_object_type                    type;           /* ACPI object type */ \
 	acpi_name                           name	/* ACPI object Name */
@@ -895,6 +956,8 @@
 /*
  * Definitions for Resource Attributes
  */
+typedef u16 acpi_rs_length;	/* Resource Length field is fixed at 16 bits */
+typedef u32 acpi_rsdesc_size;	/* Max Resource Descriptor size is (length+3) = (64_k-1)+3 */
 
 /*
  *  Memory Attributes
@@ -916,7 +979,9 @@
 #define ACPI_ISA_ONLY_RANGES            (u8) 0x02
 #define ACPI_ENTIRE_RANGE               (ACPI_NON_ISA_ONLY_RANGES | ACPI_ISA_ONLY_RANGES)
 
-#define ACPI_SPARSE_TRANSLATION         (u8) 0x03
+/* Type of translation - 1=Sparse, 0=Dense */
+
+#define ACPI_SPARSE_TRANSLATION         (u8) 0x01
 
 /*
  *  IO Port Descriptor Decode
@@ -927,8 +992,8 @@
 /*
  *  IRQ Attributes
  */
-#define ACPI_EDGE_SENSITIVE             (u8) 0x00
-#define ACPI_LEVEL_SENSITIVE            (u8) 0x01
+#define ACPI_LEVEL_SENSITIVE            (u8) 0x00
+#define ACPI_EDGE_SENSITIVE             (u8) 0x01
 
 #define ACPI_ACTIVE_HIGH                (u8) 0x00
 #define ACPI_ACTIVE_LOW                 (u8) 0x01
@@ -975,27 +1040,45 @@
 #define ACPI_CONSUMER                   (u8) 0x01
 
 /*
+ * If possible, pack the following structures to byte alignment
+ */
+#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
+#pragma pack(1)
+#endif
+
+/* UUID data structures for use in vendor-defined resource descriptors */
+
+struct acpi_uuid {
+	u8 data[ACPI_UUID_LENGTH];
+};
+
+struct acpi_vendor_uuid {
+	u8 subtype;
+	u8 data[ACPI_UUID_LENGTH];
+};
+
+/*
  *  Structures used to describe device resources
  */
 struct acpi_resource_irq {
-	u32 edge_level;
-	u32 active_high_low;
-	u32 shared_exclusive;
-	u32 number_of_interrupts;
-	u32 interrupts[1];
+	u8 triggering;
+	u8 polarity;
+	u8 sharable;
+	u8 interrupt_count;
+	u8 interrupts[1];
 };
 
 struct acpi_resource_dma {
-	u32 type;
-	u32 bus_master;
-	u32 transfer;
-	u32 number_of_channels;
-	u32 channels[1];
+	u8 type;
+	u8 bus_master;
+	u8 transfer;
+	u8 channel_count;
+	u8 channels[1];
 };
 
-struct acpi_resource_start_dpf {
-	u32 compatibility_priority;
-	u32 performance_robustness;
+struct acpi_resource_start_dependent {
+	u8 compatibility_priority;
+	u8 performance_robustness;
 };
 
 /*
@@ -1004,179 +1087,217 @@
  */
 
 struct acpi_resource_io {
-	u32 io_decode;
-	u32 min_base_address;
-	u32 max_base_address;
-	u32 alignment;
-	u32 range_length;
+	u8 io_decode;
+	u8 alignment;
+	u8 address_length;
+	u16 minimum;
+	u16 maximum;
 };
 
 struct acpi_resource_fixed_io {
-	u32 base_address;
-	u32 range_length;
+	u16 address;
+	u8 address_length;
 };
 
 struct acpi_resource_vendor {
-	u32 length;
-	u8 reserved[1];
+	u16 byte_length;
+	u8 byte_data[1];
+};
+
+/* Vendor resource with UUID info (introduced in ACPI 3.0) */
+
+struct acpi_resource_vendor_typed {
+	u16 byte_length;
+	u8 uuid_subtype;
+	u8 uuid[ACPI_UUID_LENGTH];
+	u8 byte_data[1];
 };
 
 struct acpi_resource_end_tag {
 	u8 checksum;
 };
 
-struct acpi_resource_mem24 {
-	u32 read_write_attribute;
-	u32 min_base_address;
-	u32 max_base_address;
-	u32 alignment;
-	u32 range_length;
+struct acpi_resource_memory24 {
+	u8 write_protect;
+	u16 minimum;
+	u16 maximum;
+	u16 alignment;
+	u16 address_length;
 };
 
-struct acpi_resource_mem32 {
-	u32 read_write_attribute;
-	u32 min_base_address;
-	u32 max_base_address;
+struct acpi_resource_memory32 {
+	u8 write_protect;
+	u32 minimum;
+	u32 maximum;
 	u32 alignment;
-	u32 range_length;
+	u32 address_length;
 };
 
-struct acpi_resource_fixed_mem32 {
-	u32 read_write_attribute;
-	u32 range_base_address;
-	u32 range_length;
+struct acpi_resource_fixed_memory32 {
+	u8 write_protect;
+	u32 address;
+	u32 address_length;
 };
 
 struct acpi_memory_attribute {
-	u16 cache_attribute;
-	u16 read_write_attribute;
+	u8 write_protect;
+	u8 caching;
+	u8 range_type;
+	u8 translation;
 };
 
 struct acpi_io_attribute {
-	u16 range_attribute;
-	u16 translation_attribute;
-};
-
-struct acpi_bus_attribute {
-	u16 reserved1;
-	u16 reserved2;
+	u8 range_type;
+	u8 translation;
+	u8 translation_type;
+	u8 reserved1;
 };
 
 union acpi_resource_attribute {
-	struct acpi_memory_attribute memory;
+	struct acpi_memory_attribute mem;
 	struct acpi_io_attribute io;
-	struct acpi_bus_attribute bus;
+
+	/* Used for the *word_space macros */
+
+	u8 type_specific;
 };
 
 struct acpi_resource_source {
-	u32 index;
-	u32 string_length;
+	u8 index;
+	u16 string_length;
 	char *string_ptr;
 };
 
 /* Fields common to all address descriptors, 16/32/64 bit */
 
 #define ACPI_RESOURCE_ADDRESS_COMMON \
-	u32                                 resource_type; \
-	u32                                 producer_consumer; \
-	u32                                 decode; \
-	u32                                 min_address_fixed; \
-	u32                                 max_address_fixed; \
-	union acpi_resource_attribute       attribute;
+	u8                                  resource_type; \
+	u8                                  producer_consumer; \
+	u8                                  decode; \
+	u8                                  min_address_fixed; \
+	u8                                  max_address_fixed; \
+	union acpi_resource_attribute       info;
 
 struct acpi_resource_address {
 ACPI_RESOURCE_ADDRESS_COMMON};
 
 struct acpi_resource_address16 {
-	ACPI_RESOURCE_ADDRESS_COMMON u32 granularity;
-	u32 min_address_range;
-	u32 max_address_range;
-	u32 address_translation_offset;
-	u32 address_length;
+	ACPI_RESOURCE_ADDRESS_COMMON u16 granularity;
+	u16 minimum;
+	u16 maximum;
+	u16 translation_offset;
+	u16 address_length;
 	struct acpi_resource_source resource_source;
 };
 
 struct acpi_resource_address32 {
 	ACPI_RESOURCE_ADDRESS_COMMON u32 granularity;
-	u32 min_address_range;
-	u32 max_address_range;
-	u32 address_translation_offset;
+	u32 minimum;
+	u32 maximum;
+	u32 translation_offset;
 	u32 address_length;
 	struct acpi_resource_source resource_source;
 };
 
 struct acpi_resource_address64 {
 	ACPI_RESOURCE_ADDRESS_COMMON u64 granularity;
-	u64 min_address_range;
-	u64 max_address_range;
-	u64 address_translation_offset;
+	u64 minimum;
+	u64 maximum;
+	u64 translation_offset;
 	u64 address_length;
-	u64 type_specific_attributes;
 	struct acpi_resource_source resource_source;
 };
 
-struct acpi_resource_ext_irq {
-	u32 producer_consumer;
-	u32 edge_level;
-	u32 active_high_low;
-	u32 shared_exclusive;
-	u32 number_of_interrupts;
+struct acpi_resource_extended_address64 {
+	ACPI_RESOURCE_ADDRESS_COMMON u8 revision_iD;
+	u64 granularity;
+	u64 minimum;
+	u64 maximum;
+	u64 translation_offset;
+	u64 address_length;
+	u64 type_specific;
+};
+
+struct acpi_resource_extended_irq {
+	u8 producer_consumer;
+	u8 triggering;
+	u8 polarity;
+	u8 sharable;
+	u8 interrupt_count;
 	struct acpi_resource_source resource_source;
 	u32 interrupts[1];
 };
 
+struct acpi_resource_generic_register {
+	u8 space_id;
+	u8 bit_width;
+	u8 bit_offset;
+	u8 access_size;
+	u64 address;
+};
+
 /* ACPI_RESOURCE_TYPEs */
 
-#define ACPI_RSTYPE_IRQ                 0
-#define ACPI_RSTYPE_DMA                 1
-#define ACPI_RSTYPE_START_DPF           2
-#define ACPI_RSTYPE_END_DPF             3
-#define ACPI_RSTYPE_IO                  4
-#define ACPI_RSTYPE_FIXED_IO            5
-#define ACPI_RSTYPE_VENDOR              6
-#define ACPI_RSTYPE_END_TAG             7
-#define ACPI_RSTYPE_MEM24               8
-#define ACPI_RSTYPE_MEM32               9
-#define ACPI_RSTYPE_FIXED_MEM32         10
-#define ACPI_RSTYPE_ADDRESS16           11
-#define ACPI_RSTYPE_ADDRESS32           12
-#define ACPI_RSTYPE_ADDRESS64           13
-#define ACPI_RSTYPE_EXT_IRQ             14
-
-typedef u32 acpi_resource_type;
+#define ACPI_RESOURCE_TYPE_IRQ                  0
+#define ACPI_RESOURCE_TYPE_DMA                  1
+#define ACPI_RESOURCE_TYPE_START_DEPENDENT      2
+#define ACPI_RESOURCE_TYPE_END_DEPENDENT        3
+#define ACPI_RESOURCE_TYPE_IO                   4
+#define ACPI_RESOURCE_TYPE_FIXED_IO             5
+#define ACPI_RESOURCE_TYPE_VENDOR               6
+#define ACPI_RESOURCE_TYPE_END_TAG              7
+#define ACPI_RESOURCE_TYPE_MEMORY24             8
+#define ACPI_RESOURCE_TYPE_MEMORY32             9
+#define ACPI_RESOURCE_TYPE_FIXED_MEMORY32       10
+#define ACPI_RESOURCE_TYPE_ADDRESS16            11
+#define ACPI_RESOURCE_TYPE_ADDRESS32            12
+#define ACPI_RESOURCE_TYPE_ADDRESS64            13
+#define ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64   14	/* ACPI 3.0 */
+#define ACPI_RESOURCE_TYPE_EXTENDED_IRQ         15
+#define ACPI_RESOURCE_TYPE_GENERIC_REGISTER     16
+#define ACPI_RESOURCE_TYPE_MAX                  16
 
 union acpi_resource_data {
 	struct acpi_resource_irq irq;
 	struct acpi_resource_dma dma;
-	struct acpi_resource_start_dpf start_dpf;
+	struct acpi_resource_start_dependent start_dpf;
 	struct acpi_resource_io io;
 	struct acpi_resource_fixed_io fixed_io;
-	struct acpi_resource_vendor vendor_specific;
+	struct acpi_resource_vendor vendor;
+	struct acpi_resource_vendor_typed vendor_typed;
 	struct acpi_resource_end_tag end_tag;
-	struct acpi_resource_mem24 memory24;
-	struct acpi_resource_mem32 memory32;
-	struct acpi_resource_fixed_mem32 fixed_memory32;
-	struct acpi_resource_address address;	/* Common 16/32/64 address fields */
+	struct acpi_resource_memory24 memory24;
+	struct acpi_resource_memory32 memory32;
+	struct acpi_resource_fixed_memory32 fixed_memory32;
 	struct acpi_resource_address16 address16;
 	struct acpi_resource_address32 address32;
 	struct acpi_resource_address64 address64;
-	struct acpi_resource_ext_irq extended_irq;
+	struct acpi_resource_extended_address64 ext_address64;
+	struct acpi_resource_extended_irq extended_irq;
+	struct acpi_resource_generic_register generic_reg;
+
+	/* Common fields */
+
+	struct acpi_resource_address address;	/* Common 16/32/64 address fields */
 };
 
 struct acpi_resource {
-	acpi_resource_type id;
+	u32 type;
 	u32 length;
 	union acpi_resource_data data;
 };
 
-#define ACPI_RESOURCE_LENGTH                12
-#define ACPI_RESOURCE_LENGTH_NO_DATA        8	/* Id + Length fields */
+/* restore default alignment */
 
-#define ACPI_SIZEOF_RESOURCE(type)          (ACPI_RESOURCE_LENGTH_NO_DATA + sizeof (type))
+#pragma pack()
+
+#define ACPI_RS_SIZE_MIN                    12
+#define ACPI_RS_SIZE_NO_DATA                8	/* Id + Length fields */
+#define ACPI_RS_SIZE(type)                  (u32) (ACPI_RS_SIZE_NO_DATA + sizeof (type))
 
 #define ACPI_NEXT_RESOURCE(res)             (struct acpi_resource *)((u8 *) res + res->length)
 
-#ifdef ACPI_MISALIGNED_TRANSFERS
+#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
 #define ACPI_ALIGN_RESOURCE_SIZE(length)    (length)
 #else
 #define ACPI_ALIGN_RESOURCE_SIZE(length)    ACPI_ROUND_UP_TO_NATIVE_WORD(length)
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index c108645..0927765 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,6 +44,39 @@
 #ifndef _ACUTILS_H
 #define _ACUTILS_H
 
+extern const u8 acpi_gbl_resource_aml_sizes[];
+
+/* Strings used by the disassembler and debugger resource dump routines */
+
+#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
+
+extern const char *acpi_gbl_BMdecode[2];
+extern const char *acpi_gbl_config_decode[4];
+extern const char *acpi_gbl_consume_decode[2];
+extern const char *acpi_gbl_DECdecode[2];
+extern const char *acpi_gbl_HEdecode[2];
+extern const char *acpi_gbl_io_decode[2];
+extern const char *acpi_gbl_LLdecode[2];
+extern const char *acpi_gbl_max_decode[2];
+extern const char *acpi_gbl_MEMdecode[4];
+extern const char *acpi_gbl_min_decode[2];
+extern const char *acpi_gbl_MTPdecode[4];
+extern const char *acpi_gbl_RNGdecode[4];
+extern const char *acpi_gbl_RWdecode[2];
+extern const char *acpi_gbl_SHRdecode[2];
+extern const char *acpi_gbl_SIZdecode[4];
+extern const char *acpi_gbl_TRSdecode[2];
+extern const char *acpi_gbl_TTPdecode[2];
+extern const char *acpi_gbl_TYPdecode[4];
+#endif
+
+/* Types for Resource descriptor entries */
+
+#define ACPI_INVALID_RESOURCE           0
+#define ACPI_FIXED_LENGTH               1
+#define ACPI_VARIABLE_LENGTH            2
+#define ACPI_SMALL_VARIABLE_LENGTH      3
+
 typedef
 acpi_status(*acpi_pkg_callback) (u8 object_type,
 				 union acpi_operand_object * source_object,
@@ -159,7 +192,6 @@
 #define ACPI_IS_LOWER(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO))
 #define ACPI_IS_PRINT(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU))
 #define ACPI_IS_ALPHA(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP))
-#define ACPI_IS_ASCII(c)  ((c) < 0x80)
 
 #endif				/* ACPI_USE_SYSTEM_CLIBRARY */
 
@@ -243,21 +275,22 @@
 		 const char *function_name,
 		 char *module_name, u32 component_id, u8 * ptr);
 
-void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id);
-
-void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id);
-
-void
-acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id);
-
 void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id);
 
+void acpi_ut_report_error(char *module_name, u32 line_number);
+
+void acpi_ut_report_info(char *module_name, u32 line_number);
+
+void acpi_ut_report_warning(char *module_name, u32 line_number);
+
+/* Error and message reporting interfaces */
+
 void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_debug_print(u32 requested_debug_level,
 		    u32 line_number,
 		    const char *function_name,
 		    char *module_name,
-		    u32 component_id, char *format, ...) ACPI_PRINTF_LIKE_FUNC;
+		    u32 component_id, char *format, ...) ACPI_PRINTF_LIKE(6);
 
 void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_debug_print_raw(u32 requested_debug_level,
@@ -265,7 +298,24 @@
 			const char *function_name,
 			char *module_name,
 			u32 component_id,
-			char *format, ...) ACPI_PRINTF_LIKE_FUNC;
+			char *format, ...) ACPI_PRINTF_LIKE(6);
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_error(char *module_name,
+	      u32 line_number, char *format, ...) ACPI_PRINTF_LIKE(3);
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_exception(char *module_name,
+		  u32 line_number,
+		  acpi_status status, char *format, ...) ACPI_PRINTF_LIKE(4);
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_warning(char *module_name,
+		u32 line_number, char *format, ...) ACPI_PRINTF_LIKE(3);
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_info(char *module_name,
+	     u32 line_number, char *format, ...) ACPI_PRINTF_LIKE(3);
 
 /*
  * utdelete - Object deletion and reference counts
@@ -419,7 +469,19 @@
 
 #define ACPI_ANY_BASE        0
 
-u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc);
+acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index);
+
+u32 acpi_ut_get_descriptor_length(void *aml);
+
+u16 acpi_ut_get_resource_length(void *aml);
+
+u8 acpi_ut_get_resource_header_length(void *aml);
+
+u8 acpi_ut_get_resource_type(void *aml);
+
+acpi_status
+acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc,
+			     u8 ** end_tag);
 
 u8 acpi_ut_generate_checksum(u8 * buffer, u32 length);
 
diff --git a/include/acpi/amlcode.h b/include/acpi/amlcode.h
index 7fdf529..37964a5 100644
--- a/include/acpi/amlcode.h
+++ b/include/acpi/amlcode.h
@@ -7,7 +7,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h
index 051786e..fb47353 100644
--- a/include/acpi/amlresrc.h
+++ b/include/acpi/amlresrc.h
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -92,182 +92,168 @@
 	struct asl_resource_node *next;
 };
 
+/* Macros used to generate AML resource length fields */
+
+#define ACPI_AML_SIZE_LARGE(r)      (sizeof (r) - sizeof (struct aml_resource_large_header))
+#define ACPI_AML_SIZE_SMALL(r)      (sizeof (r) - sizeof (struct aml_resource_small_header))
+
 /*
  * Resource descriptors defined in the ACPI specification.
  *
  * Packing/alignment must be BYTE because these descriptors
- * are used to overlay the AML byte stream.
+ * are used to overlay the raw AML byte stream.
  */
 #pragma pack(1)
 
-struct asl_irq_format_desc {
-	u8 descriptor_type;
-	u16 irq_mask;
+/*
+ * SMALL descriptors
+ */
+#define AML_RESOURCE_SMALL_HEADER_COMMON \
+	u8                                  descriptor_type;
+
+struct aml_resource_small_header {
+AML_RESOURCE_SMALL_HEADER_COMMON};
+
+struct aml_resource_irq {
+	AML_RESOURCE_SMALL_HEADER_COMMON u16 irq_mask;
 	u8 flags;
 };
 
-struct asl_irq_noflags_desc {
-	u8 descriptor_type;
-	u16 irq_mask;
+struct aml_resource_irq_noflags {
+	AML_RESOURCE_SMALL_HEADER_COMMON u16 irq_mask;
 };
 
-struct asl_dma_format_desc {
-	u8 descriptor_type;
-	u8 dma_channel_mask;
+struct aml_resource_dma {
+	AML_RESOURCE_SMALL_HEADER_COMMON u8 dma_channel_mask;
 	u8 flags;
 };
 
-struct asl_start_dependent_desc {
-	u8 descriptor_type;
-	u8 flags;
+struct aml_resource_start_dependent {
+	AML_RESOURCE_SMALL_HEADER_COMMON u8 flags;
 };
 
-struct asl_start_dependent_noprio_desc {
-	u8 descriptor_type;
-};
+struct aml_resource_start_dependent_noprio {
+AML_RESOURCE_SMALL_HEADER_COMMON};
 
-struct asl_end_dependent_desc {
-	u8 descriptor_type;
-};
+struct aml_resource_end_dependent {
+AML_RESOURCE_SMALL_HEADER_COMMON};
 
-struct asl_io_port_desc {
-	u8 descriptor_type;
-	u8 information;
-	u16 address_min;
-	u16 address_max;
+struct aml_resource_io {
+	AML_RESOURCE_SMALL_HEADER_COMMON u8 flags;
+	u16 minimum;
+	u16 maximum;
 	u8 alignment;
-	u8 length;
+	u8 address_length;
 };
 
-struct asl_fixed_io_port_desc {
-	u8 descriptor_type;
-	u16 base_address;
-	u8 length;
+struct aml_resource_fixed_io {
+	AML_RESOURCE_SMALL_HEADER_COMMON u16 address;
+	u8 address_length;
 };
 
-struct asl_small_vendor_desc {
-	u8 descriptor_type;
-	u8 vendor_defined[7];
+struct aml_resource_vendor_small {
+AML_RESOURCE_SMALL_HEADER_COMMON};
+
+struct aml_resource_end_tag {
+	AML_RESOURCE_SMALL_HEADER_COMMON u8 checksum;
 };
 
-struct asl_end_tag_desc {
-	u8 descriptor_type;
-	u8 checksum;
-};
+/*
+ * LARGE descriptors
+ */
+#define AML_RESOURCE_LARGE_HEADER_COMMON \
+	u8                                  descriptor_type;\
+	u16                                 resource_length;
 
-/* LARGE descriptors */
+struct aml_resource_large_header {
+AML_RESOURCE_LARGE_HEADER_COMMON};
 
-struct asl_memory_24_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 information;
-	u16 address_min;
-	u16 address_max;
+struct aml_resource_memory24 {
+	AML_RESOURCE_LARGE_HEADER_COMMON u8 flags;
+	u16 minimum;
+	u16 maximum;
 	u16 alignment;
-	u16 range_length;
+	u16 address_length;
 };
 
-struct asl_large_vendor_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 vendor_defined[1];
-};
+struct aml_resource_vendor_large {
+AML_RESOURCE_LARGE_HEADER_COMMON};
 
-struct asl_memory_32_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 information;
-	u32 address_min;
-	u32 address_max;
+struct aml_resource_memory32 {
+	AML_RESOURCE_LARGE_HEADER_COMMON u8 flags;
+	u32 minimum;
+	u32 maximum;
 	u32 alignment;
-	u32 range_length;
+	u32 address_length;
 };
 
-struct asl_fixed_memory_32_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 information;
-	u32 base_address;
-	u32 range_length;
+struct aml_resource_fixed_memory32 {
+	AML_RESOURCE_LARGE_HEADER_COMMON u8 flags;
+	u32 address;
+	u32 address_length;
 };
 
-struct asl_extended_address_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 resource_type;
-	u8 flags;
-	u8 specific_flags;
-	u8 revision_iD;
+#define AML_RESOURCE_ADDRESS_COMMON \
+	u8                                  resource_type; \
+	u8                                  flags; \
+	u8                                  specific_flags;
+
+struct aml_resource_address {
+AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_ADDRESS_COMMON};
+
+struct aml_resource_extended_address64 {
+	AML_RESOURCE_LARGE_HEADER_COMMON
+	    AML_RESOURCE_ADDRESS_COMMON u8 revision_iD;
 	u8 reserved;
 	u64 granularity;
-	u64 address_min;
-	u64 address_max;
+	u64 minimum;
+	u64 maximum;
 	u64 translation_offset;
 	u64 address_length;
-	u64 type_specific_attributes;
-	u8 optional_fields[2];	/* Used for length calculation only */
+	u64 type_specific;
 };
 
-#define ASL_EXTENDED_ADDRESS_DESC_REVISION          1	/* ACPI 3.0 */
+#define AML_RESOURCE_EXTENDED_ADDRESS_REVISION          1	/* ACPI 3.0 */
 
-struct asl_qword_address_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 resource_type;
-	u8 flags;
-	u8 specific_flags;
-	u64 granularity;
-	u64 address_min;
-	u64 address_max;
+struct aml_resource_address64 {
+	AML_RESOURCE_LARGE_HEADER_COMMON
+	    AML_RESOURCE_ADDRESS_COMMON u64 granularity;
+	u64 minimum;
+	u64 maximum;
 	u64 translation_offset;
 	u64 address_length;
-	u8 optional_fields[2];
 };
 
-struct asl_dword_address_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 resource_type;
-	u8 flags;
-	u8 specific_flags;
-	u32 granularity;
-	u32 address_min;
-	u32 address_max;
+struct aml_resource_address32 {
+	AML_RESOURCE_LARGE_HEADER_COMMON
+	    AML_RESOURCE_ADDRESS_COMMON u32 granularity;
+	u32 minimum;
+	u32 maximum;
 	u32 translation_offset;
 	u32 address_length;
-	u8 optional_fields[2];
 };
 
-struct asl_word_address_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 resource_type;
-	u8 flags;
-	u8 specific_flags;
-	u16 granularity;
-	u16 address_min;
-	u16 address_max;
+struct aml_resource_address16 {
+	AML_RESOURCE_LARGE_HEADER_COMMON
+	    AML_RESOURCE_ADDRESS_COMMON u16 granularity;
+	u16 minimum;
+	u16 maximum;
 	u16 translation_offset;
 	u16 address_length;
-	u8 optional_fields[2];
 };
 
-struct asl_extended_xrupt_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 flags;
-	u8 table_length;
-	u32 interrupt_number[1];
+struct aml_resource_extended_irq {
+	AML_RESOURCE_LARGE_HEADER_COMMON u8 flags;
+	u8 interrupt_count;
+	u32 interrupts[1];
 	/* res_source_index, res_source optional fields follow */
 };
 
-struct asl_general_register_desc {
-	u8 descriptor_type;
-	u16 length;
-	u8 address_space_id;
+struct aml_resource_generic_register {
+	AML_RESOURCE_LARGE_HEADER_COMMON u8 address_space_id;
 	u8 bit_width;
 	u8 bit_offset;
-	u8 access_size;		/* ACPI 3.0, was Reserved */
+	u8 access_size;		/* ACPI 3.0, was previously Reserved */
 	u64 address;
 };
 
@@ -277,26 +263,39 @@
 
 /* Union of all resource descriptors, so we can allocate the worst case */
 
-union asl_resource_desc {
-	struct asl_irq_format_desc irq;
-	struct asl_dma_format_desc dma;
-	struct asl_start_dependent_desc std;
-	struct asl_end_dependent_desc end;
-	struct asl_io_port_desc iop;
-	struct asl_fixed_io_port_desc fio;
-	struct asl_small_vendor_desc smv;
-	struct asl_end_tag_desc et;
+union aml_resource {
+	/* Descriptor headers */
 
-	struct asl_memory_24_desc M24;
-	struct asl_large_vendor_desc lgv;
-	struct asl_memory_32_desc M32;
-	struct asl_fixed_memory_32_desc F32;
-	struct asl_qword_address_desc qas;
-	struct asl_dword_address_desc das;
-	struct asl_word_address_desc was;
-	struct asl_extended_address_desc eas;
-	struct asl_extended_xrupt_desc exx;
-	struct asl_general_register_desc grg;
+	struct aml_resource_small_header small_header;
+	struct aml_resource_large_header large_header;
+
+	/* Small resource descriptors */
+
+	struct aml_resource_irq irq;
+	struct aml_resource_dma dma;
+	struct aml_resource_start_dependent start_dpf;
+	struct aml_resource_end_dependent end_dpf;
+	struct aml_resource_io io;
+	struct aml_resource_fixed_io fixed_io;
+	struct aml_resource_vendor_small vendor_small;
+	struct aml_resource_end_tag end_tag;
+
+	/* Large resource descriptors */
+
+	struct aml_resource_memory24 memory24;
+	struct aml_resource_generic_register generic_reg;
+	struct aml_resource_vendor_large vendor_large;
+	struct aml_resource_memory32 memory32;
+	struct aml_resource_fixed_memory32 fixed_memory32;
+	struct aml_resource_address16 address16;
+	struct aml_resource_address32 address32;
+	struct aml_resource_address64 address64;
+	struct aml_resource_extended_address64 ext_address64;
+	struct aml_resource_extended_irq extended_irq;
+
+	/* Utility overlays */
+
+	struct aml_resource_address address;
 	u32 u32_item;
 	u16 u16_item;
 	u8 U8item;
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h
index 91f4a12..3fa81d5 100644
--- a/include/acpi/pdc_intel.h
+++ b/include/acpi/pdc_intel.h
@@ -15,9 +15,7 @@
 #define ACPI_PDC_C_C1_FFH		(0x0100)
 
 #define ACPI_PDC_EST_CAPABILITY_SMP	(ACPI_PDC_SMP_C1PT | \
-					 ACPI_PDC_C_C1_HALT)
-
-#define ACPI_PDC_EST_CAPABILITY_SMP_MSR	(ACPI_PDC_EST_CAPABILITY_SMP | \
+					 ACPI_PDC_C_C1_HALT | \
 					 ACPI_PDC_P_FFH)
 
 #define ACPI_PDC_C_CAPABILITY_SMP	(ACPI_PDC_SMP_C2C3 | \
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index 16609c1..223ec64 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -68,6 +68,7 @@
 #define ACPI_APPLICATION
 #define ACPI_DEBUGGER
 #define ACPI_DISASSEMBLER
+#define ACPI_MUTEX_DEBUG
 #endif
 
 #ifdef ACPI_ASL_COMPILER
@@ -148,6 +149,9 @@
 #elif defined(NETWARE)
 #include "acnetware.h"
 
+#elif defined(__sun)
+#include "acsolaris.h"
+
 #else
 
 /* All other environments */
@@ -157,13 +161,6 @@
 #define COMPILER_DEPENDENT_INT64   long long
 #define COMPILER_DEPENDENT_UINT64  unsigned long long
 
-/*
- * This macro is used to tag functions as "printf-like" because
- * some compilers can catch printf format string problems. MSVC
- * doesn't, so this is proprocessed away.
- */
-#define ACPI_PRINTF_LIKE_FUNC
-
 #endif
 
 /*
@@ -205,6 +202,8 @@
  *
  *****************************************************************************/
 
+#define ACPI_IS_ASCII(c)  ((c) < 0x80)
+
 #ifdef ACPI_USE_SYSTEM_CLIBRARY
 /*
  * Use the standard C library headers.
@@ -234,7 +233,7 @@
 #define ACPI_STRCAT(d,s)        (void) strcat((d), (s))
 #define ACPI_STRNCAT(d,s,n)     strncat((d), (s), (acpi_size)(n))
 #define ACPI_STRTOUL(d,s,n)     strtoul((d), (s), (acpi_size)(n))
-#define ACPI_MEMCMP(s1,s2,n)    memcmp((s1), (s2), (acpi_size)(n))
+#define ACPI_MEMCMP(s1,s2,n)    memcmp((const char *)(s1), (const char *)(s2), (acpi_size)(n))
 #define ACPI_MEMCPY(d,s,n)      (void) memcpy((d), (s), (acpi_size)(n))
 #define ACPI_MEMSET(d,s,n)      (void) memset((d), (s), (acpi_size)(n))
 
@@ -246,7 +245,6 @@
 #define ACPI_IS_UPPER(i)        isupper((int) (i))
 #define ACPI_IS_PRINT(i)        isprint((int) (i))
 #define ACPI_IS_ALPHA(i)        isalpha((int) (i))
-#define ACPI_IS_ASCII(i)        isascii((int) (i))
 
 #else
 
@@ -273,8 +271,8 @@
 /*
  * Storage alignment properties
  */
-#define  _AUPBND                (sizeof (acpi_native_int) - 1)
-#define  _ADNBND                (sizeof (acpi_native_int) - 1)
+#define  _AUPBND                (sizeof (acpi_native_uint) - 1)
+#define  _ADNBND                (sizeof (acpi_native_uint) - 1)
 
 /*
  * Variable argument list macro definitions
@@ -296,7 +294,7 @@
 #define ACPI_STRCAT(d,s)        (void) acpi_ut_strcat ((d), (s))
 #define ACPI_STRNCAT(d,s,n)     acpi_ut_strncat ((d), (s), (acpi_size)(n))
 #define ACPI_STRTOUL(d,s,n)     acpi_ut_strtoul ((d), (s), (acpi_size)(n))
-#define ACPI_MEMCMP(s1,s2,n)    acpi_ut_memcmp((s1), (s2), (acpi_size)(n))
+#define ACPI_MEMCMP(s1,s2,n)    acpi_ut_memcmp((const char *)(s1), (const char *)(s2), (acpi_size)(n))
 #define ACPI_MEMCPY(d,s,n)      (void) acpi_ut_memcpy ((d), (s), (acpi_size)(n))
 #define ACPI_MEMSET(d,v,n)      (void) acpi_ut_memset ((d), (v), (acpi_size)(n))
 #define ACPI_TOUPPER            acpi_ut_to_upper
diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h
index 4c0e0ba..da80933 100644
--- a/include/acpi/platform/acgcc.h
+++ b/include/acpi/platform/acgcc.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -48,12 +48,14 @@
 
 #define ACPI_GET_FUNCTION_NAME          __FUNCTION__
 
-/* This macro is used to tag functions as "printf-like" because
+/*
+ * This macro is used to tag functions as "printf-like" because
  * some compilers (like GCC) can catch printf format string problems.
  */
-#define ACPI_PRINTF_LIKE_FUNC __attribute__ ((__format__ (__printf__, 6, 7)))
+#define ACPI_PRINTF_LIKE(c) __attribute__ ((__format__ (__printf__, c, c+1)))
 
-/* Some compilers complain about unused variables. Sometimes we don't want to
+/*
+ * Some compilers complain about unused variables. Sometimes we don't want to
  * use all the variables (for example, _acpi_module_name). This allows us
  * to to tell the compiler warning in a per-variable manner that a variable
  * is unused.
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index c93e656..2e6d545 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -71,6 +71,10 @@
 #define acpi_cache_t	kmem_cache_t
 #endif
 
+/* Full namespace pathname length limit - arbitrary */
+
+#define ACPI_PATHNAME_MAX              256
+
 #else				/* !__KERNEL__ */
 
 #include <stdarg.h>
@@ -98,4 +102,6 @@
 
 #include "acgcc.h"
 
+#define acpi_cpu_flags unsigned long
+
 #endif				/* __ACLINUX_H__ */
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 7a00d50..badf027 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -62,9 +62,6 @@
 	u32 bm_activity;
 	int count;
 	struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
-
-	/* the _PDC objects passed by the driver, if any */
-	struct acpi_object_list *pdc;
 };
 
 /* Performance Management */
@@ -96,8 +93,6 @@
 	unsigned int state_count;
 	struct acpi_processor_px *states;
 
-	/* the _PDC objects passed by the driver, if any */
-	struct acpi_object_list *pdc;
 };
 
 /* Throttling Control */
@@ -151,6 +146,9 @@
 	struct acpi_processor_performance *performance;
 	struct acpi_processor_throttling throttling;
 	struct acpi_processor_limit limit;
+
+	/* the _PDC objects for this processor, if any */
+	struct acpi_object_list *pdc;
 };
 
 struct acpi_processor_errata {
@@ -178,22 +176,12 @@
 extern struct acpi_processor *processors[NR_CPUS];
 extern struct acpi_processor_errata errata;
 
-int acpi_processor_set_pdc(struct acpi_processor *pr,
-			   struct acpi_object_list *pdc_in);
+void arch_acpi_processor_init_pdc(struct acpi_processor *pr);
 
-#ifdef ARCH_HAS_POWER_PDC_INIT
-void acpi_processor_power_init_pdc(struct acpi_processor_power *pow,
-				   unsigned int cpu);
+#ifdef ARCH_HAS_POWER_INIT
 void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
 					unsigned int cpu);
 #else
-static inline void acpi_processor_power_init_pdc(struct acpi_processor_power
-						 *pow, unsigned int cpu)
-{
-	pow->pdc = NULL;
-	return;
-}
-
 static inline void acpi_processor_power_init_bm_check(struct
 						      acpi_processor_flags
 						      *flags, unsigned int cpu)
@@ -235,9 +223,6 @@
 /* in processor_throttling.c */
 int acpi_processor_get_throttling_info(struct acpi_processor *pr);
 int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
-ssize_t acpi_processor_write_throttling(struct file *file,
-					const char __user * buffer,
-					size_t count, loff_t * data);
 extern struct file_operations acpi_processor_throttling_fops;
 
 /* in processor_idle.c */
@@ -249,9 +234,6 @@
 
 /* in processor_thermal.c */
 int acpi_processor_get_limit_info(struct acpi_processor *pr);
-ssize_t acpi_processor_write_limit(struct file *file,
-				   const char __user * buffer,
-				   size_t count, loff_t * data);
 extern struct file_operations acpi_processor_limit_fops;
 
 #ifdef CONFIG_CPU_FREQ
diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h
index 9dc7256..62d0d66 100644
--- a/include/asm-alpha/dma-mapping.h
+++ b/include/asm-alpha/dma-mapping.h
@@ -30,6 +30,7 @@
 
 #else	/* no PCI - no IOMMU. */
 
+struct scatterlist;
 void *dma_alloc_coherent(struct device *dev, size_t size,
 			 dma_addr_t *dma_handle, gfp_t gfp);
 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h
index cc9c7e8..f3b7b1a 100644
--- a/include/asm-alpha/system.h
+++ b/include/asm-alpha/system.h
@@ -572,7 +572,7 @@
    if something tries to do an invalid cmpxchg().  */
 extern void __cmpxchg_called_with_bad_pointer(void);
 
-static inline unsigned long
+static __always_inline unsigned long
 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
 {
 	switch (size) {
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index 740c297..46a0402 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -38,8 +38,6 @@
 struct clk_functions {
 	int		(*clk_enable)(struct clk *clk);
 	void		(*clk_disable)(struct clk *clk);
-	int		(*clk_use)(struct clk *clk);
-	void		(*clk_unuse)(struct clk *clk);
 	long		(*clk_round_rate)(struct clk *clk, unsigned long rate);
 	int		(*clk_set_rate)(struct clk *clk, unsigned long rate);
 	int		(*clk_set_parent)(struct clk *clk, struct clk *parent);
diff --git a/include/asm-arm/arch-omap/io.h b/include/asm-arm/arch-omap/io.h
index f5bcc9a..b726acf 100644
--- a/include/asm-arm/arch-omap/io.h
+++ b/include/asm-arm/arch-omap/io.h
@@ -116,7 +116,11 @@
 					->offset[((vaddr)&4095)>>2]
 #define __REG32(paddr)		__REGV32(io_p2v(paddr))
 
-extern void omap_map_common_io(void);
+extern void omap1_map_common_io(void);
+extern void omap1_init_common_hw(void);
+
+extern void omap2_map_common_io(void);
+extern void omap2_init_common_hw(void);
 
 #else
 
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index dae138b..1409c5b 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -108,6 +108,7 @@
 #define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt (read / write) */
 #define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt (read / write) */
 
+#define DALGN		__REG(0x400000a0)  /* DMA Alignment Register */
 #define DINT		__REG(0x400000f0)  /* DMA Interrupt Register */
 
 #define DRCMR(n)	__REG2(0x40000100, (n)<<2)
@@ -1614,8 +1615,21 @@
 #define SSCR0_National	(0x2 << 4)	/* National Microwire */
 #define SSCR0_ECS	(1 << 6)	/* External clock select */
 #define SSCR0_SSE	(1 << 7)	/* Synchronous Serial Port Enable */
+#if defined(CONFIG_PXA25x)
 #define SSCR0_SCR	(0x0000ff00)	/* Serial Clock Rate (mask) */
 #define SSCR0_SerClkDiv(x) ((((x) - 2)/2) << 8) /* Divisor [2..512] */
+#elif defined(CONFIG_PXA27x)
+#define SSCR0_SCR	(0x000fff00)	/* Serial Clock Rate (mask) */
+#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */
+#define SSCR0_EDSS	(1 << 20)	/* Extended data size select */
+#define SSCR0_NCS	(1 << 21)	/* Network clock select */
+#define SSCR0_RIM	(1 << 22)	/* Receive FIFO overrrun interrupt mask */
+#define SSCR0_TUM	(1 << 23)	/* Transmit FIFO underrun interrupt mask */
+#define SSCR0_FRDC	(0x07000000)	/* Frame rate divider control (mask) */
+#define SSCR0_SlotsPerFrm(c) ((x) - 1)	/* Time slots per frame [1..8] */
+#define SSCR0_ADC	(1 << 30)	/* Audio clock select */
+#define SSCR0_MOD	(1 << 31)	/* Mode (normal or network) */
+#endif
 
 #define SSCR1_RIE	(1 << 0)	/* Receive FIFO Interrupt Enable */
 #define SSCR1_TIE	(1 << 1)	/* Transmit FIFO Interrupt Enable */
diff --git a/include/asm-arm/arch-s3c2410/debug-macro.S b/include/asm-arm/arch-s3c2410/debug-macro.S
index abfbe45..5f8223e 100644
--- a/include/asm-arm/arch-s3c2410/debug-macro.S
+++ b/include/asm-arm/arch-s3c2410/debug-macro.S
@@ -25,7 +25,7 @@
 		.macro addruart, rx
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1
-		ldreq	\rx, = S3C2410_PA_UART
+		ldreq	\rx, = S3C24XX_PA_UART
 		ldrne	\rx, = S3C24XX_VA_UART
 #if CONFIG_DEBUG_S3C2410_UART != 0
 		add	\rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C2410_UART)
@@ -44,7 +44,7 @@
 1003:
 		mrc	p15, 0, \rd, c1, c0
 		tst	\rd, #1
-		addeq	\rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
+		addeq	\rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
 		addne	\rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
 		bic	\rd, \rd, #0xff000
 		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
@@ -75,7 +75,7 @@
 1003:
 		mrc	p15, 0, \rd, c1, c0
 		tst	\rd, #1
-		addeq	\rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
+		addeq	\rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
 		addne	\rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
 		bic	\rd, \rd, #0xff000
 		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
diff --git a/include/asm-arm/arch-s3c2410/h1940-latch.h b/include/asm-arm/arch-s3c2410/h1940-latch.h
new file mode 100644
index 0000000..c580241
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/h1940-latch.h
@@ -0,0 +1,64 @@
+/* linux/include/asm-arm/arch-s3c2410/h1940-latch.h
+ *
+ * (c) 2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ *  iPAQ H1940 series - latch definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_H1940_LATCH_H
+#define __ASM_ARCH_H1940_LATCH_H
+
+
+#ifndef __ASSEMBLY__
+#define H1940_LATCH		((void __iomem *)0xF8000000)
+#else
+#define H1940_LATCH		0xF8000000
+#endif
+
+#define H1940_PA_LATCH		(S3C2410_CS2)
+
+/* SD layer latch */
+
+#define H1940_LATCH_SDQ1		(1<<16)
+#define H1940_LATCH_LCD_P1		(1<<17)
+#define H1940_LATCH_LCD_P2		(1<<18)
+#define H1940_LATCH_LCD_P3		(1<<19)
+#define H1940_LATCH_MAX1698_nSHUTDOWN	(1<<20)		/* LCD backlight */
+#define H1940_LATCH_LED_RED		(1<<21)
+#define H1940_LATCH_SDQ7		(1<<22)
+#define H1940_LATCH_USB_DP		(1<<23)
+
+/* CPU layer latch */
+
+#define H1940_LATCH_UDA_POWER		(1<<24)
+#define H1940_LATCH_AUDIO_POWER		(1<<25)
+#define H1940_LATCH_SM803_ENABLE	(1<<26)
+#define H1940_LATCH_LCD_P4		(1<<27)
+#define H1940_LATCH_CPUQ5		(1<<28)		/* untraced */
+#define H1940_LATCH_BLUETOOTH_POWER	(1<<29)		/* active high */
+#define H1940_LATCH_LED_GREEN		(1<<30)
+#define H1940_LATCH_LED_FLASH		(1<<31)
+
+/* default settings */
+
+#define H1940_LATCH_DEFAULT		\
+	H1940_LATCH_LCD_P4		| \
+	H1940_LATCH_SM803_ENABLE	| \
+	H1940_LATCH_SDQ1		| \
+	H1940_LATCH_LCD_P1		| \
+	H1940_LATCH_LCD_P2		| \
+	H1940_LATCH_LCD_P3		| \
+	H1940_LATCH_MAX1698_nSHUTDOWN   | \
+	H1940_LATCH_CPUQ5
+
+/* control functions */
+
+extern void h1940_latch_control(unsigned int clear, unsigned int set);
+
+#endif /* __ASM_ARCH_H1940_LATCH_H */
diff --git a/include/asm-arm/arch-s3c2410/hardware.h b/include/asm-arm/arch-s3c2410/hardware.h
index 1c9de29..a2330bf 100644
--- a/include/asm-arm/arch-s3c2410/hardware.h
+++ b/include/asm-arm/arch-s3c2410/hardware.h
@@ -17,6 +17,7 @@
  *  14-Sep-2004 BJD  Added misccr and getpin to gpio
  *  01-Oct-2004 BJD  Added the new gpio functions
  *  16-Oct-2004 BJD  Removed the clock variables
+ *  15-Jan-2006 LCVR Added s3c2400_gpio_getirq()
 */
 
 #ifndef __ASM_ARCH_HARDWARE_H
@@ -55,6 +56,12 @@
 
 extern int s3c2410_gpio_getirq(unsigned int pin);
 
+#ifdef CONFIG_CPU_S3C2400
+
+extern int s3c2400_gpio_getirq(unsigned int pin);
+
+#endif /* CONFIG_CPU_S3C2400 */
+
 /* s3c2410_gpio_irqfilter
  *
  * set the irq filtering on the given pin
diff --git a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h
index 1833ea5..c380d26 100644
--- a/include/asm-arm/arch-s3c2410/map.h
+++ b/include/asm-arm/arch-s3c2410/map.h
@@ -14,6 +14,7 @@
  *  06-Jan-2003 BJD   Linux 2.6.0 version, moved bast specifics out
  *  10-Feb-2005 BJD   Added CAMIF definition from guillaume.gourat@nexvision.tv
  *  10-Mar-2005 LCVR  Added support to S3C2400, changed {VA,SZ} names
+ *  15-Jan-2006 LCVR  Added S3C24XX_PA macros for common S3C24XX resources
 */
 
 #ifndef __ASM_ARCH_MAP_H
@@ -188,5 +189,42 @@
 
 #define S3C2400_SDRAM_PA    (S3C2400_CS6)
 
+/* Use a single interface for common resources between S3C24XX cpus */
+
+#ifdef CONFIG_CPU_S3C2400
+#define S3C24XX_PA_IRQ      S3C2400_PA_IRQ
+#define S3C24XX_PA_MEMCTRL  S3C2400_PA_MEMCTRL
+#define S3C24XX_PA_USBHOST  S3C2400_PA_USBHOST
+#define S3C24XX_PA_DMA      S3C2400_PA_DMA
+#define S3C24XX_PA_CLKPWR   S3C2400_PA_CLKPWR
+#define S3C24XX_PA_LCD      S3C2400_PA_LCD
+#define S3C24XX_PA_UART     S3C2400_PA_UART
+#define S3C24XX_PA_TIMER    S3C2400_PA_TIMER
+#define S3C24XX_PA_USBDEV   S3C2400_PA_USBDEV
+#define S3C24XX_PA_WATCHDOG S3C2400_PA_WATCHDOG
+#define S3C24XX_PA_IIC      S3C2400_PA_IIC
+#define S3C24XX_PA_IIS      S3C2400_PA_IIS
+#define S3C24XX_PA_GPIO     S3C2400_PA_GPIO
+#define S3C24XX_PA_RTC      S3C2400_PA_RTC
+#define S3C24XX_PA_ADC      S3C2400_PA_ADC
+#define S3C24XX_PA_SPI      S3C2400_PA_SPI
+#else
+#define S3C24XX_PA_IRQ      S3C2410_PA_IRQ
+#define S3C24XX_PA_MEMCTRL  S3C2410_PA_MEMCTRL
+#define S3C24XX_PA_USBHOST  S3C2410_PA_USBHOST
+#define S3C24XX_PA_DMA      S3C2410_PA_DMA
+#define S3C24XX_PA_CLKPWR   S3C2410_PA_CLKPWR
+#define S3C24XX_PA_LCD      S3C2410_PA_LCD
+#define S3C24XX_PA_UART     S3C2410_PA_UART
+#define S3C24XX_PA_TIMER    S3C2410_PA_TIMER
+#define S3C24XX_PA_USBDEV   S3C2410_PA_USBDEV
+#define S3C24XX_PA_WATCHDOG S3C2410_PA_WATCHDOG
+#define S3C24XX_PA_IIC      S3C2410_PA_IIC
+#define S3C24XX_PA_IIS      S3C2410_PA_IIS
+#define S3C24XX_PA_GPIO     S3C2410_PA_GPIO
+#define S3C24XX_PA_RTC      S3C2410_PA_RTC
+#define S3C24XX_PA_ADC      S3C2410_PA_ADC
+#define S3C24XX_PA_SPI      S3C2410_PA_SPI
+#endif
 
 #endif /* __ASM_ARCH_MAP_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index 7f1be48..9697f93 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -22,6 +22,7 @@
  *    28-Mar-2005    LCVR    Fixed definition of GPB10
  *    26-Oct-2005    BJD     Added generic configuration types
  *    27-Nov-2005    LCVR    Added definitions to S3C2400 registers
+ *    15-Jan-2006    LCVR    Written S3C24XX_GPIO_BASE() macro
 */
 
 
@@ -39,6 +40,27 @@
 #define S3C2410_GPIO_BANKG   (32*6)
 #define S3C2410_GPIO_BANKH   (32*7)
 
+#ifdef CONFIG_CPU_S3C2400
+#define S3C24XX_GPIO_BASE(x)  S3C2400_GPIO_BASE(x)
+#define S3C24XX_MISCCR        S3C2400_MISCCR
+#else
+#define S3C24XX_GPIO_BASE(x)  S3C2410_GPIO_BASE(x)
+#define S3C24XX_MISCCR        S3C2410_MISCCR
+#endif /* CONFIG_CPU_S3C2400 */
+
+
+/* S3C2400 doesn't have a 1:1 mapping to S3C2410 gpio base pins */
+
+#define S3C2400_BANKNUM(pin)     (((pin) & ~31) / 32)
+#define S3C2400_BASEA2B(pin)     ((((pin) & ~31) >> 2))
+#define S3C2400_BASEC2H(pin)     ((S3C2400_BANKNUM(pin) * 10) + \
+                                 (2 * (S3C2400_BANKNUM(pin)-2)))
+
+#define S3C2400_GPIO_BASE(pin)   (pin < S3C2410_GPIO_BANKC ? \
+                                 S3C2400_BASEA2B(pin)+S3C24XX_VA_GPIO : \
+                                 S3C2400_BASEC2H(pin)+S3C24XX_VA_GPIO)
+
+
 #define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
 #define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
 
diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
index ce1bbba..83b0125 100644
--- a/include/asm-arm/arch-s3c2410/regs-serial.h
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h
@@ -39,9 +39,9 @@
 #define S3C24XX_VA_UART1      (S3C24XX_VA_UART + 0x4000 )
 #define S3C24XX_VA_UART2      (S3C24XX_VA_UART + 0x8000 )
 
-#define S3C2410_PA_UART0      (S3C2410_PA_UART)
-#define S3C2410_PA_UART1      (S3C2410_PA_UART + 0x4000 )
-#define S3C2410_PA_UART2      (S3C2410_PA_UART + 0x8000 )
+#define S3C2410_PA_UART0      (S3C24XX_PA_UART)
+#define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
+#define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
 
 #define S3C2410_URXH	  (0x24)
 #define S3C2410_UTXH	  (0x20)
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
index ddd1578..4367ec0 100644
--- a/include/asm-arm/arch-s3c2410/uncompress.h
+++ b/include/asm-arm/arch-s3c2410/uncompress.h
@@ -35,13 +35,13 @@
 #undef S3C2410_GPIOREG
 #undef S3C2410_WDOGREG
 
-#define S3C2410_GPIOREG(x) ((S3C2410_PA_GPIO + (x)))
-#define S3C2410_WDOGREG(x) ((S3C2410_PA_WATCHDOG + (x)))
+#define S3C2410_GPIOREG(x) ((S3C24XX_PA_GPIO + (x)))
+#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
 
 /* how many bytes we allow into the FIFO at a time in FIFO mode */
 #define FIFO_MAX	 (14)
 
-#define uart_base S3C2410_PA_UART + (0x4000*CONFIG_S3C2410_LOWLEVEL_UART_PORT)
+#define uart_base S3C24XX_PA_UART + (0x4000*CONFIG_S3C2410_LOWLEVEL_UART_PORT)
 
 static __inline__ void
 uart_wr(unsigned int reg, unsigned int val)
diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
index d4256d5..747bdd3 100644
--- a/include/asm-arm/checksum.h
+++ b/include/asm-arm/checksum.h
@@ -77,7 +77,7 @@
 	mov	%0, %0, lsr #16"
 	: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
 	: "1" (iph), "2" (ihl)
-	: "cc");
+	: "cc", "memory");
 	return sum;
 }
 
diff --git a/include/asm-arm/mach/map.h b/include/asm-arm/mach/map.h
index 3351b77..e8ea67c 100644
--- a/include/asm-arm/mach/map.h
+++ b/include/asm-arm/mach/map.h
@@ -26,6 +26,7 @@
 #define MT_MEMORY		5
 #define MT_ROM			6
 #define MT_IXP2000_DEVICE	7
+#define MT_NONSHARED_DEVICE	8
 
 extern void create_memmap_holes(struct meminfo *);
 extern void memtable_init(struct meminfo *);
diff --git a/include/asm-arm/mutex.h b/include/asm-arm/mutex.h
index 6caa59f..cb29d84 100644
--- a/include/asm-arm/mutex.h
+++ b/include/asm-arm/mutex.h
@@ -23,72 +23,71 @@
  * simply bail out immediately through the slow path where the lock will be
  * reattempted until it succeeds.
  */
-#define __mutex_fastpath_lock(count, fail_fn)				\
-do {									\
-	int __ex_flag, __res;						\
-									\
-	typecheck(atomic_t *, count);					\
-	typecheck_fn(fastcall void (*)(atomic_t *), fail_fn);		\
-									\
-	__asm__ (							\
-		"ldrex	%0, [%2]	\n"				\
-		"sub	%0, %0, #1	\n"				\
-		"strex	%1, %0, [%2]	\n"				\
-									\
-		: "=&r" (__res), "=&r" (__ex_flag)			\
-		: "r" (&(count)->counter)				\
-		: "cc","memory" );					\
-									\
-	if (unlikely(__res || __ex_flag))				\
-		fail_fn(count);						\
-} while (0)
+static inline void
+__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+	int __ex_flag, __res;
 
-#define __mutex_fastpath_lock_retval(count, fail_fn)			\
-({									\
-	int __ex_flag, __res;						\
-									\
-	typecheck(atomic_t *, count);					\
-	typecheck_fn(fastcall int (*)(atomic_t *), fail_fn);		\
-									\
-	__asm__ (							\
-		"ldrex	%0, [%2]	\n"				\
-		"sub	%0, %0, #1	\n"				\
-		"strex	%1, %0, [%2]	\n"				\
-									\
-		: "=&r" (__res), "=&r" (__ex_flag)			\
-		: "r" (&(count)->counter)				\
-		: "cc","memory" );					\
-									\
-	__res |= __ex_flag;						\
-	if (unlikely(__res != 0))					\
-		__res = fail_fn(count);					\
-	__res;								\
-})
+	__asm__ (
+
+		"ldrex	%0, [%2]	\n\t"
+		"sub	%0, %0, #1	\n\t"
+		"strex	%1, %0, [%2]	"
+
+		: "=&r" (__res), "=&r" (__ex_flag)
+		: "r" (&(count)->counter)
+		: "cc","memory" );
+
+	__res |= __ex_flag;
+	if (unlikely(__res != 0))
+		fail_fn(count);
+}
+
+static inline int
+__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *))
+{
+	int __ex_flag, __res;
+
+	__asm__ (
+
+		"ldrex	%0, [%2]	\n\t"
+		"sub	%0, %0, #1	\n\t"
+		"strex	%1, %0, [%2]	"
+
+		: "=&r" (__res), "=&r" (__ex_flag)
+		: "r" (&(count)->counter)
+		: "cc","memory" );
+
+	__res |= __ex_flag;
+	if (unlikely(__res != 0))
+		__res = fail_fn(count);
+	return __res;
+}
 
 /*
  * Same trick is used for the unlock fast path. However the original value,
  * rather than the result, is used to test for success in order to have
  * better generated assembly.
  */
-#define __mutex_fastpath_unlock(count, fail_fn)				\
-do {									\
-	int __ex_flag, __res, __orig;					\
-									\
-	typecheck(atomic_t *, count);					\
-	typecheck_fn(fastcall void (*)(atomic_t *), fail_fn);		\
-									\
-	__asm__ (							\
-		"ldrex	%0, [%3]	\n"				\
-		"add	%1, %0, #1	\n"				\
-		"strex	%2, %1, [%3]	\n"				\
-									\
-		: "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag)	\
-		: "r" (&(count)->counter)				\
-		: "cc","memory" );					\
-									\
-	if (unlikely(__orig || __ex_flag))				\
-		fail_fn(count);						\
-} while (0)
+static inline void
+__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+	int __ex_flag, __res, __orig;
+
+	__asm__ (
+
+		"ldrex	%0, [%3]	\n\t"
+		"add	%1, %0, #1	\n\t"
+		"strex	%2, %1, [%3]	"
+
+		: "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag)
+		: "r" (&(count)->counter)
+		: "cc","memory" );
+
+	__orig |= __ex_flag;
+	if (unlikely(__orig != 0))
+		fail_fn(count);
+}
 
 /*
  * If the unlock was done on a contended lock, or if the unlock simply fails
@@ -110,12 +109,12 @@
 
 	__asm__ (
 
-		"1: ldrex	%0, [%3]	\n"
-		"subs		%1, %0, #1	\n"
-		"strexeq	%2, %1, [%3]	\n"
-		"movlt		%0, #0		\n"
-		"cmpeq		%2, #0		\n"
-		"bgt		1b		\n"
+		"1: ldrex	%0, [%3]	\n\t"
+		"subs		%1, %0, #1	\n\t"
+		"strexeq	%2, %1, [%3]	\n\t"
+		"movlt		%0, #0		\n\t"
+		"cmpeq		%2, #0		\n\t"
+		"bgt		1b		"
 
 		: "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag)
 		: "r" (&count->counter)
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 5a0d19b..70e00d0 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -168,6 +168,7 @@
 #define PMD_SECT_WB		(PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
 #define PMD_SECT_MINICACHE	(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
 #define PMD_SECT_WBWA		(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_NONSHARED_DEV	(PMD_SECT_TEX(2))
 
 /*
  *   - coarse table (not used)
diff --git a/include/asm-arm26/bitops.h b/include/asm-arm26/bitops.h
index 15cc6f2..d87f863 100644
--- a/include/asm-arm26/bitops.h
+++ b/include/asm-arm26/bitops.h
@@ -186,7 +186,7 @@
 extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
 extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
 extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_le(void * p, unsigned size);
+extern int _find_first_zero_bit_le(const unsigned long * p, unsigned size);
 extern int _find_next_zero_bit_le(void * p, int size, int offset);
 extern int _find_first_bit_le(const unsigned long *p, unsigned size);
 extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
@@ -326,7 +326,7 @@
 #define minix_test_and_clear_bit(nr,p)		\
 		__test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
 #define minix_find_first_zero_bit(p,sz)		\
-		_find_first_zero_bit_le(p,sz)
+		_find_first_zero_bit_le((unsigned long *)(p),sz)
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-arm26/hardirq.h b/include/asm-arm26/hardirq.h
index dc28daa..87c19d2 100644
--- a/include/asm-arm26/hardirq.h
+++ b/include/asm-arm26/hardirq.h
@@ -4,6 +4,7 @@
 #include <linux/config.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
+#include <asm/irq.h>
 
 typedef struct {
 	unsigned int __softirq_pending;
@@ -26,13 +27,6 @@
 
 extern asmlinkage void __do_softirq(void);
 
-#define irq_exit()                                                      \
-        do {                                                            \
-                preempt_count() -= IRQ_EXIT_OFFSET;                     \
-                if (!in_interrupt() && local_softirq_pending())         \
-                        __do_softirq();                                 \
-                preempt_enable_no_resched();                            \
-        } while (0)
 #endif
 
 
diff --git a/include/asm-arm26/posix_types.h b/include/asm-arm26/posix_types.h
index b88344a..f8d1eb4 100644
--- a/include/asm-arm26/posix_types.h
+++ b/include/asm-arm26/posix_types.h
@@ -44,6 +44,7 @@
 
 typedef unsigned short		__kernel_old_uid_t;
 typedef unsigned short		__kernel_old_gid_t;
+typedef unsigned short		__kernel_old_dev_t;
 
 #ifdef __GNUC__
 typedef long long		__kernel_loff_t;
diff --git a/include/asm-arm26/system.h b/include/asm-arm26/system.h
index ca4ccfc..7028849 100644
--- a/include/asm-arm26/system.h
+++ b/include/asm-arm26/system.h
@@ -98,9 +98,8 @@
  * spin_unlock_irq() and friends are implemented.  This avoids
  * us needlessly decrementing and incrementing the preempt count.
  */
-#define prepare_arch_switch(rq,next)	local_irq_enable()
-#define finish_arch_switch(rq,prev)	spin_unlock(&(rq)->lock)
-#define task_running(rq,p)		((rq)->curr == (p))
+#define prepare_arch_switch(next)	local_irq_enable()
+#define finish_arch_switch(prev)	spin_unlock(&(rq)->lock)
 
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h
index d3eb0f1..b7fef15 100644
--- a/include/asm-cris/bitops.h
+++ b/include/asm-cris/bitops.h
@@ -290,7 +290,7 @@
 	tmp = *p;
 	
  found_first:
-	tmp |= ~0UL >> size;
+	tmp |= ~0UL << size;
  found_middle:
 	return result + ffz(tmp);
 }
diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h
index 02be7b3..f686b51 100644
--- a/include/asm-frv/bitops.h
+++ b/include/asm-frv/bitops.h
@@ -209,7 +209,7 @@
 	tmp = *p;
 
 found_first:
-	tmp |= ~0UL >> size;
+	tmp |= ~0UL << size;
 found_middle:
 	return result + ffz(tmp);
 }
diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h
index a5576e0..ea426ab 100644
--- a/include/asm-frv/thread_info.h
+++ b/include/asm-frv/thread_info.h
@@ -129,6 +129,7 @@
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
+#define TIF_RESTORE_SIGMASK	6	/* restore signal mask in do_signal() */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* OOM killer killed process */
 
@@ -138,6 +139,7 @@
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_IRET		(1 << TIF_IRET)
+#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index cde376a..4d994d2 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -486,6 +486,7 @@
 /* #define __ARCH_WANT_SYS_SIGPENDING */
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #endif
 
 /*
diff --git a/include/asm-h8300/bitops.h b/include/asm-h8300/bitops.h
index c0411ec..ff7c2b7 100644
--- a/include/asm-h8300/bitops.h
+++ b/include/asm-h8300/bitops.h
@@ -227,7 +227,7 @@
 	tmp = *p;
 
 found_first:
-	tmp |= ~0UL >> size;
+	tmp |= ~0UL << size;
 found_middle:
 	return result + ffz(tmp);
 }
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
index df4ed32..55059ab 100644
--- a/include/asm-i386/acpi.h
+++ b/include/asm-i386/acpi.h
@@ -179,7 +179,7 @@
 
 extern u8 x86_acpiid_to_apicid[];
 
-#define ARCH_HAS_POWER_PDC_INIT	1
+#define ARCH_HAS_POWER_INIT	1
 
 #endif /*__KERNEL__*/
 
diff --git a/include/asm-i386/edac.h b/include/asm-i386/edac.h
new file mode 100644
index 0000000..3e7dd0a
--- /dev/null
+++ b/include/asm-i386/edac.h
@@ -0,0 +1,18 @@
+#ifndef ASM_EDAC_H
+#define ASM_EDAC_H
+
+/* ECC atomic, DMA, SMP and interrupt safe scrub function */
+
+static __inline__ void atomic_scrub(void *va, u32 size)
+{
+	unsigned long *virt_addr = va;
+	u32 i;
+
+	for (i = 0; i < size / 4; i++, virt_addr++)
+		/* Very carefully read and write to memory atomically
+		 * so we are interrupt, DMA and SMP safe.
+		 */
+		__asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr));
+}
+
+#endif
diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h
index e7a271d..44b9db8 100644
--- a/include/asm-i386/futex.h
+++ b/include/asm-i386/futex.h
@@ -61,7 +61,7 @@
 	if (op == FUTEX_OP_SET)
 		__futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
 	else {
-#if !defined(CONFIG_X86_BSWAP) && !defined(CONFIG_UML)
+#ifndef CONFIG_X86_BSWAP
 		if (boot_cpu_data.x86 == 3)
 			ret = -ENOSYS;
 		else
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 73296d9..997ca5d 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -110,10 +110,10 @@
 #endif /* __ASSEMBLY__ */
 
 #ifdef __ASSEMBLY__
-#define __PAGE_OFFSET		(0xC0000000)
+#define __PAGE_OFFSET		CONFIG_PAGE_OFFSET
 #define __PHYSICAL_START	CONFIG_PHYSICAL_START
 #else
-#define __PAGE_OFFSET		(0xC0000000UL)
+#define __PAGE_OFFSET		((unsigned long)CONFIG_PAGE_OFFSET)
 #define __PHYSICAL_START	((unsigned long)CONFIG_PHYSICAL_START)
 #endif
 #define __KERNEL_START		(__PAGE_OFFSET + __PHYSICAL_START)
diff --git a/include/asm-i386/signal.h b/include/asm-i386/signal.h
index 76524b4..026fd23 100644
--- a/include/asm-i386/signal.h
+++ b/include/asm-i386/signal.h
@@ -218,7 +218,6 @@
 }
 
 struct pt_regs;
-extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
 
 #define ptrace_signal_deliver(regs, cookie)		\
 	do {						\
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 36a92ed..399145a 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -507,7 +507,7 @@
 #define smp_rmb()	rmb()
 #define smp_wmb()	wmb()
 #define smp_read_barrier_depends()	read_barrier_depends()
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
 #else
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 2493e77..e20e995 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -140,6 +140,7 @@
 #define TIF_SYSCALL_EMU		6	/* syscall emulation active */
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 #define TIF_SECCOMP		8	/* secure computing */
+#define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
 
@@ -152,6 +153,7 @@
 #define _TIF_SYSCALL_EMU	(1<<TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 /* work to do on interrupt/exception return */
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index d7e19eb..af503a1 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -27,6 +27,15 @@
 #ifndef _ASM_I386_TOPOLOGY_H
 #define _ASM_I386_TOPOLOGY_H
 
+#ifdef CONFIG_SMP
+#define topology_physical_package_id(cpu)				\
+	(phys_proc_id[cpu] == BAD_APICID ? -1 : phys_proc_id[cpu])
+#define topology_core_id(cpu)						\
+	(cpu_core_id[cpu] == BAD_APICID ? 0 : cpu_core_id[cpu])
+#define topology_core_siblings(cpu)		(cpu_core_map[cpu])
+#define topology_thread_siblings(cpu)		(cpu_sibling_map[cpu])
+#endif
+
 #ifdef CONFIG_NUMA
 
 #include <asm/mpspec.h>
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index 481c3c0..dc81a55 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -300,8 +300,24 @@
 #define __NR_inotify_add_watch	292
 #define __NR_inotify_rm_watch	293
 #define __NR_migrate_pages	294
+#define __NR_openat		295
+#define __NR_mkdirat		296
+#define __NR_mknodat		297
+#define __NR_fchownat		298
+#define __NR_futimesat		299
+#define __NR_fstatat64		300
+#define __NR_unlinkat		301
+#define __NR_renameat		302
+#define __NR_linkat		303
+#define __NR_symlinkat		304
+#define __NR_readlinkat		305
+#define __NR_fchmodat		306
+#define __NR_faccessat		307
+#define __NR_pselect6		308
+#define __NR_ppoll		309
+#define __NR_unshare		310
 
-#define NR_syscalls 295
+#define NR_syscalls 311
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
@@ -417,6 +433,7 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #endif
 
 #ifdef __KERNEL_SYSCALLS__
diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
index e62b953..93f45c5 100644
--- a/include/asm-ia64/ide.h
+++ b/include/asm-ia64/ide.h
@@ -17,14 +17,6 @@
 
 #include <linux/irq.h>
 
-#ifndef MAX_HWIFS
-# ifdef CONFIG_PCI
-#define MAX_HWIFS	10
-# else
-#define MAX_HWIFS	6
-# endif
-#endif
-
 #define IDE_ARCH_OBSOLETE_DEFAULTS
 
 static inline int ide_default_irq(unsigned long base)
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
index 09b9902..23c8e1b 100644
--- a/include/asm-ia64/processor.h
+++ b/include/asm-ia64/processor.h
@@ -559,6 +559,23 @@
 
 #define cpu_relax()	ia64_hint(ia64_hint_pause)
 
+static inline int
+ia64_get_irr(unsigned int vector)
+{
+	unsigned int reg = vector / 64;
+	unsigned int bit = vector % 64;
+	u64 irr;
+
+	switch (reg) {
+	case 0: irr = ia64_getreg(_IA64_REG_CR_IRR0); break;
+	case 1: irr = ia64_getreg(_IA64_REG_CR_IRR1); break;
+	case 2: irr = ia64_getreg(_IA64_REG_CR_IRR2); break;
+	case 3: irr = ia64_getreg(_IA64_REG_CR_IRR3); break;
+	}
+
+	return test_bit(bit, &irr);
+}
+
 static inline void
 ia64_set_lrr0 (unsigned long val)
 {
diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
index 313cad0..0b210ab 100644
--- a/include/asm-ia64/sal.h
+++ b/include/asm-ia64/sal.h
@@ -658,15 +658,7 @@
 	return isrv.status;
 }
 
-/* Flush all the processor and platform level instruction and/or data caches */
-static inline s64
-ia64_sal_cache_flush (u64 cache_type)
-{
-	struct ia64_sal_retval isrv;
-	SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0);
-	return isrv.status;
-}
-
+extern s64 ia64_sal_cache_flush (u64 cache_type);
 
 /* Initialize all the processor and platform level instruction and data caches */
 static inline s64
diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h
index bb89062..f483eeb 100644
--- a/include/asm-ia64/semaphore.h
+++ b/include/asm-ia64/semaphore.h
@@ -61,7 +61,7 @@
 down (struct semaphore *sem)
 {
 	might_sleep();
-	if (atomic_dec_return(&sem->count) < 0)
+	if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
 		__down(sem);
 }
 
@@ -75,7 +75,7 @@
 	int ret = 0;
 
 	might_sleep();
-	if (atomic_dec_return(&sem->count) < 0)
+	if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
 		ret = __down_interruptible(sem);
 	return ret;
 }
@@ -85,7 +85,7 @@
 {
 	int ret = 0;
 
-	if (atomic_dec_return(&sem->count) < 0)
+	if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
 		ret = __down_trylock(sem);
 	return ret;
 }
@@ -93,7 +93,7 @@
 static inline void
 up (struct semaphore * sem)
 {
-	if (atomic_inc_return(&sem->count) <= 0)
+	if (ia64_fetchadd(1, &sem->count.counter, rel) <= -1)
 		__up(sem);
 }
 
diff --git a/include/asm-ia64/sn/bte.h b/include/asm-ia64/sn/bte.h
index f50da3d..01e5b41 100644
--- a/include/asm-ia64/sn/bte.h
+++ b/include/asm-ia64/sn/bte.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 
@@ -100,13 +100,28 @@
 #define BTE_LNSTAT_STORE(_bte, _x)					\
 			HUB_S(_bte->bte_base_addr, (_x))
 #define BTE_SRC_STORE(_bte, _x)						\
-			HUB_S(_bte->bte_source_addr, (_x))
+({									\
+		u64 __addr = ((_x) & ~AS_MASK);				\
+		if (is_shub2()) 					\
+			__addr = SH2_TIO_PHYS_TO_DMA(__addr);		\
+		HUB_S(_bte->bte_source_addr, __addr);			\
+})
 #define BTE_DEST_STORE(_bte, _x)					\
-			HUB_S(_bte->bte_destination_addr, (_x))
+({									\
+		u64 __addr = ((_x) & ~AS_MASK);				\
+		if (is_shub2()) 					\
+			__addr = SH2_TIO_PHYS_TO_DMA(__addr);		\
+		HUB_S(_bte->bte_destination_addr, __addr);		\
+})
 #define BTE_CTRL_STORE(_bte, _x)					\
 			HUB_S(_bte->bte_control_addr, (_x))
 #define BTE_NOTIF_STORE(_bte, _x)					\
-			HUB_S(_bte->bte_notify_addr, (_x))
+({									\
+		u64 __addr = ia64_tpa((_x) & ~AS_MASK);			\
+		if (is_shub2()) 					\
+			__addr = SH2_TIO_PHYS_TO_DMA(__addr);		\
+		HUB_S(_bte->bte_notify_addr, __addr);			\
+})
 
 #define BTE_START_TRANSFER(_bte, _len, _mode)				\
 	is_shub2() ? BTE_CTRL_STORE(_bte, IBLS_BUSY | (_mode << 24) | _len) \
diff --git a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h
index a343137..60a51a4 100644
--- a/include/asm-ia64/sn/intr.h
+++ b/include/asm-ia64/sn/intr.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 #ifndef _ASM_IA64_SN_INTR_H
@@ -11,26 +11,26 @@
 
 #include <linux/rcupdate.h>
 
-#define SGI_UART_VECTOR		(0xe9)
+#define SGI_UART_VECTOR		0xe9
 
 /* Reserved IRQs : Note, not to exceed IA64_SN2_FIRST_DEVICE_VECTOR */
-#define SGI_XPC_ACTIVATE                (0x30)
-#define SGI_II_ERROR                    (0x31)
-#define SGI_XBOW_ERROR                  (0x32)
-#define SGI_PCIASIC_ERROR               (0x33)
-#define SGI_ACPI_SCI_INT                (0x34)
-#define SGI_TIOCA_ERROR                 (0x35)
-#define SGI_TIO_ERROR                   (0x36)
-#define SGI_TIOCX_ERROR                 (0x37)
-#define SGI_MMTIMER_VECTOR              (0x38)
-#define SGI_XPC_NOTIFY                  (0xe7)
+#define SGI_XPC_ACTIVATE	0x30
+#define SGI_II_ERROR		0x31
+#define SGI_XBOW_ERROR		0x32
+#define SGI_PCIASIC_ERROR	0x33
+#define SGI_ACPI_SCI_INT	0x34
+#define SGI_TIOCA_ERROR		0x35
+#define SGI_TIO_ERROR		0x36
+#define SGI_TIOCX_ERROR		0x37
+#define SGI_MMTIMER_VECTOR	0x38
+#define SGI_XPC_NOTIFY		0xe7
 
-#define IA64_SN2_FIRST_DEVICE_VECTOR    (0x3c)
-#define IA64_SN2_LAST_DEVICE_VECTOR     (0xe6)
+#define IA64_SN2_FIRST_DEVICE_VECTOR	0x3c
+#define IA64_SN2_LAST_DEVICE_VECTOR	0xe6
 
-#define SN2_IRQ_RESERVED        (0x1)
-#define SN2_IRQ_CONNECTED       (0x2)
-#define SN2_IRQ_SHARED          (0x4)
+#define SN2_IRQ_RESERVED	0x1
+#define SN2_IRQ_CONNECTED	0x2
+#define SN2_IRQ_SHARED		0x4
 
 // The SN PROM irq struct
 struct sn_irq_info {
diff --git a/include/asm-ia64/sn/sn_feature_sets.h b/include/asm-ia64/sn/sn_feature_sets.h
index e68a808..9ca642c 100644
--- a/include/asm-ia64/sn/sn_feature_sets.h
+++ b/include/asm-ia64/sn/sn_feature_sets.h
@@ -8,7 +8,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2005 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2005-2006 Silicon Graphics, Inc.  All rights reserved.
  */
 
 
@@ -27,14 +27,12 @@
  * "false" for new features.
  *
  * Use:
- * 		if (sn_prom_feature_available(PRF_FEATURE_XXX))
+ * 		if (sn_prom_feature_available(PRF_XXX))
  * 			...
  */
 
-/*
- * Example: feature XXX
- */
-#define PRF_FEATURE_XXX		0
+#define PRF_PAL_CACHE_FLUSH_SAFE	0
+#define PRF_DEVICE_FLUSH_LIST		1
 
 
 
@@ -51,7 +49,7 @@
  *
  * By default, features are disabled unless explicitly enabled.
  */
-#define  OSF_MCA_SLV_TO_OS_INIT_SLV		0
-#define  OSF_FEAT_LOG_SBES			1
+#define  OSF_MCA_SLV_TO_OS_INIT_SLV	0
+#define  OSF_FEAT_LOG_SBES		1
 
 #endif /* _ASM_IA64_SN_FEATURE_SETS_H */
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
index 203945a..9bd2f9b 100644
--- a/include/asm-ia64/sn/xp.h
+++ b/include/asm-ia64/sn/xp.h
@@ -18,6 +18,7 @@
 
 #include <linux/cache.h>
 #include <linux/hardirq.h>
+#include <linux/mutex.h>
 #include <asm/sn/types.h>
 #include <asm/sn/bte.h>
 
@@ -359,7 +360,7 @@
  * the channel.
  */
 struct xpc_registration {
-	struct semaphore sema;
+	struct mutex mutex;
 	xpc_channel_func func;		/* function to call */
 	void *key;			/* pointer to user's key */
 	u16 nentries;			/* #of msg entries in local msg queue */
diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
index 87e9cd5..0c36928 100644
--- a/include/asm-ia64/sn/xpc.h
+++ b/include/asm-ia64/sn/xpc.h
@@ -19,6 +19,8 @@
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
 #include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/sn/bte.h>
@@ -335,8 +337,7 @@
  * and consumed by the intended recipient.
  */
 struct xpc_notify {
-	struct semaphore sema;		/* notify semaphore */
-	volatile u8 type;			/* type of notification */
+	volatile u8 type;		/* type of notification */
 
 	/* the following two fields are only used if type == XPC_N_CALL */
 	xpc_notify_func func;		/* user's notify function */
@@ -465,8 +466,8 @@
 	xpc_channel_func func;		/* user's channel function */
 	void *key;			/* pointer to user's key */
 
-	struct semaphore msg_to_pull_sema; /* next msg to pull serialization */
-	struct semaphore wdisconnect_sema; /* wait for channel disconnect */
+	struct mutex msg_to_pull_mutex;	/* next msg to pull serialization */
+	struct completion wdisconnect_wait; /* wait for channel disconnect */
 
 	struct xpc_openclose_args *local_openclose_args; /* args passed on */
 					/* opening or closing of channel */
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index 80c5a23..0625387 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -249,32 +249,7 @@
 # define switch_to(prev,next,last)	__switch_to(prev, next, last)
 #endif
 
-/*
- * On IA-64, we don't want to hold the runqueue's lock during the low-level context-switch,
- * because that could cause a deadlock.  Here is an example by Erich Focht:
- *
- * Example:
- * CPU#0:
- * schedule()
- *    -> spin_lock_irq(&rq->lock)
- *    -> context_switch()
- *       -> wrap_mmu_context()
- *          -> read_lock(&tasklist_lock)
- *
- * CPU#1:
- * sys_wait4() or release_task() or forget_original_parent()
- *    -> write_lock(&tasklist_lock)
- *    -> do_notify_parent()
- *       -> wake_up_parent()
- *          -> try_to_wake_up()
- *             -> spin_lock_irq(&parent_rq->lock)
- *
- * If the parent's rq happens to be on CPU#0, we'll wait for the rq->lock
- * of that CPU which will not be released, because there we wait for the
- * tasklist_lock to become available.
- */
 #define __ARCH_WANT_UNLOCKED_CTXSW
-
 #define ARCH_HAS_PREFETCH_SWITCH_STACK
 #define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
 
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index d8aae4d..3ee19df 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -18,6 +18,10 @@
 #include <asm/smp.h>
 
 #ifdef CONFIG_NUMA
+
+/* Nodes w/o CPUs are preferred for memory allocations, see build_zonelists */
+#define PENALTY_FOR_NODE_WITH_CPUS 255
+
 /*
  * Returns the number of the node containing CPU 'cpu'
  */
@@ -98,6 +102,13 @@
 
 #endif /* CONFIG_NUMA */
 
+#ifdef CONFIG_SMP
+#define topology_physical_package_id(cpu)	(cpu_data(cpu)->socket_id)
+#define topology_core_id(cpu)			(cpu_data(cpu)->core_id)
+#define topology_core_siblings(cpu)		(cpu_core_map[cpu])
+#define topology_thread_siblings(cpu)		(cpu_sibling_map[cpu])
+#endif
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_IA64_TOPOLOGY_H */
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 962f9bd..019956c 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -270,12 +270,27 @@
 #define __NR_inotify_add_watch		1278
 #define __NR_inotify_rm_watch		1279
 #define __NR_migrate_pages		1280
+#define __NR_openat			1281
+#define __NR_mkdirat			1282
+#define __NR_mknodat			1283
+#define __NR_fchownat			1284
+#define __NR_futimesat			1285
+#define __NR_newfstatat			1286
+#define __NR_unlinkat			1287
+#define __NR_renameat			1288
+#define __NR_linkat			1289
+#define __NR_symlinkat			1290
+#define __NR_readlinkat			1291
+#define __NR_fchmodat			1292
+#define __NR_faccessat			1293
+/* 1294, 1295 reserved for pselect/ppoll */
+#define __NR_unshare			1296
 
 #ifdef __KERNEL__
 
 #include <linux/config.h>
 
-#define NR_syscalls			270 /* length of syscall table */
+#define NR_syscalls			273 /* length of syscall table */
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 
diff --git a/include/asm-m68knommu/hardirq.h b/include/asm-m68knommu/hardirq.h
index e8659e7..476180f 100644
--- a/include/asm-m68knommu/hardirq.h
+++ b/include/asm-m68knommu/hardirq.h
@@ -4,6 +4,7 @@
 #include <linux/config.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
+#include <asm/irq.h>
 
 typedef struct {
 	unsigned int __softirq_pending;
diff --git a/include/asm-mips/abi.h b/include/asm-mips/abi.h
index 2e7e651..1ce0518 100644
--- a/include/asm-mips/abi.h
+++ b/include/asm-mips/abi.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2005 by Ralf Baechle
+ * Copyright (C) 2005, 06 by Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2005 MIPS Technologies, Inc.
  */
 #ifndef _ASM_ABI_H
@@ -13,7 +13,7 @@
 #include <asm/siginfo.h>
 
 struct mips_abi {
-	int (* const do_signal)(sigset_t *oldset, struct pt_regs *regs);
+	void (* const do_signal)(struct pt_regs *regs);
 	int (* const setup_frame)(struct k_sigaction * ka,
 	                          struct pt_regs *regs, int signr,
 	                          sigset_t *set);
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index 3b0c8aa..8e80205 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -644,44 +644,6 @@
 }
 
 /*
- * flz - find last zero in word.
- * @word: The word to search
- *
- * Returns 0..SZLONG-1
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-static inline unsigned long flz(unsigned long word)
-{
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
-	return __ilog2(~word);
-#else
-#ifdef CONFIG_32BIT
-	int r = 31, s;
-	word = ~word;
-	s = 16; if ((word & 0xffff0000)) s = 0; r -= s; word <<= s;
-	s = 8;  if ((word & 0xff000000)) s = 0; r -= s; word <<= s;
-	s = 4;  if ((word & 0xf0000000)) s = 0; r -= s; word <<= s;
-	s = 2;  if ((word & 0xc0000000)) s = 0; r -= s; word <<= s;
-	s = 1;  if ((word & 0x80000000)) s = 0; r -= s;
-
-	return r;
-#endif
-#ifdef CONFIG_64BIT
-	int r = 63, s;
-	word = ~word;
-	s = 32; if ((word & 0xffffffff00000000UL)) s = 0; r -= s; word <<= s;
-	s = 16; if ((word & 0xffff000000000000UL)) s = 0; r -= s; word <<= s;
-	s = 8;  if ((word & 0xff00000000000000UL)) s = 0; r -= s; word <<= s;
-	s = 4;  if ((word & 0xf000000000000000UL)) s = 0; r -= s; word <<= s;
-	s = 2;  if ((word & 0xc000000000000000UL)) s = 0; r -= s; word <<= s;
-	s = 1;  if ((word & 0x8000000000000000UL)) s = 0; r -= s;
-
-	return r;
-#endif
-#endif
-}
-
-/*
  * fls - find last bit set.
  * @word: The word to search
  *
@@ -690,11 +652,55 @@
  */
 static inline unsigned long fls(unsigned long word)
 {
+#ifdef CONFIG_32BIT
+#ifdef CONFIG_CPU_MIPS32
+	__asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
+
+	return 32 - word;
+#else
+	{
+	int r = 32, s;
+
 	if (word == 0)
 		return 0;
 
-	return flz(~word) + 1;
+	s = 16; if ((word & 0xffff0000)) s = 0; r -= s; word <<= s;
+	s = 8;  if ((word & 0xff000000)) s = 0; r -= s; word <<= s;
+	s = 4;  if ((word & 0xf0000000)) s = 0; r -= s; word <<= s;
+	s = 2;  if ((word & 0xc0000000)) s = 0; r -= s; word <<= s;
+	s = 1;  if ((word & 0x80000000)) s = 0; r -= s;
+
+	return r;
+	}
+#endif
+#endif /* CONFIG_32BIT */
+
+#ifdef CONFIG_64BIT
+#ifdef CONFIG_CPU_MIPS64
+
+	__asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
+
+	return 64 - word;
+#else
+	{
+	int r = 64, s;
+
+	if (word == 0)
+		return 0;
+
+	s = 32; if ((word & 0xffffffff00000000UL)) s = 0; r -= s; word <<= s;
+	s = 16; if ((word & 0xffff000000000000UL)) s = 0; r -= s; word <<= s;
+	s = 8;  if ((word & 0xff00000000000000UL)) s = 0; r -= s; word <<= s;
+	s = 4;  if ((word & 0xf000000000000000UL)) s = 0; r -= s; word <<= s;
+	s = 2;  if ((word & 0xc000000000000000UL)) s = 0; r -= s; word <<= s;
+	s = 1;  if ((word & 0x8000000000000000UL)) s = 0; r -= s;
+
+	return r;
+	}
+#endif
+#endif /* CONFIG_64BIT */
 }
+
 #define fls64(x)   generic_fls64(x)
 
 /*
diff --git a/include/asm-mips/byteorder.h b/include/asm-mips/byteorder.h
index d1fe9e5..584f812 100644
--- a/include/asm-mips/byteorder.h
+++ b/include/asm-mips/byteorder.h
@@ -8,10 +8,39 @@
 #ifndef _ASM_BYTEORDER_H
 #define _ASM_BYTEORDER_H
 
+#include <linux/config.h>
+#include <linux/compiler.h>
 #include <asm/types.h>
 
 #ifdef __GNUC__
 
+#ifdef CONFIG_CPU_MIPSR2
+
+static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
+{
+	__asm__(
+	"	wsbh	%0, %1			\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+#define __arch__swab16(x)	___arch__swab16(x)
+
+static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+{
+	__asm__(
+	"	wsbh	%0, %1			\n"
+	"	rotr	%0, %0, 16		\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+#define __arch__swab32(x)	___arch__swab32(x)
+
+#endif /* CONFIG_CPU_MIPSR2 */
+
 #if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
 #  define __BYTEORDER_HAS_U64__
 #  define __SWAB_64_THRU_32__
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index a18ba2e..aeae9fa 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -49,8 +49,7 @@
 
 extern void (*flush_icache_page)(struct vm_area_struct *vma,
 	struct page *page);
-extern void (*flush_icache_range)(unsigned long __user start,
-	unsigned long __user end);
+extern void (*flush_icache_range)(unsigned long start, unsigned long end);
 #define flush_cache_vmap(start, end)		flush_cache_all()
 #define flush_cache_vunmap(start, end)		flush_cache_all()
 
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index 2fc9063..6111a0c 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -100,7 +100,7 @@
 
 __asm__(
 	"	.macro	_ssnop					\n\t"
-	"	sll	$0, $2, 1				\n\t"
+	"	sll	$0, $0, 1				\n\t"
 	"	.endm						\n\t"
 	"							\n\t"
 	"	.macro	_ehb					\n\t"
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h
index abdf54e..7743487 100644
--- a/include/asm-mips/interrupt.h
+++ b/include/asm-mips/interrupt.h
@@ -47,6 +47,17 @@
  * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
  * no nops at all.
  */
+/*
+ * For TX49, operating only IE bit is not enough.
+ *
+ * If mfc0 $12 follows store and the mfc0 is last instruction of a
+ * page and fetching the next instruction causes TLB miss, the result
+ * of the mfc0 might wrongly contain EXL bit.
+ *
+ * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
+ *
+ * Workaround: mask EXL bit of the result or place a nop before mfc0.
+ */
 __asm__ (
 	"	.macro	local_irq_disable\n"
 	"	.set	push						\n"
@@ -55,8 +66,8 @@
 	"	di							\n"
 #else
 	"	mfc0	$1,$12						\n"
-	"	ori	$1,1						\n"
-	"	xori	$1,1						\n"
+	"	ori	$1,0x1f						\n"
+	"	xori	$1,0x1f						\n"
 	"	.set	noreorder					\n"
 	"	mtc0	$1,$12						\n"
 #endif
@@ -96,8 +107,8 @@
 	"	andi	\\result, 1					\n"
 #else
 	"	mfc0	\\result, $12					\n"
-	"	ori	$1, \\result, 1					\n"
-	"	xori	$1, 1						\n"
+	"	ori	$1, \\result, 0x1f				\n"
+	"	xori	$1, 0x1f					\n"
 	"	.set	noreorder					\n"
 	"	mtc0	$1, $12						\n"
 #endif
@@ -114,6 +125,7 @@
 
 __asm__ (
 	"	.macro	local_irq_restore flags				\n"
+	"	.set	push						\n"
 	"	.set	noreorder					\n"
 	"	.set	noat						\n"
 #if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
@@ -135,14 +147,13 @@
 #else
 	"	mfc0	$1, $12						\n"
 	"	andi	\\flags, 1					\n"
-	"	ori	$1, 1						\n"
-	"	xori	$1, 1						\n"
+	"	ori	$1, 0x1f					\n"
+	"	xori	$1, 0x1f					\n"
 	"	or	\\flags, $1					\n"
 	"	mtc0	\\flags, $12					\n"
 #endif
 	"	irq_disable_hazard					\n"
-	"	.set	at						\n"
-	"	.set	reorder						\n"
+	"	.set	pop						\n"
 	"	.endm							\n");
 
 #define local_irq_restore(flags)					\
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index d426857..5a4c8a5 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
-#include <asm/bug.h>
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
@@ -57,38 +56,38 @@
  * variations of functions: non-prefixed ones that preserve the value
  * and prefixed ones that preserve byte addresses.  The latters are
  * typically used for moving raw data between a peripheral and memory (cf.
- * string I/O functions), hence the "mem_" prefix.
+ * string I/O functions), hence the "__mem_" prefix.
  */
 #if defined(CONFIG_SWAP_IO_SPACE)
 
 # define ioswabb(x)		(x)
-# define mem_ioswabb(x)		(x)
+# define __mem_ioswabb(x)	(x)
 # ifdef CONFIG_SGI_IP22
 /*
  * IP22 seems braindead enough to swap 16bits values in hardware, but
  * not 32bits.  Go figure... Can't tell without documentation.
  */
 #  define ioswabw(x)		(x)
-#  define mem_ioswabw(x)	le16_to_cpu(x)
+#  define __mem_ioswabw(x)	le16_to_cpu(x)
 # else
 #  define ioswabw(x)		le16_to_cpu(x)
-#  define mem_ioswabw(x)	(x)
+#  define __mem_ioswabw(x)	(x)
 # endif
 # define ioswabl(x)		le32_to_cpu(x)
-# define mem_ioswabl(x)		(x)
+# define __mem_ioswabl(x)	(x)
 # define ioswabq(x)		le64_to_cpu(x)
-# define mem_ioswabq(x)		(x)
+# define __mem_ioswabq(x)	(x)
 
 #else
 
 # define ioswabb(x)		(x)
-# define mem_ioswabb(x)		(x)
+# define __mem_ioswabb(x)	(x)
 # define ioswabw(x)		(x)
-# define mem_ioswabw(x)		cpu_to_le16(x)
+# define __mem_ioswabw(x)	cpu_to_le16(x)
 # define ioswabl(x)		(x)
-# define mem_ioswabl(x)		cpu_to_le32(x)
+# define __mem_ioswabl(x)	cpu_to_le32(x)
 # define ioswabq(x)		(x)
-# define mem_ioswabq(x)		cpu_to_le32(x)
+# define __mem_ioswabq(x)	cpu_to_le32(x)
 
 #endif
 
@@ -343,7 +342,7 @@
 		BUG();							\
 }									\
 									\
-static inline type pfx##read##bwlq(volatile void __iomem *mem)		\
+static inline type pfx##read##bwlq(const volatile void __iomem *mem)	\
 {									\
 	volatile type *__mem;						\
 	type __val;							\
@@ -418,7 +417,7 @@
 									\
 __BUILD_MEMORY_PFX(__raw_, bwlq, type)					\
 __BUILD_MEMORY_PFX(, bwlq, type)					\
-__BUILD_MEMORY_PFX(mem_, bwlq, type)					\
+__BUILD_MEMORY_PFX(__mem_, bwlq, type)					\
 
 BUILDIO_MEM(b, u8)
 BUILDIO_MEM(w, u16)
@@ -431,7 +430,7 @@
 
 #define BUILDIO_IOPORT(bwlq, type)					\
 	__BUILD_IOPORT_PFX(, bwlq, type)				\
-	__BUILD_IOPORT_PFX(mem_, bwlq, type)
+	__BUILD_IOPORT_PFX(__mem_, bwlq, type)
 
 BUILDIO_IOPORT(b, u8)
 BUILDIO_IOPORT(w, u16)
@@ -465,7 +464,7 @@
 	const volatile type *__addr = addr;				\
 									\
 	while (count--) {						\
-		mem_write##bwlq(*__addr, mem);				\
+		__mem_write##bwlq(*__addr, mem);			\
 		__addr++;						\
 	}								\
 }									\
@@ -476,7 +475,7 @@
 	volatile type *__addr = addr;					\
 									\
 	while (count--) {						\
-		*__addr = mem_read##bwlq(mem);				\
+		*__addr = __mem_read##bwlq(mem);			\
 		__addr++;						\
 	}								\
 }
@@ -489,7 +488,7 @@
 	const volatile type *__addr = addr;				\
 									\
 	while (count--) {						\
-		mem_out##bwlq(*__addr, port);				\
+		__mem_out##bwlq(*__addr, port);				\
 		__addr++;						\
 	}								\
 }									\
@@ -500,7 +499,7 @@
 	volatile type *__addr = addr;					\
 									\
 	while (count--) {						\
-		*__addr = mem_in##bwlq(port);				\
+		*__addr = __mem_in##bwlq(port);				\
 		__addr++;						\
 	}								\
 }
diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
index 8e1d7ed..4686e17 100644
--- a/include/asm-mips/mach-au1x00/au1000.h
+++ b/include/asm-mips/mach-au1x00/au1000.h
@@ -1198,7 +1198,11 @@
 
 /* UARTS 0-3 */
 #define UART_BASE                 UART0_ADDR
+#ifdef	CONFIG_SOC_AU1200
+#define UART_DEBUG_BASE           UART1_ADDR
+#else
 #define UART_DEBUG_BASE           UART3_ADDR
+#endif
 
 #define UART_RX		0	/* Receive buffer */
 #define UART_TX		4	/* Transmit buffer */
diff --git a/include/asm-mips/cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h
similarity index 100%
rename from include/asm-mips/cobalt/cobalt.h
rename to include/asm-mips/mach-cobalt/cobalt.h
diff --git a/include/asm-mips/mach-cobalt/cpu-feature-overrides.h b/include/asm-mips/mach-cobalt/cpu-feature-overrides.h
new file mode 100644
index 0000000..ace8c5e
--- /dev/null
+++ b/include/asm-mips/mach-cobalt/cpu-feature-overrides.h
@@ -0,0 +1,56 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef __ASM_COBALT_CPU_FEATURE_OVERRIDES_H
+#define __ASM_COBALT_CPU_FEATURE_OVERRIDES_H
+
+#include <linux/config.h>
+
+#define cpu_has_tlb		1
+#define cpu_has_4kex		1
+#define cpu_has_3k_cache	0
+#define cpu_has_4k_cache	1
+#define cpu_has_tx39_cache	0
+#define cpu_has_sb1_cache	0
+#define cpu_has_fpu		1
+#define cpu_has_32fpr		1
+#define cpu_has_counter		1
+#define cpu_has_watch		0
+#define cpu_has_divec		1
+#define cpu_has_vce		0
+#define cpu_has_cache_cdex_p	0
+#define cpu_has_cache_cdex_s	0
+#define cpu_has_prefetch	0
+#define cpu_has_mcheck		0
+#define cpu_has_ejtag		0
+
+#define cpu_has_subset_pcaches	0
+#define cpu_dcache_line_size()	32
+#define cpu_icache_line_size()	32
+#define cpu_scache_line_size()	0
+
+#ifdef CONFIG_64BIT
+#define cpu_has_llsc            0
+#else
+#define cpu_has_llsc            1
+#endif
+
+#define cpu_has_mips16		0
+#define cpu_has_mdmx		0
+#define cpu_has_mips3d		0
+#define cpu_has_smartmips	0
+#define cpu_has_vtag_icache	0
+#define cpu_has_ic_fills_f_dc	0
+#define cpu_icache_snoops_remote_store	0
+#define cpu_has_dsp		0
+
+#define cpu_has_mips32r1	0
+#define cpu_has_mips32r2	0
+#define cpu_has_mips64r1	0
+#define cpu_has_mips64r2	0
+
+#endif /* __ASM_COBALT_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/cobalt/mach-gt64120.h b/include/asm-mips/mach-cobalt/mach-gt64120.h
similarity index 100%
rename from include/asm-mips/cobalt/mach-gt64120.h
rename to include/asm-mips/mach-cobalt/mach-gt64120.h
diff --git a/include/asm-mips/mach-ip32/cpu-feature-overrides.h b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
index b80c307..36070b5 100644
--- a/include/asm-mips/mach-ip32/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
@@ -18,7 +18,7 @@
  * so, for 64bit IP32 kernel we just don't use ll/sc.
  * This does not affect luserland.
  */
-#if defined(CONFIG_CPU_R5000) && defined(CONFIG_64BIT)
+#if (defined(CONFIG_CPU_R5000) || defined(CONFIG_CPU_NEVADA)) && defined(CONFIG_64BIT)
 #define cpu_has_llsc		0
 #else
 #define cpu_has_llsc		1
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
index a5ea9d8..cc53196 100644
--- a/include/asm-mips/r4kcache.h
+++ b/include/asm-mips/r4kcache.h
@@ -166,123 +166,6 @@
 		: "r" (base),						\
 		  "i" (op));
 
-static inline void blast_dcache16(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.dcache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
-	unsigned long ws_end = current_cpu_data.dcache.ways <<
-	                       current_cpu_data.dcache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x200)
-			cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
-}
-
-static inline void blast_dcache16_page(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-
-	do {
-		cache16_unroll32(start,Hit_Writeback_Inv_D);
-		start += 0x200;
-	} while (start < end);
-}
-
-static inline void blast_dcache16_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
-	unsigned long ws_end = current_cpu_data.dcache.ways <<
-	                       current_cpu_data.dcache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x200)
-			cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
-}
-
-static inline void blast_icache16(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.icache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
-	unsigned long ws_end = current_cpu_data.icache.ways <<
-	                       current_cpu_data.icache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x200)
-			cache16_unroll32(addr|ws,Index_Invalidate_I);
-}
-
-static inline void blast_icache16_page(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-
-	do {
-		cache16_unroll32(start,Hit_Invalidate_I);
-		start += 0x200;
-	} while (start < end);
-}
-
-static inline void blast_icache16_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
-	unsigned long ws_end = current_cpu_data.icache.ways <<
-	                       current_cpu_data.icache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x200)
-			cache16_unroll32(addr|ws,Index_Invalidate_I);
-}
-
-static inline void blast_scache16(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.scache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
-	unsigned long ws_end = current_cpu_data.scache.ways <<
-	                       current_cpu_data.scache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x200)
-			cache16_unroll32(addr|ws,Index_Writeback_Inv_SD);
-}
-
-static inline void blast_scache16_page(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = page + PAGE_SIZE;
-
-	do {
-		cache16_unroll32(start,Hit_Writeback_Inv_SD);
-		start += 0x200;
-	} while (start < end);
-}
-
-static inline void blast_scache16_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
-	unsigned long ws_end = current_cpu_data.scache.ways <<
-	                       current_cpu_data.scache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x200)
-			cache16_unroll32(addr|ws,Index_Writeback_Inv_SD);
-}
-
 #define cache32_unroll32(base,op)					\
 	__asm__ __volatile__(						\
 	"	.set push					\n"	\
@@ -309,123 +192,6 @@
 		: "r" (base),						\
 		  "i" (op));
 
-static inline void blast_dcache32(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.dcache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
-	unsigned long ws_end = current_cpu_data.dcache.ways <<
-	                       current_cpu_data.dcache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x400)
-			cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
-}
-
-static inline void blast_dcache32_page(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-
-	do {
-		cache32_unroll32(start,Hit_Writeback_Inv_D);
-		start += 0x400;
-	} while (start < end);
-}
-
-static inline void blast_dcache32_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
-	unsigned long ws_end = current_cpu_data.dcache.ways <<
-	                       current_cpu_data.dcache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x400)
-			cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
-}
-
-static inline void blast_icache32(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.icache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
-	unsigned long ws_end = current_cpu_data.icache.ways <<
-	                       current_cpu_data.icache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x400)
-			cache32_unroll32(addr|ws,Index_Invalidate_I);
-}
-
-static inline void blast_icache32_page(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-
-	do {
-		cache32_unroll32(start,Hit_Invalidate_I);
-		start += 0x400;
-	} while (start < end);
-}
-
-static inline void blast_icache32_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
-	unsigned long ws_end = current_cpu_data.icache.ways <<
-	                       current_cpu_data.icache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x400)
-			cache32_unroll32(addr|ws,Index_Invalidate_I);
-}
-
-static inline void blast_scache32(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.scache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
-	unsigned long ws_end = current_cpu_data.scache.ways <<
-	                       current_cpu_data.scache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x400)
-			cache32_unroll32(addr|ws,Index_Writeback_Inv_SD);
-}
-
-static inline void blast_scache32_page(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = page + PAGE_SIZE;
-
-	do {
-		cache32_unroll32(start,Hit_Writeback_Inv_SD);
-		start += 0x400;
-	} while (start < end);
-}
-
-static inline void blast_scache32_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
-	unsigned long ws_end = current_cpu_data.scache.ways <<
-	                       current_cpu_data.scache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x400)
-			cache32_unroll32(addr|ws,Index_Writeback_Inv_SD);
-}
-
 #define cache64_unroll32(base,op)					\
 	__asm__ __volatile__(						\
 	"	.set push					\n"	\
@@ -452,84 +218,6 @@
 		: "r" (base),						\
 		  "i" (op));
 
-static inline void blast_icache64(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.icache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
-	unsigned long ws_end = current_cpu_data.icache.ways <<
-	                       current_cpu_data.icache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x800)
-			cache64_unroll32(addr|ws,Index_Invalidate_I);
-}
-
-static inline void blast_icache64_page(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-
-	do {
-		cache64_unroll32(start,Hit_Invalidate_I);
-		start += 0x800;
-	} while (start < end);
-}
-
-static inline void blast_icache64_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
-	unsigned long ws_end = current_cpu_data.icache.ways <<
-	                       current_cpu_data.icache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x800)
-			cache64_unroll32(addr|ws,Index_Invalidate_I);
-}
-
-static inline void blast_scache64(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.scache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
-	unsigned long ws_end = current_cpu_data.scache.ways <<
-	                       current_cpu_data.scache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x800)
-			cache64_unroll32(addr|ws,Index_Writeback_Inv_SD);
-}
-
-static inline void blast_scache64_page(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = page + PAGE_SIZE;
-
-	do {
-		cache64_unroll32(start,Hit_Writeback_Inv_SD);
-		start += 0x800;
-	} while (start < end);
-}
-
-static inline void blast_scache64_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
-	unsigned long ws_end = current_cpu_data.scache.ways <<
-	                       current_cpu_data.scache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x800)
-			cache64_unroll32(addr|ws,Index_Writeback_Inv_SD);
-}
-
 #define cache128_unroll32(base,op)					\
 	__asm__ __volatile__(						\
 	"	.set push					\n"	\
@@ -556,43 +244,55 @@
 		: "r" (base),						\
 		  "i" (op));
 
-static inline void blast_scache128(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.scache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
-	unsigned long ws_end = current_cpu_data.scache.ways <<
-	                       current_cpu_data.scache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x1000)
-			cache128_unroll32(addr|ws,Index_Writeback_Inv_SD);
+/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
+#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
+static inline void blast_##pfx##cache##lsize(void)			\
+{									\
+	unsigned long start = INDEX_BASE;				\
+	unsigned long end = start + current_cpu_data.desc.waysize;	\
+	unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit;	\
+	unsigned long ws_end = current_cpu_data.desc.ways <<		\
+	                       current_cpu_data.desc.waybit;		\
+	unsigned long ws, addr;						\
+									\
+	for (ws = 0; ws < ws_end; ws += ws_inc)				\
+		for (addr = start; addr < end; addr += lsize * 32)	\
+			cache##lsize##_unroll32(addr|ws,indexop);	\
+}									\
+									\
+static inline void blast_##pfx##cache##lsize##_page(unsigned long page)	\
+{									\
+	unsigned long start = page;					\
+	unsigned long end = page + PAGE_SIZE;				\
+									\
+	do {								\
+		cache##lsize##_unroll32(start,hitop);			\
+		start += lsize * 32;					\
+	} while (start < end);						\
+}									\
+									\
+static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
+{									\
+	unsigned long start = page;					\
+	unsigned long end = start + PAGE_SIZE;				\
+	unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit;	\
+	unsigned long ws_end = current_cpu_data.desc.ways <<		\
+	                       current_cpu_data.desc.waybit;		\
+	unsigned long ws, addr;						\
+									\
+	for (ws = 0; ws < ws_end; ws += ws_inc)				\
+		for (addr = start; addr < end; addr += lsize * 32)	\
+			cache##lsize##_unroll32(addr|ws,indexop);	\
 }
 
-static inline void blast_scache128_page(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = page + PAGE_SIZE;
-
-	do {
-		cache128_unroll32(start,Hit_Writeback_Inv_SD);
-		start += 0x1000;
-	} while (start < end);
-}
-
-static inline void blast_scache128_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
-	unsigned long ws_end = current_cpu_data.scache.ways <<
-	                       current_cpu_data.scache.waybit;
-	unsigned long ws, addr;
-
-	for (ws = 0; ws < ws_end; ws += ws_inc)
-		for (addr = start; addr < end; addr += 0x1000)
-			cache128_unroll32(addr|ws,Index_Writeback_Inv_SD);
-}
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
 
 #endif /* _ASM_R4KCACHE_H */
diff --git a/include/asm-mips/reboot.h b/include/asm-mips/reboot.h
index 2f10ebc..e48c0bf 100644
--- a/include/asm-mips/reboot.h
+++ b/include/asm-mips/reboot.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1997, 1999, 2001 by Ralf Baechle
+ * Copyright (C) 1997, 1999, 2001, 06 by Ralf Baechle
  * Copyright (C) 2001 MIPS Technologies, Inc.
  */
 #ifndef _ASM_REBOOT_H
@@ -11,6 +11,5 @@
 
 extern void (*_machine_restart)(char *command);
 extern void (*_machine_halt)(void);
-extern void (*_machine_power_off)(void);
 
 #endif /* _ASM_REBOOT_H */
diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h
index 5a06f6d..907da60 100644
--- a/include/asm-mips/string.h
+++ b/include/asm-mips/string.h
@@ -141,26 +141,4 @@
 #define __HAVE_ARCH_MEMMOVE
 extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
 
-#ifdef CONFIG_32BIT
-#define __HAVE_ARCH_MEMSCAN
-static __inline__ void *memscan(void *__addr, int __c, size_t __size)
-{
-	char *__end = (char *)__addr + __size;
-	unsigned char __uc = (unsigned char) __c;
-
-	__asm__(".set\tpush\n\t"
-		".set\tnoat\n\t"
-		".set\treorder\n\t"
-		"1:\tbeq\t%0,%1,2f\n\t"
-		"addiu\t%0,1\n\t"
-		"lbu\t$1,-1(%0)\n\t"
-		"bne\t$1,%z4,1b\n"
-		"2:\t.set\tpop"
-		: "=r" (__addr), "=r" (__end)
-		: "0" (__addr), "1" (__end), "Jr" (__uc));
-
-	return __addr;
-}
-#endif /* CONFIG_32BIT */
-
 #endif /* _ASM_STRING_H */
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index 1612b3f..fa193f8 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -114,6 +114,7 @@
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SYSCALL_AUDIT	4	/* syscall auditing active */
 #define TIF_SECCOMP		5	/* secure computing */
+#define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
@@ -125,6 +126,7 @@
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
diff --git a/include/asm-mips/tx4927/tx4927.h b/include/asm-mips/tx4927/tx4927.h
index 3bb7f00..de85bd2 100644
--- a/include/asm-mips/tx4927/tx4927.h
+++ b/include/asm-mips/tx4927/tx4927.h
@@ -2,7 +2,7 @@
  * Author: MontaVista Software, Inc.
  *         source@mvista.com
  *
- * Copyright 2001-2002 MontaVista Software Inc.
+ * Copyright 2001-2006 MontaVista Software Inc.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License as published by the
@@ -30,10 +30,10 @@
 #include <asm/tx4927/tx4927_mips.h>
 
 /*
- This register naming came from the intergrate cpu/controoler name TX4927
+ This register naming came from the integrated CPU/controller name TX4927
  followed by the device name from table 4.2.2 on page 4-3 and then followed
  by the register name from table 4.2.3 on pages 4-4 to 4-8.  The manaul
- used is "TMPR4927BT Preliminary Rev 0.1 20.Jul.2001".
+ used was "TMPR4927BT Preliminary Rev 0.1 20.Jul.2001".
  */
 
 #define TX4927_SIO_0_BASE
@@ -251,8 +251,8 @@
 
 /* TX4927 Timer 0 (32-bit registers) */
 #define TX4927_TMR0_BASE                0xf000
-#define TX4927_TMR0_TMTCR0              0xf004
-#define TX4927_TMR0_TMTISR0             0xf008
+#define TX4927_TMR0_TMTCR0              0xf000
+#define TX4927_TMR0_TMTISR0             0xf004
 #define TX4927_TMR0_TMCPRA0             0xf008
 #define TX4927_TMR0_TMCPRB0             0xf00c
 #define TX4927_TMR0_TMITMR0             0xf010
@@ -264,8 +264,8 @@
 
 /* TX4927 Timer 1 (32-bit registers) */
 #define TX4927_TMR1_BASE                0xf100
-#define TX4927_TMR1_TMTCR1              0xf104
-#define TX4927_TMR1_TMTISR1             0xf108
+#define TX4927_TMR1_TMTCR1              0xf100
+#define TX4927_TMR1_TMTISR1             0xf104
 #define TX4927_TMR1_TMCPRA1             0xf108
 #define TX4927_TMR1_TMCPRB1             0xf10c
 #define TX4927_TMR1_TMITMR1             0xf110
@@ -277,13 +277,12 @@
 
 /* TX4927 Timer 2 (32-bit registers) */
 #define TX4927_TMR2_BASE                0xf200
-#define TX4927_TMR2_TMTCR2              0xf104
-#define TX4927_TMR2_TMTISR2             0xf208
+#define TX4927_TMR2_TMTCR2              0xf200
+#define TX4927_TMR2_TMTISR2             0xf204
 #define TX4927_TMR2_TMCPRA2             0xf208
-#define TX4927_TMR2_TMCPRB2             0xf20c
 #define TX4927_TMR2_TMITMR2             0xf210
 #define TX4927_TMR2_TMCCDR2             0xf220
-#define TX4927_TMR2_TMPGMR2             0xf230
+#define TX4927_TMR2_TMWTMR2             0xf240
 #define TX4927_TMR2_TMTRR2              0xf2f0
 #define TX4927_TMR2_LIMIT               0xf2ff
 
diff --git a/include/asm-mips/tx4927/tx4927_pci.h b/include/asm-mips/tx4927/tx4927_pci.h
index 165f6b8..66c0646 100644
--- a/include/asm-mips/tx4927/tx4927_pci.h
+++ b/include/asm-mips/tx4927/tx4927_pci.h
@@ -253,6 +253,16 @@
 #define TX4927_CCFG_PCIDIVMODE_5        0x00001000
 #define TX4927_CCFG_PCIDIVMODE_6        0x00001800
 
+#define TX4937_CCFG_PCIDIVMODE_MASK	0x00001c00
+#define TX4937_CCFG_PCIDIVMODE_8	0x00000000
+#define TX4937_CCFG_PCIDIVMODE_4	0x00000400
+#define TX4937_CCFG_PCIDIVMODE_9 	0x00000800
+#define TX4937_CCFG_PCIDIVMODE_4_5	0x00000c00
+#define TX4937_CCFG_PCIDIVMODE_10	0x00001000
+#define TX4937_CCFG_PCIDIVMODE_5	0x00001400
+#define TX4937_CCFG_PCIDIVMODE_11	0x00001800
+#define TX4937_CCFG_PCIDIVMODE_5_5	0x00001c00
+
 /* PCFG : Pin Configuration */
 #define TX4927_PCFG_PCICLKEN_ALL        0x003f0000
 #define TX4927_PCFG_PCICLKEN(ch)        (0x00010000<<(ch))
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 41bb96b..91d813a 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -202,49 +202,49 @@
  * Yuck.  We need two variants, one for 64bit operation and one
  * for 32 bit mode and old iron.
  */
-#ifdef __mips64
-#define __GET_USER_DW(ptr) __get_user_asm("ld", ptr)
-#else
-#define __GET_USER_DW(ptr) __get_user_asm_ll32(ptr)
+#ifdef CONFIG_32BIT
+#define __GET_USER_DW(val, ptr) __get_user_asm_ll32(val, ptr)
 #endif
+#ifdef CONFIG_64BIT
+#define __GET_USER_DW(val, ptr) __get_user_asm(val, "ld", ptr)
+#endif
+
+extern void __get_user_unknown(void);
+
+#define __get_user_common(val, size, ptr)				\
+do {									\
+	switch (size) {							\
+	case 1: __get_user_asm(val, "lb", ptr); break;			\
+	case 2: __get_user_asm(val, "lh", ptr); break;			\
+	case 4: __get_user_asm(val, "lw", ptr); break;			\
+	case 8: __GET_USER_DW(val, ptr); break;				\
+	default: __get_user_unknown(); break;				\
+	}								\
+} while (0)
 
 #define __get_user_nocheck(x,ptr,size)					\
 ({									\
-	__typeof(*(ptr)) __gu_val =  (__typeof(*(ptr))) 0;		\
-	long __gu_err = 0;						\
+	long __gu_err;							\
 									\
-	switch (size) {							\
-	case 1: __get_user_asm("lb", ptr); break;			\
-	case 2: __get_user_asm("lh", ptr); break;			\
-	case 4: __get_user_asm("lw", ptr); break;			\
-	case 8: __GET_USER_DW(ptr); break;				\
-	default: __get_user_unknown(); break;				\
-	}								\
-	(x) = (__typeof__(*(ptr))) __gu_val;				\
+	__get_user_common((x), size, ptr);				\
 	__gu_err;							\
 })
 
 #define __get_user_check(x,ptr,size)					\
 ({									\
-	const __typeof__(*(ptr)) __user * __gu_addr = (ptr);		\
-	__typeof__(*(ptr)) __gu_val = 0;				\
 	long __gu_err = -EFAULT;					\
+	const void __user * __gu_ptr = (ptr);				\
 									\
-	if (likely(access_ok(VERIFY_READ,  __gu_addr, size))) {		\
-		switch (size) {						\
-		case 1: __get_user_asm("lb", __gu_addr); break;		\
-		case 2: __get_user_asm("lh", __gu_addr); break;		\
-		case 4: __get_user_asm("lw", __gu_addr); break;		\
-		case 8: __GET_USER_DW(__gu_addr); break;		\
-		default: __get_user_unknown(); break;			\
-		}							\
-	}								\
-	(x) = (__typeof__(*(ptr))) __gu_val;				\
+	if (likely(access_ok(VERIFY_READ,  __gu_ptr, size)))		\
+		__get_user_common((x), size, __gu_ptr);			\
+									\
 	__gu_err;							\
 })
 
-#define __get_user_asm(insn, addr)					\
+#define __get_user_asm(val, insn, addr)					\
 {									\
+	long __gu_tmp;							\
+									\
 	__asm__ __volatile__(						\
 	"1:	" insn "	%1, %3				\n"	\
 	"2:							\n"	\
@@ -255,14 +255,16 @@
 	"	.section __ex_table,\"a\"			\n"	\
 	"	"__UA_ADDR "\t1b, 3b				\n"	\
 	"	.previous					\n"	\
-	: "=r" (__gu_err), "=r" (__gu_val)				\
+	: "=r" (__gu_err), "=r" (__gu_tmp)				\
 	: "0" (0), "o" (__m(addr)), "i" (-EFAULT));			\
+									\
+	(val) = (__typeof__(val)) __gu_tmp;				\
 }
 
 /*
  * Get a long long 64 using 32 bit registers.
  */
-#define __get_user_asm_ll32(addr)					\
+#define __get_user_asm_ll32(val, addr)					\
 {									\
 	__asm__ __volatile__(						\
 	"1:	lw	%1, (%3)				\n"	\
@@ -278,21 +280,20 @@
 	"	" __UA_ADDR "	1b, 4b				\n"	\
 	"	" __UA_ADDR "	2b, 4b				\n"	\
 	"	.previous					\n"	\
-	: "=r" (__gu_err), "=&r" (__gu_val)				\
+	: "=r" (__gu_err), "=&r" (val)					\
 	: "0" (0), "r" (addr), "i" (-EFAULT));				\
 }
 
-extern void __get_user_unknown(void);
-
 /*
  * Yuck.  We need two variants, one for 64bit operation and one
  * for 32 bit mode and old iron.
  */
-#ifdef __mips64
-#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr)
-#else
+#ifdef CONFIG_32BIT
 #define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr)
 #endif
+#ifdef CONFIG_64BIT
+#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr)
+#endif
 
 #define __put_user_nocheck(x,ptr,size)					\
 ({									\
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 89ea8b6..e7ff9b1 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -307,17 +307,33 @@
 #define __NR_inotify_init		(__NR_Linux + 284)
 #define __NR_inotify_add_watch		(__NR_Linux + 285)
 #define __NR_inotify_rm_watch		(__NR_Linux + 286)
-
+#define __NR_migrate_pages		(__NR_Linux + 287)
+#define __NR_openat			(__NR_Linux + 288)
+#define __NR_mkdirat			(__NR_Linux + 289)
+#define __NR_mknodat			(__NR_Linux + 290)
+#define __NR_fchownat			(__NR_Linux + 291)
+#define __NR_futimesat			(__NR_Linux + 292)
+#define __NR_newfstatat			(__NR_Linux + 293)
+#define __NR_unlinkat			(__NR_Linux + 294)
+#define __NR_renameat			(__NR_Linux + 295)
+#define __NR_linkat			(__NR_Linux + 296)
+#define __NR_symlinkat			(__NR_Linux + 297)
+#define __NR_readlinkat			(__NR_Linux + 298)
+#define __NR_fchmodat			(__NR_Linux + 299)
+#define __NR_faccessat			(__NR_Linux + 300)
+#define __NR_pselect6			(__NR_Linux + 301)
+#define __NR_ppoll			(__NR_Linux + 302)
+#define __NR_unshare			(__NR_Linux + 303)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		286
+#define __NR_Linux_syscalls		303
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		283
+#define __NR_O32_Linux_syscalls		303
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -571,16 +587,33 @@
 #define __NR_inotify_init		(__NR_Linux + 243)
 #define __NR_inotify_add_watch		(__NR_Linux + 244)
 #define __NR_inotify_rm_watch		(__NR_Linux + 245)
+#define __NR_migrate_pages		(__NR_Linux + 246)
+#define __NR_openat			(__NR_Linux + 247)
+#define __NR_mkdirat			(__NR_Linux + 248)
+#define __NR_mknodat			(__NR_Linux + 249)
+#define __NR_fchownat			(__NR_Linux + 250)
+#define __NR_futimesat			(__NR_Linux + 251)
+#define __NR_newfstatat			(__NR_Linux + 252)
+#define __NR_unlinkat			(__NR_Linux + 253)
+#define __NR_renameat			(__NR_Linux + 254)
+#define __NR_linkat			(__NR_Linux + 255)
+#define __NR_symlinkat			(__NR_Linux + 256)
+#define __NR_readlinkat			(__NR_Linux + 257)
+#define __NR_fchmodat			(__NR_Linux + 258)
+#define __NR_faccessat			(__NR_Linux + 259)
+#define __NR_pselect6			(__NR_Linux + 260)
+#define __NR_ppoll			(__NR_Linux + 261)
+#define __NR_unshare			(__NR_Linux + 262)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		245
+#define __NR_Linux_syscalls		262
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		242
+#define __NR_64_Linux_syscalls		262
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -838,16 +871,33 @@
 #define __NR_inotify_init		(__NR_Linux + 247)
 #define __NR_inotify_add_watch		(__NR_Linux + 248)
 #define __NR_inotify_rm_watch		(__NR_Linux + 249)
+#define __NR_migrate_pages		(__NR_Linux + 250)
+#define __NR_openat			(__NR_Linux + 251)
+#define __NR_mkdirat			(__NR_Linux + 252)
+#define __NR_mknodat			(__NR_Linux + 253)
+#define __NR_fchownat			(__NR_Linux + 254)
+#define __NR_futimesat			(__NR_Linux + 255)
+#define __NR_newfstatat			(__NR_Linux + 256)
+#define __NR_unlinkat			(__NR_Linux + 257)
+#define __NR_renameat			(__NR_Linux + 258)
+#define __NR_linkat			(__NR_Linux + 259)
+#define __NR_symlinkat			(__NR_Linux + 260)
+#define __NR_readlinkat			(__NR_Linux + 261)
+#define __NR_fchmodat			(__NR_Linux + 262)
+#define __NR_faccessat			(__NR_Linux + 263)
+#define __NR_pselect6			(__NR_Linux + 264)
+#define __NR_ppoll			(__NR_Linux + 265)
+#define __NR_unshare			(__NR_Linux + 266)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		249
+#define __NR_Linux_syscalls		266
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		246
+#define __NR_N32_Linux_syscalls		266
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h
index 2ca56d3..4dc7253 100644
--- a/include/asm-parisc/atomic.h
+++ b/include/asm-parisc/atomic.h
@@ -1,9 +1,13 @@
+/* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2006 Kyle McMartin <kyle@parisc-linux.org>
+ */
+
 #ifndef _ASM_PARISC_ATOMIC_H_
 #define _ASM_PARISC_ATOMIC_H_
 
 #include <linux/config.h>
+#include <linux/types.h>
 #include <asm/system.h>
-/* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.  */
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -46,15 +50,6 @@
 #  define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0)
 #endif
 
-/* Note that we need not lock read accesses - aligned word writes/reads
- * are atomic, so a reader never sees unconsistent values.
- *
- * Cache-line alignment would conflict with, for example, linux/module.h
- */
-
-typedef struct { volatile int counter; } atomic_t;
-
-
 /* This should get optimized out since it's never called.
 ** Or get a link error if xchg is used "wrong".
 */
@@ -69,10 +64,9 @@
 #endif
 
 /* optimizer better get rid of switch since size is a constant */
-static __inline__ unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
-                                       int size)
+static __inline__ unsigned long
+__xchg(unsigned long x, __volatile__ void * ptr, int size)
 {
-
 	switch(size) {
 #ifdef __LP64__
 	case 8: return __xchg64(x,(unsigned long *) ptr);
@@ -129,7 +123,13 @@
 				    (unsigned long)_n_, sizeof(*(ptr))); \
   })
 
+/* Note that we need not lock read accesses - aligned word writes/reads
+ * are atomic, so a reader never sees unconsistent values.
+ *
+ * Cache-line alignment would conflict with, for example, linux/module.h
+ */
 
+typedef struct { volatile int counter; } atomic_t;
 
 /* It's possible to reduce all atomic operations to either
  * __atomic_add_return, atomic_set and atomic_read (the latter
@@ -210,12 +210,66 @@
 
 #define atomic_dec_and_test(v)	(atomic_dec_return(v) == 0)
 
-#define ATOMIC_INIT(i)	{ (i) }
+#define ATOMIC_INIT(i)	((atomic_t) { (i) })
 
 #define smp_mb__before_atomic_dec()	smp_mb()
 #define smp_mb__after_atomic_dec()	smp_mb()
 #define smp_mb__before_atomic_inc()	smp_mb()
 #define smp_mb__after_atomic_inc()	smp_mb()
 
+#ifdef __LP64__
+
+typedef struct { volatile s64 counter; } atomic64_t;
+
+#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
+
+static __inline__ int
+__atomic64_add_return(s64 i, atomic64_t *v)
+{
+	int ret;
+	unsigned long flags;
+	_atomic_spin_lock_irqsave(v, flags);
+
+	ret = (v->counter += i);
+
+	_atomic_spin_unlock_irqrestore(v, flags);
+	return ret;
+}
+
+static __inline__ void
+atomic64_set(atomic64_t *v, s64 i)
+{
+	unsigned long flags;
+	_atomic_spin_lock_irqsave(v, flags);
+
+	v->counter = i;
+
+	_atomic_spin_unlock_irqrestore(v, flags);
+}
+
+static __inline__ s64
+atomic64_read(const atomic64_t *v)
+{
+	return v->counter;
+}
+
+#define atomic64_add(i,v)	((void)(__atomic64_add_return( ((s64)i),(v))))
+#define atomic64_sub(i,v)	((void)(__atomic64_add_return(-((s64)i),(v))))
+#define atomic64_inc(v)		((void)(__atomic64_add_return(   1,(v))))
+#define atomic64_dec(v)		((void)(__atomic64_add_return(  -1,(v))))
+
+#define atomic64_add_return(i,v)	(__atomic64_add_return( ((s64)i),(v)))
+#define atomic64_sub_return(i,v)	(__atomic64_add_return(-((s64)i),(v)))
+#define atomic64_inc_return(v)		(__atomic64_add_return(   1,(v)))
+#define atomic64_dec_return(v)		(__atomic64_add_return(  -1,(v)))
+
+#define atomic64_add_negative(a, v)	(atomic64_add_return((a), (v)) < 0)
+
+#define atomic64_inc_and_test(v) 	(atomic64_inc_return(v) == 0)
+#define atomic64_dec_and_test(v)	(atomic64_dec_return(v) == 0)
+
+#endif /* __LP64__ */
+
 #include <asm-generic/atomic.h>
-#endif
+
+#endif /* _ASM_PARISC_ATOMIC_H_ */
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index 1bc3c83..c53af9f 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -183,4 +183,10 @@
 		__flush_cache_page(vma, vmaddr);
 
 }
+
+#ifdef CONFIG_DEBUG_RODATA
+void mark_rodata_ro(void);
 #endif
+
+#endif /* _PARISC_CACHEFLUSH_H */
+
diff --git a/include/asm-parisc/compat_ucontext.h b/include/asm-parisc/compat_ucontext.h
index a1228a3..2f7292a 100644
--- a/include/asm-parisc/compat_ucontext.h
+++ b/include/asm-parisc/compat_ucontext.h
@@ -1,8 +1,7 @@
 #ifndef _ASM_PARISC_COMPAT_UCONTEXT_H
 #define _ASM_PARISC_COMPAT_UCONTEXT_H
 
-#include<linux/compat.h>
-#include<asm/compat_signal.h>
+#include <linux/compat.h>
 
 /* 32-bit ucontext as seen from an 64-bit kernel */
 struct compat_ucontext {
diff --git a/include/asm-parisc/grfioctl.h b/include/asm-parisc/grfioctl.h
index 6a91031..671e060 100644
--- a/include/asm-parisc/grfioctl.h
+++ b/include/asm-parisc/grfioctl.h
@@ -58,7 +58,7 @@
 #define CRT_ID_ELK_1024DB	0x27849CA5      /* Elk 1024x768 double buffer */
 #define CRT_ID_ELK_GS		S9000_ID_A1924A	/* Elk 1280x1024 GreyScale    */
 #define CRT_ID_CRX24		S9000_ID_A1439A	/* Piranha */
-#define CRT_ID_VISUALIZE_EG	0x2D08C0A7      /* Graffiti (built-in B132+/B160L) */
+#define CRT_ID_VISUALIZE_EG	0x2D08C0A7      /* Graffiti, A4450A (built-in B132+/B160L) */
 #define CRT_ID_THUNDER		0x2F23E5FC      /* Thunder 1 VISUALIZE 48*/
 #define CRT_ID_THUNDER2		0x2F8D570E      /* Thunder 2 VISUALIZE 48 XP*/
 #define CRT_ID_HCRX		S9000_ID_HCRX	/* Hyperdrive HCRX */
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index f277254..fe7f6a2 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -18,6 +18,18 @@
 */
 #define PCI_MAX_BUSSES	256
 
+
+/* To be used as: mdelay(pci_post_reset_delay);
+ *
+ * post_reset is the time the kernel should stall to prevent anyone from
+ * accessing the PCI bus once #RESET is de-asserted. 
+ * PCI spec somewhere says 1 second but with multi-PCI bus systems,
+ * this makes the boot time much longer than necessary.
+ * 20ms seems to work for all the HP PCI implementations to date.
+ */
+#define pci_post_reset_delay 50
+
+
 /*
 ** pci_hba_data (aka H2P_OBJECT in HP/UX)
 **
@@ -83,7 +95,7 @@
 
 /*
 ** Convert between PCI (IO_VIEW) addresses and processor (PA_VIEW) addresses.
-** See pcibios.c for more conversions used by Generic PCI code.
+** See pci.c for more conversions used by Generic PCI code.
 **
 ** Platform characteristics/firmware guarantee that
 **	(1) PA_VIEW - IO_VIEW = lmmio_offset for both LMMIO and ELMMIO
@@ -191,9 +203,6 @@
 */
 extern struct pci_port_ops *pci_port;
 extern struct pci_bios_ops *pci_bios;
-extern int pci_post_reset_delay;	/* delay after de-asserting #RESET */
-extern int pci_hba_count;
-extern struct pci_hba_data *parisc_pci_hba[];
 
 #ifdef CONFIG_PCI
 extern void pcibios_register_hba(struct pci_hba_data *);
diff --git a/include/asm-parisc/pgalloc.h b/include/asm-parisc/pgalloc.h
index 6291d66..3122fad 100644
--- a/include/asm-parisc/pgalloc.h
+++ b/include/asm-parisc/pgalloc.h
@@ -137,7 +137,6 @@
 
 #define pte_free(page)	pte_free_kernel(page_address(page))
 
-extern int do_check_pgt_cache(int, int);
 #define check_pgt_cache()	do { } while (0)
 
 #endif
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index b455471..4e34c6b 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -213,7 +213,7 @@
 #define PAGE_COPY       PAGE_EXECREAD
 #define PAGE_RWX        __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED)
 #define PAGE_KERNEL	__pgprot(_PAGE_KERNEL)
-#define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_DIRTY | _PAGE_ACCESSED)
+#define PAGE_KERNEL_RO	__pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
 #define PAGE_KERNEL_UNC	__pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
 #define PAGE_GATEWAY    __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ)
 #define PAGE_FLUSH      __pgprot(_PAGE_FLUSH)
diff --git a/include/asm-parisc/rt_sigframe.h b/include/asm-parisc/rt_sigframe.h
index 5623c03..f0dd3b3 100644
--- a/include/asm-parisc/rt_sigframe.h
+++ b/include/asm-parisc/rt_sigframe.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_PARISC_RT_SIGFRAME_H
 #define _ASM_PARISC_RT_SIGFRAME_H
 
-#ifdef CONFIG_COMPAT
-#include <asm/compat_rt_sigframe.h>
-#endif
-
 #define SIGRETURN_TRAMP 4
 #define SIGRESTARTBLOCK_TRAMP 5 
 #define TRAMP_SIZE (SIGRETURN_TRAMP + SIGRESTARTBLOCK_TRAMP)
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index 80b7b98..c56fccb 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -761,8 +761,27 @@
 #define __NR_keyctl		(__NR_Linux + 266)
 #define __NR_ioprio_set		(__NR_Linux + 267)
 #define __NR_ioprio_get		(__NR_Linux + 268)
+#define __NR_inotify_init	(__NR_Linux + 269)
+#define __NR_inotify_add_watch	(__NR_Linux + 270)
+#define __NR_inotify_rm_watch	(__NR_Linux + 271)
+#define __NR_migrate_pages	(__NR_Linux + 272)
+#define __NR_pselect6		(__NR_Linux + 273)
+#define __NR_ppoll		(__NR_Linux + 274)
+#define __NR_openat		(__NR_Linux + 275)
+#define __NR_mkdirat		(__NR_Linux + 276)
+#define __NR_mknodat		(__NR_Linux + 277)
+#define __NR_fchownat		(__NR_Linux + 278)
+#define __NR_futimesat		(__NR_Linux + 279)
+#define __NR_newfstatat		(__NR_Linux + 280)
+#define __NR_unlinkat		(__NR_Linux + 281)
+#define __NR_renameat		(__NR_Linux + 282)
+#define __NR_linkat		(__NR_Linux + 283)
+#define __NR_symlinkat		(__NR_Linux + 284)
+#define __NR_readlinkat		(__NR_Linux + 285)
+#define __NR_fchmodat		(__NR_Linux + 286)
+#define __NR_faccessat		(__NR_Linux + 287)
 
-#define __NR_Linux_syscalls     269
+#define __NR_Linux_syscalls     288
 
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
diff --git a/include/asm-powerpc/compat.h b/include/asm-powerpc/compat.h
index accb80c..aacaabd 100644
--- a/include/asm-powerpc/compat.h
+++ b/include/asm-powerpc/compat.h
@@ -126,6 +126,11 @@
 	return (void __user *)(unsigned long)uptr;
 }
 
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+	return (u32)(unsigned long)uptr;
+}
+
 static inline void __user *compat_alloc_user_space(long len)
 {
 	struct pt_regs *regs = current->thread.regs;
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index 837756a..2ac63f5 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -15,7 +15,6 @@
 #include <linux/mm.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
-#include <asm/bug.h>
 
 #define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
 
diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h
index 640a645..bda2f21 100644
--- a/include/asm-powerpc/kexec.h
+++ b/include/asm-powerpc/kexec.h
@@ -33,6 +33,7 @@
 
 #ifdef CONFIG_KEXEC
 
+#ifndef __ASSEMBLY__
 #ifdef __powerpc64__
 /*
  * This function is responsible for capturing register states if coming
@@ -104,7 +105,6 @@
 					struct pt_regs *oldregs) { }
 #endif /* !__powerpc64 __ */
 
-#ifndef __ASSEMBLY__
 #define MAX_NOTE_BYTES 1024
 
 #ifdef __powerpc64__
@@ -121,6 +121,8 @@
 extern int default_machine_kexec_prepare(struct kimage *image);
 extern void default_machine_crash_shutdown(struct pt_regs *regs);
 
+extern void machine_kexec_simple(struct kimage *image);
+
 #endif /* ! __ASSEMBLY__ */
 #endif /* CONFIG_KEXEC */
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/pmac_pfunc.h b/include/asm-powerpc/pmac_pfunc.h
index d9728c8..cef6130 100644
--- a/include/asm-powerpc/pmac_pfunc.h
+++ b/include/asm-powerpc/pmac_pfunc.h
@@ -167,6 +167,7 @@
 	void			*data;
 	struct module		*owner;
 	struct list_head	link;
+	struct pmf_function	*func;
 };
 
 
@@ -187,9 +188,7 @@
 				   const char *name,
 				   struct pmf_irq_client *client);
 
-extern void pmf_unregister_irq_client(struct device_node *np,
-				      const char *name,
-				      struct pmf_irq_client *client);
+extern void pmf_unregister_irq_client(struct pmf_irq_client *client);
 
 /*
  * Called by the handlers when an irq happens
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 5b2bd4e..cbd297f 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -222,5 +222,7 @@
 extern int of_pci_address_to_resource(struct device_node *dev, int bar,
 				      struct resource *r);
 
+extern void kdump_move_device_tree(void);
+
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_PROM_H */
diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h
index 82ce476..2dc9363 100644
--- a/include/asm-powerpc/smu.h
+++ b/include/asm-powerpc/smu.h
@@ -521,6 +521,11 @@
 extern struct smu_sdbp_header *smu_get_sdb_partition(int id,
 					unsigned int *size);
 
+/* Get "sdb" partition data from an SMU satellite */
+extern struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id,
+					int id, unsigned int *size);
+
+
 #endif /* __KERNEL__ */
 
 
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index 7e09d7c..c044ec1 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -37,7 +37,7 @@
 	int		preempt_count;		/* 0 => preemptable,
 						   <0 => BUG */
 	struct restart_block restart_block;
-	void *nvgprs_frame;
+	void __user *nvgprs_frame;
 	/* low level flags - has atomic operations done on it */
 	unsigned long	flags ____cacheline_aligned_in_smp;
 };
@@ -122,6 +122,7 @@
 #define TIF_RESTOREALL		12	/* Restore all regs (implies NOERROR) */
 #define TIF_SAVE_NVGPRS		13	/* Save r14-r31 in signal frame */
 #define TIF_NOERROR		14	/* Force successful syscall return */
+#define TIF_RESTORE_SIGMASK	15	/* Restore signal mask in do_signal */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -138,10 +139,12 @@
 #define _TIF_RESTOREALL		(1<<TIF_RESTOREALL)
 #define _TIF_SAVE_NVGPRS	(1<<TIF_SAVE_NVGPRS)
 #define _TIF_NOERROR		(1<<TIF_NOERROR)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
-				 _TIF_NEED_RESCHED | _TIF_RESTOREALL)
+				 _TIF_NEED_RESCHED | _TIF_RESTOREALL | \
+				 _TIF_RESTORE_SIGMASK)
 #define _TIF_PERSYSCALL_MASK	(_TIF_RESTOREALL|_TIF_NOERROR|_TIF_SAVE_NVGPRS)
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 19eaac3..3555699 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -298,8 +298,11 @@
 #define __NR_inotify_rm_watch	277
 #define __NR_spu_run		278
 #define __NR_spu_create		279
+#define __NR_pselect6		280
+#define __NR_ppoll		281
+#define __NR_unshare		282
 
-#define __NR_syscalls		280
+#define __NR_syscalls		283
 
 #ifdef __KERNEL__
 #define __NR__exit __NR_exit
@@ -444,11 +447,13 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #ifdef CONFIG_PPC32
 #define __ARCH_WANT_OLD_STAT
 #endif
 #ifdef CONFIG_PPC64
 #define __ARCH_WANT_COMPAT_SYS_TIME
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #endif
 
 /*
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index 6123276..3628899 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -518,8 +518,8 @@
 
 static inline int 
 __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
-    return ((((volatile char *) addr)
-	    [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7)))) != 0;
+    return (((volatile char *) addr)
+	    [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7))) != 0;
 }
 
 #define test_bit(nr,addr) \
diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h
index 77b10d6..c744ff3 100644
--- a/include/asm-s390/dasd.h
+++ b/include/asm-s390/dasd.h
@@ -8,8 +8,6 @@
  * any future changes wrt the API will result in a change of the APIVERSION reported
  * to userspace by the DASDAPIVER-ioctl
  *
- * $Revision: 1.6 $
- *
  */
 
 #ifndef DASD_H
@@ -206,7 +204,8 @@
  *
  * Here ist how the ioctl-nr should be used:
  *    0 -   31   DASD driver itself
- *   32 -  239   still open
+ *   32 -  229   still open
+ *  230 -  239   DASD extended error reporting
  *  240 -  255   reserved for EMC 
  *******************************************************************************/
 
@@ -238,12 +237,22 @@
 #define BIODASDPSRD    _IOR(DASD_IOCTL_LETTER,4,dasd_rssd_perf_stats_t)
 /* Get Attributes (cache operations) */
 #define BIODASDGATTR   _IOR(DASD_IOCTL_LETTER,5,attrib_data_t) 
+/* retrieve extended error-reporting value */
+#define BIODASDEERGET  _IOR(DASD_IOCTL_LETTER,6,int)
 
 
 /* #define BIODASDFORMAT  _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
 #define BIODASDFMT     _IOW(DASD_IOCTL_LETTER,1,format_data_t) 
 /* Set Attributes (cache operations) */
 #define BIODASDSATTR   _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) 
+/* retrieve extended error-reporting value */
+#define BIODASDEERSET  _IOW(DASD_IOCTL_LETTER,3,int)
+
+
+/* remove all records from the eer buffer */
+#define DASD_EER_PURGE       _IO(DASD_IOCTL_LETTER,230)
+/* set the number of pages that are used for the internal eer buffer */
+#define DASD_EER_SETBUFSIZE  _IOW(DASD_IOCTL_LETTER,230,int)
 
 
 #endif				/* DASD_H */
diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h
index 71f55eb..b05825d 100644
--- a/include/asm-s390/io.h
+++ b/include/asm-s390/io.h
@@ -90,10 +90,16 @@
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
 
 #define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
 #define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
 #define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
 
 #define memset_io(a,b,c)        memset(__io_virt(a),(b),(c))
 #define memcpy_fromio(a,b,c)    memcpy((a),__io_virt(b),(c))
diff --git a/include/asm-s390/qdio.h b/include/asm-s390/qdio.h
index 7bc15f0..a2f37a9 100644
--- a/include/asm-s390/qdio.h
+++ b/include/asm-s390/qdio.h
@@ -11,8 +11,6 @@
 #ifndef __QDIO_H__
 #define __QDIO_H__
 
-#define VERSION_QDIO_H "$Revision: 1.57 $"
-
 /* note, that most of the typedef's are from ingo. */
 
 #include <linux/interrupt.h>
diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h
index 348a881..da3fd4a 100644
--- a/include/asm-s390/setup.h
+++ b/include/asm-s390/setup.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_S390_SETUP_H
 #define _ASM_S390_SETUP_H
 
+#ifdef __KERNEL__
+
 #include <asm/types.h>
 
 #define PARMAREA		0x10400
@@ -114,7 +116,7 @@
 				 IPL_PARMBLOCK_ORIGIN)
 #define IPL_PARMBLOCK_SIZE	(IPL_PARMBLOCK_START->hdr.length)
 
-#else 
+#else /* __ASSEMBLY__ */
 
 #ifndef __s390x__
 #define IPL_DEVICE        0x10404
@@ -127,6 +129,6 @@
 #endif /* __s390x__ */
 #define COMMAND_LINE      0x10480
 
-#endif
-
-#endif
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_S390_SETUP_H */
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index a2ae762..9c6e9c3 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -101,6 +101,7 @@
 	func(info);
 	return 0;
 }
+#define smp_cpu_not_running(cpu)	1
 #define smp_get_cpu(cpu) ({ 0; })
 #define smp_put_cpu(cpu) ({ 0; })
 #endif
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
index f3797a5..8e0c7ed 100644
--- a/include/asm-s390/thread_info.h
+++ b/include/asm-s390/thread_info.h
@@ -2,7 +2,7 @@
  *  include/asm-s390/thread_info.h
  *
  *  S390 version
- *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 2002,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
@@ -88,7 +88,7 @@
  * thread information flags bit numbers
  */
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_RESTORE_SIGMASK	1	/* restore signal mask in do_signal() */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_RESTART_SVC		4	/* restart svc with new svc number */
@@ -102,7 +102,7 @@
 #define TIF_MEMDIE		19
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_RESTART_SVC	(1<<TIF_RESTART_SVC)
diff --git a/include/asm-s390/timer.h b/include/asm-s390/timer.h
index ea07889..fcd6c25 100644
--- a/include/asm-s390/timer.h
+++ b/include/asm-s390/timer.h
@@ -1,7 +1,7 @@
 /*
  *  include/asm-s390/timer.h
  *
- *  (C) Copyright IBM Corp. 2003
+ *  (C) Copyright IBM Corp. 2003,2006
  *  Virtual CPU timer
  *
  *  Author: Jan Glauber (jang@de.ibm.com)
@@ -10,6 +10,8 @@
 #ifndef _ASM_S390_TIMER_H
 #define _ASM_S390_TIMER_H
 
+#ifdef __KERNEL__
+
 #include <linux/timer.h>
 
 #define VTIMER_MAX_SLICE (0x7ffffffffffff000LL)
@@ -43,4 +45,6 @@
 extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires);
 extern int del_virt_timer(struct vtimer_list *timer);
 
-#endif
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_S390_TIMER_H */
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
index be104f2..0b7c0ca 100644
--- a/include/asm-s390/uaccess.h
+++ b/include/asm-s390/uaccess.h
@@ -61,7 +61,7 @@
 #define segment_eq(a,b) ((a).ar4 == (b).ar4)
 
 
-static inline int __access_ok(const void *addr, unsigned long size)
+static inline int __access_ok(const void __user *addr, unsigned long size)
 {
 	return 1;
 }
@@ -208,25 +208,25 @@
 	case 1: {						\
 		unsigned char __x;				\
 		__get_user_asm(__x, ptr, __gu_err);		\
-		(x) = *(__typeof__(*(ptr)) *) &__x;		\
+		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	case 2: {						\
 		unsigned short __x;				\
 		__get_user_asm(__x, ptr, __gu_err);		\
-		(x) = *(__typeof__(*(ptr)) *) &__x;		\
+		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	case 4: {						\
 		unsigned int __x;				\
 		__get_user_asm(__x, ptr, __gu_err);		\
-		(x) = *(__typeof__(*(ptr)) *) &__x;		\
+		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	case 8: {						\
 		unsigned long long __x;				\
 		__get_user_asm(__x, ptr, __gu_err);		\
-		(x) = *(__typeof__(*(ptr)) *) &__x;		\
+		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	default:						\
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index 2861cdc..657d582 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -279,8 +279,25 @@
 #define __NR_inotify_init	284
 #define __NR_inotify_add_watch	285
 #define __NR_inotify_rm_watch	286
+/* Number 287 is reserved for new sys_migrate_pages */
+#define __NR_openat		288
+#define __NR_mkdirat		289
+#define __NR_mknodat		290
+#define __NR_fchownat		291
+#define __NR_futimesat		292
+#define __NR_fstatat64		293
+#define __NR_unlinkat		294
+#define __NR_renameat		295
+#define __NR_linkat		296
+#define __NR_symlinkat		297
+#define __NR_readlinkat		298
+#define __NR_fchmodat		299
+#define __NR_faccessat		300
+#define __NR_pselect6		301
+#define __NR_ppoll		302
+#define __NR_unshare		303
 
-#define NR_syscalls 287
+#define NR_syscalls 304
 
 /* 
  * There are some system calls that are not present on 64 bit, some
@@ -342,6 +359,7 @@
 #undef  __NR_fcntl64
 #undef  __NR_sendfile64
 #undef  __NR_fadvise64_64
+#undef  __NR_fstatat64
 
 #define __NR_select		142
 #define __NR_getrlimit		191	/* SuS compliant getrlimit */
@@ -364,6 +382,7 @@
 #define __NR_setgid  		214
 #define __NR_setfsuid  		215
 #define __NR_setfsgid  		216
+#define __NR_newfstatat		293
 
 #endif
 
@@ -539,11 +558,15 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 # ifndef CONFIG_64BIT
 #   define __ARCH_WANT_STAT64
 #   define __ARCH_WANT_SYS_TIME
 # endif
-# define __ARCH_WANT_COMPAT_SYS_TIME
+# ifdef CONFIG_COMPAT
+#   define __ARCH_WANT_COMPAT_SYS_TIME
+#   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+# endif
 #endif
 
 #ifdef __KERNEL_SYSCALLS__
diff --git a/include/asm-sh/bus-sh.h b/include/asm-sh/bus-sh.h
deleted file mode 100644
index e42d63b..0000000
--- a/include/asm-sh/bus-sh.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * include/asm-sh/bus-sh.h
- *
- * Copyright (C) 2004 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_SH_BUS_SH_H
-#define __ASM_SH_BUS_SH_H
-
-extern struct bus_type sh_bus_types[];
-
-struct sh_dev {
-	struct device	dev;
-	char		*name;
-	unsigned int	dev_id;
-	unsigned int	bus_id;
-	struct resource	res;
-	void		*mapbase;
-	unsigned int	irq[6];
-	u64		*dma_mask;
-	u64		coherent_dma_mask;
-};
-
-#define to_sh_dev(d)	container_of((d), struct sh_dev, dev)
-
-#define sh_get_drvdata(d)	dev_get_drvdata(&(d)->dev)
-#define sh_set_drvdata(d,p)	dev_set_drvdata(&(d)->dev, (p))
-
-struct sh_driver {
-	struct device_driver	drv;
-	unsigned int		dev_id;
-	unsigned int		bus_id;
-	int (*probe)(struct sh_dev *);
-	int (*remove)(struct sh_dev *);
-	int (*suspend)(struct sh_dev *, pm_message_t);
-	int (*resume)(struct sh_dev *);
-};
-
-#define to_sh_driver(d)	container_of((d), struct sh_driver, drv)
-#define sh_name(d)	((d)->dev.driver->name)
-
-/*
- * Device ID numbers for bus types
- */
-enum {
-	SH_DEV_ID_USB_OHCI,
-};
-
-#define SH_NR_BUSES		1
-#define SH_BUS_NAME_VIRT	"shbus"
-
-enum {
-	SH_BUS_VIRT,
-};
-
-/* arch/sh/kernel/cpu/bus.c */
-extern int sh_device_register(struct sh_dev *dev);
-extern void sh_device_unregister(struct sh_dev *dev);
-extern int sh_driver_register(struct sh_driver *drv);
-extern void sh_driver_unregister(struct sh_driver *drv);
-
-#endif /* __ASM_SH_BUS_SH_H */
-
diff --git a/include/asm-sh/cpu-sh3/mmu_context.h b/include/asm-sh/cpu-sh3/mmu_context.h
index 5cfaa6b..a844ea0 100644
--- a/include/asm-sh/cpu-sh3/mmu_context.h
+++ b/include/asm-sh/cpu-sh3/mmu_context.h
@@ -24,5 +24,15 @@
 #define MMU_NTLB_WAYS		4
 #define MMU_CONTROL_INIT	0x007	/* SV=0, TF=1, IX=1, AT=1 */
 
+#define TRA	0xffffffd0
+#define EXPEVT	0xffffffd4
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#define INTEVT	0xa4000000	/* INTEVTE2(0xa4000000) */
+#else
+#define INTEVT	0xffffffd8
+#endif
+
 #endif /* __ASM_CPU_SH3_MMU_CONTEXT_H */
 
diff --git a/include/asm-sh/cpu-sh4/mmu_context.h b/include/asm-sh/cpu-sh4/mmu_context.h
index 5b64d04..ff4c5fb 100644
--- a/include/asm-sh/cpu-sh4/mmu_context.h
+++ b/include/asm-sh/cpu-sh4/mmu_context.h
@@ -23,7 +23,11 @@
 #define MMU_PAGE_ASSOC_BIT	0x80
 
 #define MMU_NTLB_ENTRIES	64	/* for 7750 */
+#ifdef CONFIG_SH_STORE_QUEUES
+#define MMU_CONTROL_INIT	0x05	/* SQMD=0, SV=0, TI=1, AT=1 */
+#else
 #define MMU_CONTROL_INIT	0x205	/* SQMD=1, SV=0, TI=1, AT=1 */
+#endif
 
 #define MMU_ITLB_DATA_ARRAY	0xF3000000
 #define MMU_UTLB_DATA_ARRAY	0xF7000000
@@ -35,5 +39,9 @@
 #define MMU_I_ENTRY_SHIFT	    8
 #define MMU_ITLB_VALID		0x100
 
+#define TRA	0xff000020
+#define EXPEVT	0xff000024
+#define INTEVT	0xff000028
+
 #endif /* __ASM_CPU_SH4_MMU_CONTEXT_H */
 
diff --git a/include/asm-sh/ioctls.h b/include/asm-sh/ioctls.h
index 1866f3f..9d84a2d 100644
--- a/include/asm-sh/ioctls.h
+++ b/include/asm-sh/ioctls.h
@@ -94,6 +94,6 @@
 #define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* 0x545B */ /* Set multiport config */
 
 #define TIOCMIWAIT	_IO('T', 92) /* 0x545C */	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	_IOR('T', 93, struct async_icount) /* 0x545D */	/* read serial port inline interrupt counts */
+#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
 #endif /* __ASM_SH_IOCTLS_H */
diff --git a/include/asm-sh/irq-sh73180.h b/include/asm-sh/irq-sh73180.h
index bf2e431..d705252 100644
--- a/include/asm-sh/irq-sh73180.h
+++ b/include/asm-sh/irq-sh73180.h
@@ -25,11 +25,6 @@
 #undef DMA_IPR_POS
 #undef DMA_PRIORITY
 
-#undef NR_IRQS
-
-#undef __irq_demux
-#undef irq_demux
-
 #undef INTC_IMCR0
 #undef INTC_IMCR1
 #undef INTC_IMCR2
@@ -229,33 +224,6 @@
 #define SIU_IPR_POS	1
 #define SIU_PRIORITY	3
 
-
-/* ONCHIP_NR_IRQS */
-#define NR_IRQS 109
-
-/* In a generic kernel, NR_IRQS is an upper bound, and we should use
- * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value.
- */
-#define ACTUAL_NR_IRQS NR_IRQS
-
-
-extern void disable_irq(unsigned int);
-extern void disable_irq_nosync(unsigned int);
-extern void enable_irq(unsigned int);
-
-/*
- * Simple Mask Register Support
- */
-extern void make_maskreg_irq(unsigned int irq);
-extern unsigned short *irq_mask_register;
-
-/*
- * Function for "on chip support modules".
- */
-extern void make_ipr_irq(unsigned int irq, unsigned int addr,
-			 int pos,  int priority);
-extern void make_imask_irq(unsigned int irq);
-
 #define PORT_PACR	0xA4050100UL
 #define PORT_PBCR	0xA4050102UL
 #define PORT_PCCR	0xA4050104UL
@@ -343,8 +311,6 @@
 #define IRQ6_PRIORITY	1
 #define IRQ7_PRIORITY	1
 
-extern int shmse_irq_demux(int irq);
-#define __irq_demux(irq) shmse_irq_demux(irq)
-#define irq_demux(irq) __irq_demux(irq)
+int shmse_irq_demux(int irq);
 
 #endif /* __ASM_SH_IRQ_SH73180_H */
diff --git a/include/asm-sh/irq-sh7780.h b/include/asm-sh/irq-sh7780.h
index 8c8ca12..7f90315 100644
--- a/include/asm-sh/irq-sh7780.h
+++ b/include/asm-sh/irq-sh7780.h
@@ -299,29 +299,6 @@
 #define	GPIO_IPR_POS	2
 #define	GPIO_PRIORITY	3
 
-/* ONCHIP_NR_IRQS */
-#define NR_IRQS 150	/* 111 + 16 */
-
-/* In a generic kernel, NR_IRQS is an upper bound, and we should use
- * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value.
- */
-#define ACTUAL_NR_IRQS NR_IRQS
-
-extern void disable_irq(unsigned int);
-extern void disable_irq_nosync(unsigned int);
-extern void enable_irq(unsigned int);
-
-/*
- * Simple Mask Register Support
- */
-extern void make_maskreg_irq(unsigned int irq);
-extern unsigned short *irq_mask_register;
-
-/*
- * Function for "on chip support modules".
- */
-extern void make_imask_irq(unsigned int irq);
-
 #define	INTC_TMU0_MSK	0
 #define	INTC_TMU3_MSK	1
 #define	INTC_RTC_MSK	2
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index 060ec3c..42b8394 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -245,6 +245,7 @@
 #endif /* ST40STB1 */
 
 #endif /* 775x / SH4-202 / ST40STB1 */
+#endif /* 7780 */
 
 /* NR_IRQS is made from three components:
  *   1. ONCHIP_NR_IRQS - number of IRLS + on-chip peripherial modules
@@ -274,8 +275,11 @@
 # define ONCHIP_NR_IRQS 72
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 # define ONCHIP_NR_IRQS 144
-#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+      defined(CONFIG_CPU_SUBTYPE_SH73180)
 # define ONCHIP_NR_IRQS 109
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+# define ONCHIP_NR_IRQS 111
 #elif defined(CONFIG_SH_UNKNOWN)	/* Most be last */
 # define ONCHIP_NR_IRQS 144
 #endif
@@ -306,6 +310,8 @@
 # define OFFCHIP_NR_IRQS 96
 #elif defined (CONFIG_SH_TITAN)
 # define OFFCHIP_NR_IRQS 4
+#elif defined(CONFIG_SH_R7780RP)
+# define OFFCHIP_NR_IRQS 16
 #elif defined(CONFIG_SH_UNKNOWN)
 # define OFFCHIP_NR_IRQS 16	/* Must also be last */
 #else
@@ -550,7 +556,7 @@
 #define INTC_ICR_IRLM	(1<<7)
 #endif
 
-#else
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
 #include <asm/irq-sh7780.h>
 #endif
 
diff --git a/include/asm-sh/microdev/irq.h b/include/asm-sh/microdev.h
similarity index 64%
rename from include/asm-sh/microdev/irq.h
rename to include/asm-sh/microdev.h
index 47f6f77..018332a 100644
--- a/include/asm-sh/microdev/irq.h
+++ b/include/asm-sh/microdev.h
@@ -1,32 +1,27 @@
 /*
- * linux/include/asm-sh/irq_microdev.h
+ * linux/include/asm-sh/microdev.h
  *
  * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
  *
- * IRQ functions for the SuperH SH4-202 MicroDev board.
+ * Definitions for the SuperH SH4-202 MicroDev board.
  *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
- *
  */
-
-
-#ifndef _ASM_SH_IRQ_MICRODEV_H
-#define _ASM_SH_IRQ_MICRODEV_H
+#ifndef __ASM_SH_MICRODEV_H
+#define __ASM_SH_MICRODEV_H
 
 extern void init_microdev_irq(void);
 extern void microdev_print_fpga_intc_status(void);
 
-
-	/*
-	 *	The following are useful macros for manipulating the
-	 *	interrupt controller (INTC) on the CPU-board FPGA.
-	 *	It should be noted that there is an INTC on the FPGA,
-	 *	and a seperate INTC on the SH4-202 core - these are
-	 *	two different things, both of which need to be prorammed
-	 *	to correctly route - unfortunately, they have the
-	 *	same name and abbreviations!
-	 */
+/*
+ * The following are useful macros for manipulating the interrupt
+ * controller (INTC) on the CPU-board FPGA.  should be noted that there
+ * is an INTC on the FPGA, and a seperate INTC on the SH4-202 core -
+ * these are two different things, both of which need to be prorammed to
+ * correctly route - unfortunately, they have the same name and
+ * abbreviations!
+ */
 #define	MICRODEV_FPGA_INTC_BASE		0xa6110000ul				/* INTC base address on CPU-board FPGA */
 #define	MICRODEV_FPGA_INTENB_REG	(MICRODEV_FPGA_INTC_BASE+0ul)		/* Interrupt Enable Register on INTC on CPU-board FPGA */
 #define	MICRODEV_FPGA_INTDSB_REG	(MICRODEV_FPGA_INTC_BASE+8ul)		/* Interrupt Disable Register on INTC on CPU-board FPGA */
@@ -38,10 +33,10 @@
 #define	MICRODEV_FPGA_INTREQ_REG	(MICRODEV_FPGA_INTC_BASE+0x38ul)	/* Interrupt Request Register on INTC on CPU-board FPGA */
 
 
-	/*
-	 *	The following are the IRQ numbers for the Linux Kernel for external interrupts.
-	 *	i.e. the numbers seen by 'cat /proc/interrupt'.
-	 */
+/*
+ * The following are the IRQ numbers for the Linux Kernel for external
+ * interrupts.  i.e. the numbers seen by 'cat /proc/interrupt'.
+ */
 #define MICRODEV_LINUX_IRQ_KEYBOARD	 1	/* SuperIO Keyboard */
 #define MICRODEV_LINUX_IRQ_SERIAL1	 2	/* SuperIO Serial #1 */
 #define MICRODEV_LINUX_IRQ_ETHERNET	 3	/* on-board Ethnernet */
@@ -51,10 +46,11 @@
 #define MICRODEV_LINUX_IRQ_IDE2		13	/* SuperIO IDE #2 */
 #define MICRODEV_LINUX_IRQ_IDE1		14	/* SuperIO IDE #1 */
 
-	/*
-	 *	The following are the IRQ numbers for the INTC on the FPGA for external interrupts.
-	 *	i.e. the bits in the INTC registers in the FPGA.
-	 */
+/*
+ * The following are the IRQ numbers for the INTC on the FPGA for
+ * external interrupts.  i.e. the bits in the INTC registers in the
+ * FPGA.
+ */
 #define MICRODEV_FPGA_IRQ_KEYBOARD	 1	/* SuperIO Keyboard */
 #define MICRODEV_FPGA_IRQ_SERIAL1	 3	/* SuperIO Serial #1 */
 #define MICRODEV_FPGA_IRQ_SERIAL2	 4	/* SuperIO Serial #2 */
@@ -69,4 +65,16 @@
 #define MICRODEV_IRQ_PCI_INTC		10
 #define MICRODEV_IRQ_PCI_INTD		11
 
-#endif /* _ASM_SH_IRQ_MICRODEV_H */
+#define __IO_PREFIX microdev
+#include <asm/io_generic.h>
+
+#if defined(CONFIG_PCI)
+unsigned char  microdev_pci_inb(unsigned long port);
+unsigned short microdev_pci_inw(unsigned long port);
+unsigned long  microdev_pci_inl(unsigned long port);
+void           microdev_pci_outb(unsigned char  data, unsigned long port);
+void           microdev_pci_outw(unsigned short data, unsigned long port);
+void           microdev_pci_outl(unsigned long  data, unsigned long port);
+#endif
+
+#endif /* __ASM_SH_MICRODEV_H */
diff --git a/include/asm-sh/microdev/io.h b/include/asm-sh/microdev/io.h
deleted file mode 100644
index f2ca4ac..0000000
--- a/include/asm-sh/microdev/io.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * linux/include/asm-sh/io_microdev.h
- *
- * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
- *
- * IO functions for the SuperH SH4-202 MicroDev board.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- */
-
-
-#ifndef _ASM_SH_IO_MICRODEV_H
-#define _ASM_SH_IO_MICRODEV_H
-
-extern unsigned long microdev_isa_port2addr(unsigned long offset);
-
-extern unsigned char microdev_inb(unsigned long port);
-extern unsigned short microdev_inw(unsigned long port);
-extern unsigned int microdev_inl(unsigned long port);
-
-extern void microdev_outb(unsigned char value, unsigned long port);
-extern void microdev_outw(unsigned short value, unsigned long port);
-extern void microdev_outl(unsigned int value, unsigned long port);
-
-extern unsigned char microdev_inb_p(unsigned long port);
-extern unsigned short microdev_inw_p(unsigned long port);
-extern unsigned int microdev_inl_p(unsigned long port);
-
-extern void microdev_outb_p(unsigned char value, unsigned long port);
-extern void microdev_outw_p(unsigned short value, unsigned long port);
-extern void microdev_outl_p(unsigned int value, unsigned long port);
-
-extern void microdev_insb(unsigned long port, void *addr, unsigned long count);
-extern void microdev_insw(unsigned long port, void *addr, unsigned long count);
-extern void microdev_insl(unsigned long port, void *addr, unsigned long count);
-
-extern void microdev_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void microdev_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void microdev_outsl(unsigned long port, const void *addr, unsigned long count);
-
-#if defined(CONFIG_PCI)
-extern unsigned char  microdev_pci_inb(unsigned long port);
-extern unsigned short microdev_pci_inw(unsigned long port);
-extern unsigned long  microdev_pci_inl(unsigned long port);
-extern void           microdev_pci_outb(unsigned char  data, unsigned long port);
-extern void           microdev_pci_outw(unsigned short data, unsigned long port);
-extern void           microdev_pci_outl(unsigned long  data, unsigned long port);
-#endif
-
-#endif /* _ASM_SH_IO_MICRODEV_H */
-
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index c490479..fa5bd2d 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -12,7 +12,6 @@
 #include <asm/page.h>
 #include <asm/types.h>
 #include <asm/cache.h>
-#include <linux/threads.h>
 #include <asm/ptrace.h>
 
 /*
@@ -30,7 +29,7 @@
  *  CPU type and hardware bug flags. Kept separately for each CPU.
  *
  *  Each one of these also needs a CONFIG_CPU_SUBTYPE_xxx entry
- *  in arch/sh/Kconfig, as well as an entry in arch/sh/kernel/setup.c
+ *  in arch/sh/mm/Kconfig, as well as an entry in arch/sh/kernel/setup.c
  *  for parsing the subtype in get_cpu_subtype().
  */
 enum cpu_type {
@@ -44,7 +43,7 @@
 	/* SH-4 types */
 	CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R,
 	CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
-	CPU_SH73180,
+	CPU_SH73180, CPU_SH7770, CPU_SH7780, CPU_SH7781,
 
 	/* Unknown subtype */
 	CPU_SH_NONE
@@ -52,14 +51,8 @@
 
 struct sh_cpuinfo {
 	enum cpu_type type;
-	char	hard_math;
 	unsigned long loops_per_jiffy;
 
-	unsigned int cpu_clock, master_clock, bus_clock, module_clock;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-	unsigned int memory_clock;
-#endif
-
 	struct cache_info icache;
 	struct cache_info dcache;
 
@@ -131,7 +124,7 @@
 	struct sh_fpu_soft_struct soft;
 };
 
-/* 
+/*
  * Processor flags
  */
 
@@ -140,6 +133,7 @@
 #define CPU_HAS_MMU_PAGE_ASSOC	0x0004	/* SH3: TLB way selection bit support */
 #define CPU_HAS_DSP		0x0008	/* SH-DSP: DSP support */
 #define CPU_HAS_PERF_COUNTER	0x0010	/* Hardware performance counters */
+#define CPU_HAS_PTEA		0x0020	/* PTEA register */
 
 struct thread_struct {
 	unsigned long sp;
@@ -160,10 +154,10 @@
 #define INIT_THREAD  {						\
 	sizeof(init_stack) + (long) &init_stack, /* sp */	\
 	0,					 /* pc */	\
-	0, 0, 							\
-	0, 							\
-	0, 							\
-	{{{0,}},} 				/* fpu state */	\
+	0, 0,							\
+	0,							\
+	0,							\
+	{{{0,}},}				/* fpu state */	\
 }
 
 /*
@@ -171,7 +165,7 @@
  */
 #define start_thread(regs, new_pc, new_sp)	 \
 	set_fs(USER_DS);			 \
-	regs->pr = 0;   		 	 \
+	regs->pr = 0;				 \
 	regs->sr = SR_FD;	/* User mode. */ \
 	regs->pc = new_pc;			 \
 	regs->regs[15] = new_sp
@@ -239,16 +233,16 @@
 #define save_fpu(tsk)	do { } while (0)
 #endif
 
-#define unlazy_fpu(tsk, regs) do { 				\
+#define unlazy_fpu(tsk, regs) do {			\
 	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {	\
-		save_fpu(tsk, regs); 				\
+		save_fpu(tsk, regs);			\
 	}						\
 } while (0)
 
-#define clear_fpu(tsk, regs) do { 					\
-	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { 		\
-		clear_tsk_thread_flag(tsk, TIF_USEDFPU); 	\
-		release_fpu(regs);					\
+#define clear_fpu(tsk, regs) do {				\
+	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {		\
+		clear_tsk_thread_flag(tsk, TIF_USEDFPU);	\
+		release_fpu(regs);				\
 	}							\
 } while (0)
 
diff --git a/include/asm-sh64/ioctls.h b/include/asm-sh64/ioctls.h
index 08f3c1f..6b0c04f 100644
--- a/include/asm-sh64/ioctls.h
+++ b/include/asm-sh64/ioctls.h
@@ -111,6 +111,6 @@
 #define TIOCSERSETMULTI 0x40a8545b	/* _IOW('T', 91, struct serial_multiport_struct) 0x545B */ /* Set multiport config */
 
 #define TIOCMIWAIT	0x545c		/* _IO('T', 92) wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x802c545d	/* _IOR('T', 93, struct async_icount) 0x545D */	/* read serial port inline interrupt counts */
+#define TIOCGICOUNT	0x545d		/* read serial port inline interrupt counts */
 
 #endif /* __ASM_SH64_IOCTLS_H */
diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h
index 9594455..d0d76b3 100644
--- a/include/asm-sparc/oplib.h
+++ b/include/asm-sparc/oplib.h
@@ -164,6 +164,7 @@
 	PROMDEV_IKBD,			/* input from keyboard */
 	PROMDEV_ITTYA,			/* input from ttya */
 	PROMDEV_ITTYB,			/* input from ttyb */
+	PROMDEV_IRSC,			/* input from rsc */
 	PROMDEV_I_UNK,
 };
 
@@ -175,6 +176,7 @@
 	PROMDEV_OSCREEN,		/* to screen */
 	PROMDEV_OTTYA,			/* to ttya */
 	PROMDEV_OTTYB,			/* to ttyb */
+	PROMDEV_ORSC,			/* to rsc */
 	PROMDEV_O_UNK,
 };
 
diff --git a/include/asm-sparc/thread_info.h b/include/asm-sparc/thread_info.h
index 65f060b..91b9f58 100644
--- a/include/asm-sparc/thread_info.h
+++ b/include/asm-sparc/thread_info.h
@@ -128,9 +128,10 @@
  * thread information flag bit numbers
  */
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+/* flag bit 1 is available */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_RESTORE_SIGMASK	4	/* restore signal mask in do_signal() */
 #define TIF_USEDFPU		8	/* FPU was used by this task
 					 * this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
@@ -139,9 +140,9 @@
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 58dba51..64ec640 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -300,11 +300,27 @@
 #define __NR_add_key		281
 #define __NR_request_key	282
 #define __NR_keyctl		283
+#define __NR_openat		284
+#define __NR_mkdirat		285
+#define __NR_mknodat		286
+#define __NR_fchownat		287
+#define __NR_futimesat		288
+#define __NR_fstatat64		289
+#define __NR_unlinkat		290
+#define __NR_renameat		291
+#define __NR_linkat		292
+#define __NR_symlinkat		293
+#define __NR_readlinkat		294
+#define __NR_fchmodat		295
+#define __NR_faccessat		296
+#define __NR_pselect6		297
+#define __NR_ppoll		298
+#define __NR_unshare		299
 
-/* WARNING: You MAY NOT add syscall numbers larger than 283, since
+/* WARNING: You MAY NOT add syscall numbers larger than 299, since
  *          all of the syscall tables in the Sparc kernel are
- *          sized to have 283 entries (starting at zero).  Therefore
- *          find a free slot in the 0-282 range.
+ *          sized to have 299 entries (starting at zero).  Therefore
+ *          find a free slot in the 0-299 range.
  */
 
 #define _syscall0(type,name) \
@@ -458,6 +474,7 @@
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #endif
 
 #ifdef __KERNEL_SYSCALLS__
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
index d02f1e8..3c59b26 100644
--- a/include/asm-sparc64/oplib.h
+++ b/include/asm-sparc64/oplib.h
@@ -163,6 +163,7 @@
 	PROMDEV_IKBD,			/* input from keyboard */
 	PROMDEV_ITTYA,			/* input from ttya */
 	PROMDEV_ITTYB,			/* input from ttyb */
+	PROMDEV_IRSC,			/* input from rsc */
 	PROMDEV_I_UNK,
 };
 
@@ -174,6 +175,7 @@
 	PROMDEV_OSCREEN,		/* to screen */
 	PROMDEV_OTTYA,			/* to ttya */
 	PROMDEV_OTTYB,			/* to ttyb */
+	PROMDEV_ORSC,			/* to rsc */
 	PROMDEV_O_UNK,
 };
 
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
index ec85d12..508c416 100644
--- a/include/asm-sparc64/spinlock.h
+++ b/include/asm-sparc64/spinlock.h
@@ -131,6 +131,28 @@
 	: "memory");
 }
 
+static int inline __read_trylock(raw_rwlock_t *lock)
+{
+	int tmp1, tmp2;
+
+	__asm__ __volatile__ (
+"1:	ldsw		[%2], %0\n"
+"	brlz,a,pn	%0, 2f\n"
+"	 mov		0, %0\n"
+"	add		%0, 1, %1\n"
+"	cas		[%2], %0, %1\n"
+"	cmp		%0, %1\n"
+"	membar		#StoreLoad | #StoreStore\n"
+"	bne,pn		%%icc, 1b\n"
+"	 mov		1, %0\n"
+"2:"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock)
+	: "memory");
+
+	return tmp1;
+}
+
 static void inline __read_unlock(raw_rwlock_t *lock)
 {
 	unsigned long tmp1, tmp2;
@@ -211,12 +233,12 @@
 }
 
 #define __raw_read_lock(p)	__read_lock(p)
+#define __raw_read_trylock(p)	__read_trylock(p)
 #define __raw_read_unlock(p)	__read_unlock(p)
 #define __raw_write_lock(p)	__write_lock(p)
 #define __raw_write_unlock(p)	__write_unlock(p)
 #define __raw_write_trylock(p)	__write_trylock(p)
 
-#define __raw_read_trylock(lock)	generic__raw_read_trylock(lock)
 #define __raw_read_can_lock(rw)		(!((rw)->lock & 0x80000000UL))
 #define __raw_write_can_lock(rw)	(!(rw)->lock)
 
diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
index c94d8b3..ac9d068 100644
--- a/include/asm-sparc64/thread_info.h
+++ b/include/asm-sparc64/thread_info.h
@@ -221,7 +221,7 @@
  *	 nop
  */
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_RESTORE_SIGMASK	1	/* restore signal mask in do_signal() */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_PERFCTR		4	/* performance counters active */
@@ -241,7 +241,6 @@
 #define TIF_POLLING_NRFLAG	14
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_PERFCTR		(1<<TIF_PERFCTR)
@@ -250,11 +249,12 @@
 #define _TIF_32BIT		(1<<TIF_32BIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_USER_WORK_MASK	((0xff << TI_FLAG_WSAVED_SHIFT) | \
-				 (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
+				 (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | \
 				  _TIF_NEED_RESCHED | _TIF_PERFCTR))
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index 51ec287..a284986 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -302,11 +302,27 @@
 #define __NR_add_key		281
 #define __NR_request_key	282
 #define __NR_keyctl		283
+#define __NR_openat		284
+#define __NR_mkdirat		285
+#define __NR_mknodat		286
+#define __NR_fchownat		287
+#define __NR_futimesat		288
+#define __NR_fstatat64		289
+#define __NR_unlinkat		290
+#define __NR_renameat		291
+#define __NR_linkat		292
+#define __NR_symlinkat		293
+#define __NR_readlinkat		294
+#define __NR_fchmodat		295
+#define __NR_faccessat		296
+#define __NR_pselect6		297
+#define __NR_ppoll		298
+#define __NR_unshare		299
 
-/* WARNING: You MAY NOT add syscall numbers larger than 283, since
+/* WARNING: You MAY NOT add syscall numbers larger than 299, since
  *          all of the syscall tables in the Sparc kernel are
- *          sized to have 283 entries (starting at zero).  Therefore
- *          find a free slot in the 0-282 range.
+ *          sized to have 299 entries (starting at zero).  Therefore
+ *          find a free slot in the 0-299 range.
  */
 
 #define _syscall0(type,name) \
@@ -501,6 +517,8 @@
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #endif
 
 /*
diff --git a/include/asm-um/io.h b/include/asm-um/io.h
index 9067405..1934d93 100644
--- a/include/asm-um/io.h
+++ b/include/asm-um/io.h
@@ -33,4 +33,20 @@
  */
 #define xlate_dev_kmem_ptr(p)	p
 
+static inline void writeb(unsigned char b, volatile void __iomem *addr)
+{
+	*(volatile unsigned char __force *) addr = b;
+}
+static inline void writew(unsigned short b, volatile void __iomem *addr)
+{
+	*(volatile unsigned short __force *) addr = b;
+}
+static inline void writel(unsigned int b, volatile void __iomem *addr)
+{
+	*(volatile unsigned int __force *) addr = b;
+}
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
 #endif
diff --git a/include/asm-um/ldt-x86_64.h b/include/asm-um/ldt-x86_64.h
index 175722a..96b35aa 100644
--- a/include/asm-um/ldt-x86_64.h
+++ b/include/asm-um/ldt-x86_64.h
@@ -5,8 +5,8 @@
  * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
  */
 
-#ifndef __ASM_LDT_I386_H
-#define __ASM_LDT_I386_H
+#ifndef __ASM_LDT_X86_64_H
+#define __ASM_LDT_X86_64_H
 
 #include "asm/semaphore.h"
 #include "asm/arch/ldt.h"
@@ -39,11 +39,13 @@
 } uml_ldt_t;
 
 /*
- * macros stolen from include/asm-i386/desc.h
+ * macros stolen from include/asm-x86_64/desc.h
  */
 #define LDT_entry_a(info) \
 	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
 
+/* Don't allow setting of the lm bit. It is useless anyways because
+ * 64bit system calls require __USER_CS. */
 #define LDT_entry_b(info) \
 	(((info)->base_addr & 0xff000000) | \
 	(((info)->base_addr & 0x00ff0000) >> 16) | \
@@ -54,6 +56,7 @@
 	((info)->seg_32bit << 22) | \
 	((info)->limit_in_pages << 23) | \
 	((info)->useable << 20) | \
+	/* ((info)->lm << 21) | */ \
 	0x7000)
 
 #define LDT_empty(info) (\
@@ -64,6 +67,7 @@
 	(info)->seg_32bit	== 0	&& \
 	(info)->limit_in_pages	== 0	&& \
 	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	)
+	(info)->useable		== 0	&& \
+	(info)->lm              == 0)
 
 #endif
diff --git a/include/asm-um/smp.h b/include/asm-um/smp.h
index d879eba..aeda665 100644
--- a/include/asm-um/smp.h
+++ b/include/asm-um/smp.h
@@ -23,6 +23,8 @@
 {
 }
 
+extern struct task_struct *idle_threads[NR_CPUS];
+
 #endif
 
 #endif
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 705c719..17b6b07 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -69,6 +69,7 @@
 #define TIF_RESTART_BLOCK 	4
 #define TIF_MEMDIE	 	5
 #define TIF_SYSCALL_AUDIT	6
+#define TIF_RESTORE_SIGMASK	7
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -76,16 +77,6 @@
 #define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
+#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/include/asm-um/unistd.h b/include/asm-um/unistd.h
index 6fdde45..afccfca 100644
--- a/include/asm-um/unistd.h
+++ b/include/asm-um/unistd.h
@@ -34,6 +34,7 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #endif
 
 #ifdef __KERNEL_SYSCALLS__
diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h
index 8955d23..609b9e8 100644
--- a/include/asm-v850/bitops.h
+++ b/include/asm-v850/bitops.h
@@ -188,7 +188,7 @@
 	tmp = *p;
 
  found_first:
-	tmp |= ~0UL >> size;
+	tmp |= ~0UL << size;
  found_middle:
 	return result + ffz (tmp);
 }
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index 4f6a4dc..bdbd893 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -17,6 +17,7 @@
 #define APIC_DEBUG   2
 
 extern int apic_verbosity;
+extern int apic_runs_main_timer;
 
 /*
  * Define the default level of output to be very little
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index 41c0ac8..76bb619 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -61,7 +61,7 @@
 #define X86_FEATURE_K6_MTRR	(3*32+ 1) /* AMD K6 nonstandard MTRRs */
 #define X86_FEATURE_CYRIX_ARR	(3*32+ 2) /* Cyrix ARRs (= MTRRs) */
 #define X86_FEATURE_CENTAUR_MCR	(3*32+ 3) /* Centaur MCRs (= MTRRs) */
-/* 4 free */
+#define X86_FEATURE_REP_GOOD	(3*32+ 4) /* rep microcode works well on this CPU */
 #define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
 #define X86_FEATURE_SYNC_RDTSC  (3*32+6)  /* RDTSC syncs CPU core */
 
diff --git a/include/asm-x86_64/edac.h b/include/asm-x86_64/edac.h
new file mode 100644
index 0000000..cad1cd4
--- /dev/null
+++ b/include/asm-x86_64/edac.h
@@ -0,0 +1,18 @@
+#ifndef ASM_EDAC_H
+#define ASM_EDAC_H
+
+/* ECC atomic, DMA, SMP and interrupt safe scrub function */
+
+static __inline__ void atomic_scrub(void *va, u32 size)
+{
+	unsigned int *virt_addr = va;
+	u32 i;
+
+	for (i = 0; i < size / 4; i++, virt_addr++)
+		/* Very carefully read and write to memory atomically
+		 * so we are interrupt, DMA and SMP safe.
+		 */
+		__asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr));
+}
+
+#endif
diff --git a/include/asm-x86_64/hardirq.h b/include/asm-x86_64/hardirq.h
index 8661b47..8689951 100644
--- a/include/asm-x86_64/hardirq.h
+++ b/include/asm-x86_64/hardirq.h
@@ -16,23 +16,6 @@
 #define set_softirq_pending(x) write_pda(__softirq_pending, (x))
 #define or_softirq_pending(x)  or_pda(__softirq_pending, (x))
 
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves.
- */
-static inline void ack_bad_irq(unsigned int irq)
-{
-	printk("unexpected IRQ trap at vector %02x\n", irq);
-#ifdef CONFIG_X86_LOCAL_APIC
-	/*
-	 * Currently unexpected vectors happen only on SMP and APIC.
-	 * We _must_ ack these because every local APIC has only N
-	 * irq slots per priority level, and a 'hanging, unacked' IRQ
-	 * holds up an irq slot - in excessive cases (when multiple
-	 * unexpected vectors occur) that might lock up the APIC
-	 * completely.
-	 */
-	ack_APIC_irq();
-#endif
-}
+extern void ack_bad_irq(unsigned int irq);
+
 #endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h
index c20c28f..08b75c1 100644
--- a/include/asm-x86_64/hpet.h
+++ b/include/asm-x86_64/hpet.h
@@ -55,6 +55,8 @@
 extern int hpet_rtc_timer_init(void);
 extern int oem_force_hpet_timer(void);
 
+extern int hpet_use_timer;
+
 #ifdef CONFIG_HPET_EMULATE_RTC
 extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
 extern int hpet_set_rtc_irq_bit(unsigned long bit_mask);
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index e884336..eeb2bcd 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -300,7 +300,23 @@
 #define __NR_ia32_inotify_add_watch	292
 #define __NR_ia32_inotify_rm_watch	293
 #define __NR_ia32_migrate_pages		294
+#define __NR_ia32_openat		295
+#define __NR_ia32_mkdirat		296
+#define __NR_ia32_mknodat		297
+#define __NR_ia32_fchownat		298
+#define __NR_ia32_futimesat		299
+#define __NR_ia32_fstatat64		300
+#define __NR_ia32_unlinkat		301
+#define __NR_ia32_renameat		302
+#define __NR_ia32_linkat		303
+#define __NR_ia32_symlinkat		304
+#define __NR_ia32_readlinkat		305
+#define __NR_ia32_fchmodat		306
+#define __NR_ia32_faccessat		307
+#define __NR_ia32_pselect6		308
+#define __NR_ia32_ppoll			309
+#define __NR_ia32_unshare		310
 
-#define IA32_NR_syscalls 295	/* must be > than biggest syscall! */
+#define IA32_NR_syscalls 315	/* must be > than biggest syscall! */
 
 #endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff --git a/include/asm-x86_64/kexec.h b/include/asm-x86_64/kexec.h
index ae28cd4..c564bae 100644
--- a/include/asm-x86_64/kexec.h
+++ b/include/asm-x86_64/kexec.h
@@ -1,8 +1,9 @@
 #ifndef _X86_64_KEXEC_H
 #define _X86_64_KEXEC_H
 
+#include <linux/string.h>
+
 #include <asm/page.h>
-#include <asm/proto.h>
 #include <asm/ptrace.h>
 
 /*
diff --git a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h
index 10248a9..14fc3dd 100644
--- a/include/asm-x86_64/mpspec.h
+++ b/include/asm-x86_64/mpspec.h
@@ -188,7 +188,7 @@
 extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
 extern void mp_config_acpi_legacy_irqs (void);
-extern int mp_register_gsi (u32 gsi, int edge_level, int active_high_low);
+extern int mp_register_gsi (u32 gsi, int triggering, int polarity);
 #endif /*CONFIG_X86_IO_APIC*/
 #endif
 
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index 34e434c..dffe276 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -22,8 +22,15 @@
 extern unsigned char apicid_to_node[256];
 #ifdef CONFIG_NUMA
 extern void __init init_cpu_to_node(void);
+
+static inline void clear_node_cpumask(int cpu)
+{
+	clear_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]);
+}
+
 #else
 #define init_cpu_to_node() do {} while (0)
+#define clear_node_cpumask(cpu) do {} while (0)
 #endif
 
 #define NUMA_NO_NODE 0xff
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index 115e496..c99832e 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -41,10 +41,18 @@
 
 extern void time_init_gtod(void);
 extern int pmtimer_mark_offset(void);
+extern void pmtimer_resume(void);
+extern void pmtimer_wait(unsigned);
 extern unsigned int do_gettimeoffset_pm(void);
+#ifdef CONFIG_X86_PM_TIMER
 extern u32 pmtmr_ioport;
+#else
+#define pmtmr_ioport 0
+#endif
 extern unsigned long long monotonic_base;
 extern int sysctl_vsyscall;
+extern int nohpet;
+extern unsigned long vxtime_hz;
 
 extern void do_softirq_thunk(void);
 
@@ -65,6 +73,9 @@
 
 extern void load_gs_index(unsigned gs);
 
+extern void stop_timer_interrupt(void);
+extern void main_timer_handler(struct pt_regs *regs);
+
 extern unsigned long end_pfn_map; 
 
 extern void show_trace(unsigned long * rsp);
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index a73f0c7..b7f6603 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -327,7 +327,7 @@
 #define wmb()	asm volatile("" ::: "memory")
 #endif
 #define read_barrier_depends()	do {} while(0)
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
 #define warn_if_not_ulong(x) do { unsigned long foo; (void) (&(x) == &foo); } while (0)
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index 2fa7f27..c642f5d 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -57,6 +57,15 @@
 
 #endif
 
+#ifdef CONFIG_SMP
+#define topology_physical_package_id(cpu)				\
+	(phys_proc_id[cpu] == BAD_APICID ? -1 : phys_proc_id[cpu])
+#define topology_core_id(cpu)						\
+	(cpu_core_id[cpu] == BAD_APICID ? 0 : cpu_core_id[cpu])
+#define topology_core_siblings(cpu)		(cpu_core_map[cpu])
+#define topology_thread_siblings(cpu)		(cpu_sibling_map[cpu])
+#endif
+
 #include <asm-generic/topology.h>
 
 #endif
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index e6f8961..da0341c 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -573,8 +573,41 @@
 __SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
 #define __NR_migrate_pages	256
 __SYSCALL(__NR_migrate_pages, sys_migrate_pages)
+#define __NR_openat		257
+__SYSCALL(__NR_openat, sys_openat)
+#define __NR_mkdirat		258
+__SYSCALL(__NR_mkdirat, sys_mkdirat)
+#define __NR_mknodat		259
+__SYSCALL(__NR_mknodat, sys_mknodat)
+#define __NR_fchownat		260
+__SYSCALL(__NR_fchownat, sys_fchownat)
+#define __NR_futimesat		261
+__SYSCALL(__NR_futimesat, sys_futimesat)
+#define __NR_newfstatat		262
+__SYSCALL(__NR_newfstatat, sys_newfstatat)
+#define __NR_unlinkat		263
+__SYSCALL(__NR_unlinkat, sys_unlinkat)
+#define __NR_renameat		264
+__SYSCALL(__NR_renameat, sys_renameat)
+#define __NR_linkat		265
+__SYSCALL(__NR_linkat, sys_linkat)
+#define __NR_symlinkat		266
+__SYSCALL(__NR_symlinkat, sys_symlinkat)
+#define __NR_readlinkat		267
+__SYSCALL(__NR_readlinkat, sys_readlinkat)
+#define __NR_fchmodat		268
+__SYSCALL(__NR_fchmodat, sys_fchmodat)
+#define __NR_faccessat		269
+__SYSCALL(__NR_faccessat, sys_faccessat)
+#define __NR_pselect6		270
+__SYSCALL(__NR_pselect6, sys_ni_syscall)	/* for now */
+#define __NR_ppoll		271
+__SYSCALL(__NR_ppoll,	sys_ni_syscall)		/* for now */
+#define __NR_unshare		272
+__SYSCALL(__NR_unshare,	sys_unshare)
 
-#define __NR_syscall_max __NR_migrate_pages
+#define __NR_syscall_max __NR_unshare
+
 #ifndef __NO_STUBS
 
 /* user-visible error numbers are in the range -1 - -4095 */
diff --git a/include/asm-xtensa/futex.h b/include/asm-xtensa/futex.h
new file mode 100644
index 0000000..0b74582
--- /dev/null
+++ b/include/asm-xtensa/futex.h
@@ -0,0 +1 @@
+#include <asm-generic/futex.h>
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 026c3c0..84d3d9f 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -435,7 +435,7 @@
 
 #endif 	/* !CONFIG_ACPI */
 
-int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low);
+int acpi_register_gsi (u32 gsi, int triggering, int polarity);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
 /*
diff --git a/include/linux/agpgart.h b/include/linux/agpgart.h
index 17a17c5..6d59c8e 100644
--- a/include/linux/agpgart.h
+++ b/include/linux/agpgart.h
@@ -111,6 +111,7 @@
 } agp_unbind;
 
 #else				/* __KERNEL__ */
+#include <linux/mutex.h>
 
 #define AGPGART_MINOR 175
 
@@ -201,7 +202,7 @@
 };
 
 struct agp_front_data {
-	struct semaphore agp_mutex;
+	struct mutex agp_mutex;
 	struct agp_controller *current_controller;
 	struct agp_controller *controllers;
 	struct agp_file_private *file_priv_list;
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 6a2a19f..208650b 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -81,7 +81,7 @@
 {
 	__u32 h = x >> 32;
 	if (h)
-		return fls(x) + 32;
+		return fls(h) + 32;
 	return fls(x);
 }
 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 02a585f..860e7a4 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -392,8 +392,8 @@
 	unsigned int		nr_congestion_off;
 	unsigned int		nr_batching;
 
-	unsigned short		max_sectors;
-	unsigned short		max_hw_sectors;
+	unsigned int		max_sectors;
+	unsigned int		max_hw_sectors;
 	unsigned short		max_phys_segments;
 	unsigned short		max_hw_segments;
 	unsigned short		hardsect_size;
@@ -697,7 +697,7 @@
 extern void blk_cleanup_queue(request_queue_t *);
 extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
 extern void blk_queue_bounce_limit(request_queue_t *, u64);
-extern void blk_queue_max_sectors(request_queue_t *, unsigned short);
+extern void blk_queue_max_sectors(request_queue_t *, unsigned int);
 extern void blk_queue_max_phys_segments(request_queue_t *, unsigned short);
 extern void blk_queue_max_hw_segments(request_queue_t *, unsigned short);
 extern void blk_queue_max_segment_size(request_queue_t *, unsigned int);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index f9ca534..c9ab2a2 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -161,5 +161,25 @@
 int get_compat_sigevent(struct sigevent *event,
 		const struct compat_sigevent __user *u_event);
 
+static inline int compat_timeval_compare(struct compat_timeval *lhs,
+					struct compat_timeval *rhs)
+{
+	if (lhs->tv_sec < rhs->tv_sec)
+		return -1;
+	if (lhs->tv_sec > rhs->tv_sec)
+		return 1;
+	return lhs->tv_usec - rhs->tv_usec;
+}
+
+static inline int compat_timespec_compare(struct compat_timespec *lhs,
+					struct compat_timespec *rhs)
+{
+	if (lhs->tv_sec < rhs->tv_sec)
+		return -1;
+	if (lhs->tv_sec > rhs->tv_sec)
+		return 1;
+	return lhs->tv_nsec - rhs->tv_nsec;
+}
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index acffb8c..a7f0150 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -126,7 +126,7 @@
 
 
 struct configfs_attribute {
-	char			*ca_name;
+	const char		*ca_name;
 	struct module 		*ca_owner;
 	mode_t			ca_mode;
 };
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 13e9f4a..60e56c6 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -84,7 +84,6 @@
 #include <linux/kernel.h>
 #include <linux/threads.h>
 #include <linux/bitmap.h>
-#include <asm/bug.h>
 
 typedef struct { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
 extern cpumask_t _unused_cpumask_arg_;
@@ -329,7 +328,7 @@
  * bitmap of size NR_CPUS.
  *
  *  #ifdef CONFIG_HOTPLUG_CPU
- *     cpu_possible_map - all NR_CPUS bits set
+ *     cpu_possible_map - has bit 'cpu' set iff cpu is populatable
  *     cpu_present_map  - has bit 'cpu' set iff cpu is populated
  *     cpu_online_map   - has bit 'cpu' set iff cpu available to scheduler
  *  #else
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index a3ed5e0..4361f37 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -8,7 +8,6 @@
 #include <linux/spinlock.h>
 #include <linux/cache.h>
 #include <linux/rcupdate.h>
-#include <asm/bug.h>
 
 struct nameidata;
 struct vfsmount;
@@ -108,7 +107,9 @@
 	struct dentry_operations *d_op;
 	struct super_block *d_sb;	/* The root of the dentry tree */
 	void *d_fsdata;			/* fs-specific data */
+#ifdef CONFIG_PROFILING
 	struct dcookie_struct *d_cookie; /* cookie, if any */
+#endif
 	int d_mounted;
 	unsigned char d_iname[DNAME_INLINE_LEN_MIN];	/* small names */
 };
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 83c7d20..51e0e95 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -91,7 +91,7 @@
 };
 
 struct io_restrictions {
-	unsigned short		max_sectors;
+	unsigned int		max_sectors;
 	unsigned short		max_phys_segments;
 	unsigned short		max_hw_segments;
 	unsigned short		hardsect_size;
diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h
index b1999bf..b81e58b 100644
--- a/include/linux/dvb/video.h
+++ b/include/linux/dvb/video.h
@@ -135,7 +135,7 @@
 
 typedef struct video_spu_palette {      /* SPU Palette information */
 	int length;
-	uint8_t *palette;
+	uint8_t __user *palette;
 } video_spu_palette_t;
 
 
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 23fe746..18cf1f3 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -82,6 +82,7 @@
 extern void elv_dispatch_sort(request_queue_t *, struct request *);
 extern void elv_add_request(request_queue_t *, struct request *, int, int);
 extern void __elv_add_request(request_queue_t *, struct request *, int, int);
+extern void elv_insert(request_queue_t *, struct request *, int);
 extern int elv_merge(request_queue_t *, struct request **, struct bio *);
 extern void elv_merge_requests(request_queue_t *, struct request *,
 			       struct request *);
diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h
index dbd7bb4..0cf0bea 100644
--- a/include/linux/elfcore.h
+++ b/include/linux/elfcore.h
@@ -5,6 +5,7 @@
 #include <linux/signal.h>
 #include <linux/time.h>
 #include <linux/user.h>
+#include <linux/ptrace.h>
 
 struct elf_siginfo
 {
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 8a7c821..c52a637 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -23,6 +23,13 @@
 #define DN_ATTRIB	0x00000020	/* File changed attibutes */
 #define DN_MULTISHOT	0x80000000	/* Don't remove notifier */
 
+#define AT_FDCWD		-100    /* Special value used to indicate
+                                           openat should use the current
+                                           working directory. */
+#define AT_SYMLINK_NOFOLLOW	0x100   /* Do not follow symbolic links.  */
+#define AT_REMOVEDIR		0x200   /* Remove directory instead of
+                                           unlinking file.  */
+
 #ifdef __KERNEL__
 
 #ifndef force_o_largefile
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b77f260..e059da9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -363,6 +363,8 @@
 			loff_t offset, unsigned long nr_segs);
 	struct page* (*get_xip_page)(struct address_space *, sector_t,
 			int);
+	/* migrate the contents of a page to the specified target */
+	int (*migratepage) (struct page *, struct page *);
 };
 
 struct backing_dev_info;
@@ -1340,7 +1342,8 @@
 
 extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
 		       struct file *filp);
-extern long do_sys_open(const char __user *filename, int flags, int mode);
+extern long do_sys_open(int fdf, const char __user *filename, int flags,
+			int mode);
 extern struct file *filp_open(const char *, int, int);
 extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
 extern int filp_close(struct file *, fl_owner_t id);
@@ -1479,7 +1482,7 @@
 }
 extern int do_pipe(int *);
 
-extern int open_namei(const char *, int, int, struct nameidata *);
+extern int open_namei(int dfd, const char *, int, int, struct nameidata *);
 extern int may_open(struct nameidata *, int, int);
 
 extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
@@ -1677,6 +1680,8 @@
 
 extern int vfs_stat(char __user *, struct kstat *);
 extern int vfs_lstat(char __user *, struct kstat *);
+extern int vfs_stat_fd(int dfd, char __user *, struct kstat *);
+extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *);
 extern int vfs_fstat(unsigned int, struct kstat *);
 
 extern int vfs_ioctl(struct file *, unsigned int, unsigned int, unsigned long);
@@ -1716,6 +1721,12 @@
 
 extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t);
 
+#ifdef CONFIG_MIGRATION
+extern int buffer_migrate_page(struct page *, struct page *);
+#else
+#define buffer_migrate_page NULL
+#endif
+
 extern int inode_change_ok(struct inode *, struct iattr *);
 extern int __must_check inode_setattr(struct inode *, struct iattr *);
 
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 528959c..5425b60 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -14,7 +14,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 5
+#define FUSE_KERNEL_MINOR_VERSION 6
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -58,6 +58,9 @@
 	__u32	spare[6];
 };
 
+/**
+ * Bitmasks for fuse_setattr_in.valid
+ */
 #define FATTR_MODE	(1 << 0)
 #define FATTR_UID	(1 << 1)
 #define FATTR_GID	(1 << 2)
@@ -75,6 +78,11 @@
 #define FOPEN_DIRECT_IO		(1 << 0)
 #define FOPEN_KEEP_CACHE	(1 << 1)
 
+/**
+ * INIT request/reply flags
+ */
+#define FUSE_ASYNC_READ		(1 << 0)
+
 enum fuse_opcode {
 	FUSE_LOOKUP	   = 1,
 	FUSE_FORGET	   = 2,  /* no reply */
@@ -247,12 +255,16 @@
 struct fuse_init_in {
 	__u32	major;
 	__u32	minor;
+	__u32	max_readahead;
+	__u32	flags;
 };
 
 struct fuse_init_out {
 	__u32	major;
 	__u32	minor;
-	__u32	unused[3];
+	__u32	max_readahead;
+	__u32	flags;
+	__u32	unused;
 	__u32	max_write;
 };
 
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 089bfb1..6361544 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -40,6 +40,7 @@
 enum hrtimer_state {
 	HRTIMER_INACTIVE,	/* Timer is inactive */
 	HRTIMER_EXPIRED,		/* Timer is expired */
+	HRTIMER_RUNNING,		/* Timer is running the callback function */
 	HRTIMER_PENDING,		/* Timer is pending */
 };
 
@@ -100,9 +101,8 @@
 /* Exported timer functions: */
 
 /* Initialize timers: */
-extern void hrtimer_init(struct hrtimer *timer, const clockid_t which_clock);
-extern void hrtimer_rebase(struct hrtimer *timer, const clockid_t which_clock);
-
+extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
+			 enum hrtimer_mode mode);
 
 /* Basic timer operations: */
 extern int hrtimer_start(struct hrtimer *timer, ktime_t tim,
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 7863a59..63f1d63 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -100,6 +100,9 @@
 /* Returns the number of read bytes */
 extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
 					 u8 command, u8 *values);
+extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
+					  u8 command, u8 length,
+					  u8 *values);
 
 /*
  * A driver is capable of handling one or more physical devices present on
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index 9ba8067..5a9d8c5 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -1115,9 +1115,11 @@
 		return ERR_PTR(-ENOMEM);
 
 	mmsg->mfa = readl(c->in_port);
-	if (mmsg->mfa == I2O_QUEUE_EMPTY) {
+	if (unlikely(mmsg->mfa >= c->in_queue.len)) {
 		mempool_free(mmsg, c->in_msg.mempool);
-		return ERR_PTR(-EBUSY);
+		if(mmsg->mfa == I2O_QUEUE_EMPTY)
+			return ERR_PTR(-EBUSY);
+		return ERR_PTR(-EFAULT);
 	}
 
 	return &mmsg->msg;
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 110b3cf..a7fc4cc 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -582,7 +582,6 @@
 	unsigned noprobe 	: 1;	/* from:  hdx=noprobe */
 	unsigned removable	: 1;	/* 1 if need to do check_media_change */
 	unsigned attach		: 1;	/* needed for removable devices */
-	unsigned is_flash	: 1;	/* 1 if probed as flash */
 	unsigned forced_geom	: 1;	/* 1 if hdx=c,h,s was given at boot */
 	unsigned no_unmask	: 1;	/* disallow setting unmask bit */
 	unsigned no_io_32bit	: 1;	/* disallow enabling 32bit I/O */
@@ -1006,7 +1005,6 @@
 extern int noautodma;
 
 extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
-extern int __ide_end_request (ide_drive_t *drive, struct request *rq, int uptodate, int nrsecs);
 
 /*
  * This is used on exit from the driver to designate the next irq handler
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index fe26d43..7a92c1c 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -72,6 +72,7 @@
 					 * over Ethernet
 					 */
 #define ETH_P_AOE	0x88A2		/* ATA over Ethernet		*/
+#define ETH_P_TIPC	0x88CA		/* TIPC 			*/
 
 /*
  *	Non DIX types. Won't clash for 1500 types.
diff --git a/include/linux/io.h b/include/linux/io.h
new file mode 100644
index 0000000..85533ec
--- /dev/null
+++ b/include/linux/io.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 PathScale, Inc.  All Rights Reserved.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _LINUX_IO_H
+#define _LINUX_IO_H
+
+#include <asm/io.h>
+
+void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
+
+#endif /* _LINUX_IO_H */
diff --git a/include/linux/ioc3.h b/include/linux/ioc3.h
index e7906a7..da7c09e 100644
--- a/include/linux/ioc3.h
+++ b/include/linux/ioc3.h
@@ -27,7 +27,7 @@
 	int id;				/* IOC3 sequence number */
 	/* PCI mapping */
 	unsigned long pma;		/* physical address */
-	struct __iomem ioc3 *vma;	/* pointer to registers */
+	struct ioc3 __iomem *vma;	/* pointer to registers */
 	struct pci_dev *pdev;		/* PCI device */
 	/* IRQ stuff */
 	int dual_irq;			/* set if separate IRQs are used */
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 558cb4c..0fe4aa8 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -23,6 +23,7 @@
 #define jfs_debug jbd_debug
 #else
 
+#include <linux/types.h>
 #include <linux/buffer_head.h>
 #include <linux/journal-head.h>
 #include <linux/stddef.h>
@@ -238,7 +239,6 @@
 
 #include <linux/fs.h>
 #include <linux/sched.h>
-#include <asm/bug.h>
 
 #define JBD_ASSERTIONS
 #ifdef JBD_ASSERTIONS
@@ -618,6 +618,7 @@
  * @j_wbuf: array of buffer_heads for journal_commit_transaction
  * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the
  *	number that will fit in j_blocksize
+ * @j_last_sync_writer: most recent pid which did a synchronous write
  * @j_private: An opaque pointer to fs-private information.
  */
 
@@ -807,6 +808,8 @@
 	struct buffer_head	**j_wbuf;
 	int			j_wbufsize;
 
+	pid_t			j_last_sync_writer;
+
 	/*
 	 * An opaque pointer to fs-private information.  ext3 puts its
 	 * superblock pointer here
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index 45f625d..e87c32a 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -151,6 +151,13 @@
 
 static inline void con_schedule_flip(struct tty_struct *t)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&t->buf.lock, flags);
+	if (t->buf.tail != NULL) {
+		t->buf.tail->active = 0;
+		t->buf.tail->commit = t->buf.tail->used;
+	}
+	spin_unlock_irqrestore(&t->buf.lock, flags);
 	schedule_work(&t->buf.work);
 }
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index a536332..b49affa 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -185,6 +185,7 @@
 	SYSTEM_HALT,
 	SYSTEM_POWER_OFF,
 	SYSTEM_RESTART,
+	SYSTEM_SUSPEND_DISK,
 } system_state;
 
 #define TAINT_PROPRIETARY_MODULE	(1<<0)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index a311f58..cfb3410 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -6,6 +6,7 @@
 #include <linux/list.h>
 #include <linux/linkage.h>
 #include <linux/compat.h>
+#include <linux/ioport.h>
 #include <asm/kexec.h>
 
 /* Verify architecture specific macros are defined */
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 1bd6552..6aca67a 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -10,6 +10,12 @@
  *
  *  Started by: Thomas Gleixner and Ingo Molnar
  *
+ *  Credits:
+ *
+ *  	Roman Zippel provided the ideas and primary code snippets of
+ *  	the ktime_t union and further simplifications of the original
+ *  	code.
+ *
  *  For licencing details see kernel-base/COPYING
  */
 #ifndef _LINUX_KTIME_H
diff --git a/include/linux/list.h b/include/linux/list.h
index 945daa1..47208bd 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -34,9 +34,11 @@
 #define LIST_HEAD(name) \
 	struct list_head name = LIST_HEAD_INIT(name)
 
-#define INIT_LIST_HEAD(ptr) do { \
-	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+	list->next = list;
+	list->prev = list;
+}
 
 /*
  * Insert a new entry between two known consecutive entries.
@@ -534,7 +536,11 @@
 #define HLIST_HEAD_INIT { .first = NULL }
 #define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
 #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
-#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
+static inline void INIT_HLIST_NODE(struct hlist_node *h)
+{
+	h->next = NULL;
+	h->pprev = NULL;
+}
 
 static inline int hlist_unhashed(const struct hlist_node *h)
 {
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 95c8fea..920766c 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -84,6 +84,7 @@
 	struct nlm_args		a_args;		/* arguments */
 	struct nlm_res		a_res;		/* result */
 	struct nlm_wait *	a_block;
+	unsigned int		a_retries;	/* Retry count */
 	char			a_owner[NLMCLNT_OHSIZE];
 };
 
@@ -148,7 +149,6 @@
 int		  nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl);
 void		  nlmclnt_finish_block(struct nlm_rqst *req);
 long		  nlmclnt_block(struct nlm_rqst *req, long timeout);
-int		  nlmclnt_cancel(struct nlm_host *, struct file_lock *);
 u32		  nlmclnt_grant(struct nlm_lock *);
 void		  nlmclnt_recovery(struct nlm_host *, u32);
 int		  nlmclnt_reclaim(struct nlm_host *, struct file_lock *);
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index d6a53ed..bbd2221 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -159,6 +159,7 @@
 extern struct mempolicy default_policy;
 extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
 		unsigned long addr);
+extern unsigned slab_node(struct mempolicy *policy);
 
 extern int policy_zone;
 
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 85854b8..75e9f07 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -303,7 +303,7 @@
  */
 #define put_page_testzero(p)				\
 	({						\
-		BUG_ON(page_count(p) == 0);		\
+		BUG_ON(atomic_read(&(p)->_count) == -1);\
 		atomic_add_negative(-1, &(p)->_count);	\
 	})
 
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index 49cc68a..8ac854f 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -39,24 +39,3 @@
 	}
 }
 
-/*
- * Isolate one page from the LRU lists.
- *
- * - zone->lru_lock must be held
- */
-static inline int __isolate_lru_page(struct page *page)
-{
-	if (unlikely(!TestClearPageLRU(page)))
-		return 0;
-
-	if (get_page_testone(page)) {
-		/*
-		 * It is being freed elsewhere
-		 */
-		__put_page(page);
-		SetPageLRU(page);
-		return -ENOENT;
-	}
-
-	return 1;
-}
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index ccd3e13..f38872a 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -21,24 +21,35 @@
 	u32			arg;
 	u32			resp[4];
 	unsigned int		flags;		/* expected response type */
-#define MMC_RSP_NONE	(0 << 0)
-#define MMC_RSP_SHORT	(1 << 0)
-#define MMC_RSP_LONG	(2 << 0)
-#define MMC_RSP_MASK	(3 << 0)
-#define MMC_RSP_CRC	(1 << 3)		/* expect valid crc */
-#define MMC_RSP_BUSY	(1 << 4)		/* card may send busy */
-#define MMC_RSP_OPCODE	(1 << 5)		/* response contains opcode */
+#define MMC_RSP_PRESENT	(1 << 0)
+#define MMC_RSP_136	(1 << 1)		/* 136 bit response */
+#define MMC_RSP_CRC	(1 << 2)		/* expect valid crc */
+#define MMC_RSP_BUSY	(1 << 3)		/* card may send busy */
+#define MMC_RSP_OPCODE	(1 << 4)		/* response contains opcode */
+#define MMC_CMD_MASK	(3 << 5)		/* command type */
+#define MMC_CMD_AC	(0 << 5)
+#define MMC_CMD_ADTC	(1 << 5)
+#define MMC_CMD_BC	(2 << 5)
+#define MMC_CMD_BCR	(3 << 5)
 
 /*
  * These are the response types, and correspond to valid bit
  * patterns of the above flags.  One additional valid pattern
  * is all zeros, which means we don't expect a response.
  */
-#define MMC_RSP_R1	(MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMC_RSP_R1B	(MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
-#define MMC_RSP_R2	(MMC_RSP_LONG|MMC_RSP_CRC)
-#define MMC_RSP_R3	(MMC_RSP_SHORT)
-#define MMC_RSP_R6	(MMC_RSP_SHORT|MMC_RSP_CRC)
+#define MMC_RSP_NONE	(0)
+#define MMC_RSP_R1	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R1B	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
+#define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
+#define MMC_RSP_R3	(MMC_RSP_PRESENT)
+#define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC)
+
+#define mmc_resp_type(cmd)	((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
+
+/*
+ * These are the command types.
+ */
+#define mmc_cmd_type(cmd)	((cmd)->flags & MMC_CMD_TYPE)
 
 	unsigned int		retries;	/* max number of retries */
 	unsigned int		error;		/* command error */
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index a14dc30..81c3f77 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -79,7 +79,7 @@
 /* SD commands                           type  argument     response */
   /* class 8 */
 /* This is basically the same command as for MMC with some quirks. */
-#define SD_SEND_RELATIVE_ADDR     3   /* ac                      R6  */
+#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
 
   /* Application commands */
 #define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 34cbefd..ebfc238 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -91,10 +91,21 @@
  * be 8 (2 ** 3) zonelists.  GFP_ZONETYPES defines the number of possible
  * combinations of zone modifiers in "zone modifier space".
  *
+ * As an optimisation any zone modifier bits which are only valid when
+ * no other zone modifier bits are set (loners) should be placed in
+ * the highest order bits of this field.  This allows us to reduce the
+ * extent of the zonelists thus saving space.  For example in the case
+ * of three zone modifier bits, we could require up to eight zonelists.
+ * If the left most zone modifier is a "loner" then the highest valid
+ * zonelist would be four allowing us to allocate only five zonelists.
+ * Use the first form for GFP_ZONETYPES when the left most bit is not
+ * a "loner", otherwise use the second.
+ *
  * NOTE! Make sure this matches the zones in <linux/gfp.h>
  */
 #define GFP_ZONEMASK	0x07
-#define GFP_ZONETYPES	5
+/* #define GFP_ZONETYPES       (GFP_ZONEMASK + 1) */           /* Non-loner */
+#define GFP_ZONETYPES  ((GFP_ZONEMASK + 1) / 2 + 1)            /* Loner */
 
 /*
  * On machines where it is needed (eg PCs) we divide physical memory
@@ -149,15 +160,17 @@
 	unsigned long		pages_scanned;	   /* since last reclaim */
 	int			all_unreclaimable; /* All pages pinned */
 
-	/*
-	 * Does the allocator try to reclaim pages from the zone as soon
-	 * as it fails a watermark_ok() in __alloc_pages?
-	 */
-	int			reclaim_pages;
 	/* A count of how many reclaimers are scanning this zone */
 	atomic_t		reclaim_in_progress;
 
 	/*
+	 * timestamp (in jiffies) of the last zone reclaim that did not
+	 * result in freeing of pages. This is used to avoid repeated scans
+	 * if all memory in the zone is in use.
+	 */
+	unsigned long		last_unsuccessful_zone_reclaim;
+
+	/*
 	 * prev_priority holds the scanning priority for this zone.  It is
 	 * defined as the scanning priority at which we achieved our reclaim
 	 * target at the previous try_to_free_pages() or balance_pgdat()
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index fedfbc8..7dfd6e1 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -15,7 +15,6 @@
 #include <asm/unaligned.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/bug.h>
 
 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
 #define map_bankwidth(map) 1
diff --git a/include/linux/namei.h b/include/linux/namei.h
index b699e42..e669801 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -56,10 +56,11 @@
 #define LOOKUP_ACCESS		(0x0400)
 
 extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
+extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *));
 #define user_path_walk(name,nd) \
-	__user_walk(name, LOOKUP_FOLLOW, nd)
+	__user_walk_fd(AT_FDCWD, name, LOOKUP_FOLLOW, nd)
 #define user_path_walk_link(name,nd) \
-	__user_walk(name, 0, nd)
+	__user_walk_fd(AT_FDCWD, name, 0, nd)
 extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
 extern int FASTCALL(path_walk(const char *, struct nameidata *));
 extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
@@ -67,7 +68,7 @@
 extern void path_release_on_umount(struct nameidata *);
 
 extern int __user_path_lookup_open(const char __user *, unsigned lookup_flags, struct nameidata *nd, int open_flags);
-extern int path_lookup_open(const char *, unsigned lookup_flags, struct nameidata *, int open_flags);
+extern int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags);
 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
 		int (*open)(struct inode *, struct file *));
 extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
diff --git a/include/linux/namespace.h b/include/linux/namespace.h
index 6731977..3abc8e3 100644
--- a/include/linux/namespace.h
+++ b/include/linux/namespace.h
@@ -15,6 +15,7 @@
 
 extern int copy_namespace(int, struct task_struct *);
 extern void __put_namespace(struct namespace *namespace);
+extern struct namespace *dup_namespace(struct task_struct *, struct fs_struct *);
 
 static inline void put_namespace(struct namespace *namespace)
 {
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 472f048..6500d4e 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -19,7 +19,21 @@
 /* For standard target */
 #define XT_RETURN (-NF_REPEAT - 1)
 
-#define XT_ALIGN(s) (((s) + (__alignof__(void *)-1)) & ~(__alignof__(void *)-1))
+/* this is a dummy structure to find out the alignment requirement for a struct
+ * containing all the fundamental data types that are used in ipt_entry,
+ * ip6t_entry and arpt_entry.  This sucks, and it is a hack.  It will be my
+ * personal pleasure to remove it -HW
+ */
+struct _xt_align
+{
+	u_int8_t u8;
+	u_int16_t u16;
+	u_int32_t u32;
+	u_int64_t u64;
+};
+
+#define XT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) 	\
+			& ~(__alignof__(struct _xt_align)-1))
 
 /* Standard return verdict, or do jump. */
 #define XT_STANDARD_TARGET ""
diff --git a/include/linux/netfilter_ipv4/ipt_connbytes.h b/include/linux/netfilter_ipv4/ipt_connbytes.h
index b04dfa3..f63e6ee 100644
--- a/include/linux/netfilter_ipv4/ipt_connbytes.h
+++ b/include/linux/netfilter_ipv4/ipt_connbytes.h
@@ -1,10 +1,10 @@
 #ifndef _IPT_CONNBYTES_H
 #define _IPT_CONNBYTES_H
 
-#include <net/netfilter/xt_connbytes.h>
+#include <linux/netfilter/xt_connbytes.h>
 #define ipt_connbytes_what xt_connbytes_what
 
-#define IPT_CONNBYTES_PKTS	XT_CONNBYTES_PACKETS
+#define IPT_CONNBYTES_PKTS	XT_CONNBYTES_PKTS
 #define IPT_CONNBYTES_BYTES	XT_CONNBYTES_BYTES
 #define IPT_CONNBYTES_AVGPKT	XT_CONNBYTES_AVGPKT
 
diff --git a/include/linux/netfilter_ipv4/ipt_policy.h b/include/linux/netfilter_ipv4/ipt_policy.h
index 7fd1bec..a3f6eff 100644
--- a/include/linux/netfilter_ipv4/ipt_policy.h
+++ b/include/linux/netfilter_ipv4/ipt_policy.h
@@ -27,16 +27,22 @@
 			reqid:1;
 };
 
+union ipt_policy_addr
+{
+	struct in_addr	a4;
+	struct in6_addr	a6;
+};
+
 struct ipt_policy_elem
 {
-	u_int32_t	saddr;
-	u_int32_t	smask;
-	u_int32_t	daddr;
-	u_int32_t	dmask;
-	u_int32_t	spi;
-	u_int32_t	reqid;
-	u_int8_t	proto;
-	u_int8_t	mode;
+	union ipt_policy_addr	saddr;
+	union ipt_policy_addr	smask;
+	union ipt_policy_addr	daddr;
+	union ipt_policy_addr	dmask;
+	u_int32_t		spi;
+	u_int32_t		reqid;
+	u_int8_t		proto;
+	u_int8_t		mode;
 
 	struct ipt_policy_spec	match;
 	struct ipt_policy_spec	invert;
diff --git a/include/linux/netfilter_ipv6/ip6t_policy.h b/include/linux/netfilter_ipv6/ip6t_policy.h
index 5a93afc..671bd81 100644
--- a/include/linux/netfilter_ipv6/ip6t_policy.h
+++ b/include/linux/netfilter_ipv6/ip6t_policy.h
@@ -27,16 +27,22 @@
 			reqid:1;
 };
 
+union ip6t_policy_addr
+{
+	struct in_addr	a4;
+	struct in6_addr	a6;
+};
+
 struct ip6t_policy_elem
 {
-	struct in6_addr	saddr;
-	struct in6_addr	smask;
-	struct in6_addr	daddr;
-	struct in6_addr	dmask;
-	u_int32_t	spi;
-	u_int32_t	reqid;
-	u_int8_t	proto;
-	u_int8_t	mode;
+	union ip6t_policy_addr	saddr;
+	union ip6t_policy_addr	smask;
+	union ip6t_policy_addr	daddr;
+	union ip6t_policy_addr	dmask;
+	u_int32_t		spi;
+	u_int32_t		reqid;
+	u_int8_t		proto;
+	u_int8_t		mode;
 
 	struct ip6t_policy_spec	match;
 	struct ip6t_policy_spec	invert;
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 6a2ccf7..c256ebe 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -160,7 +160,8 @@
 
 /* finegrained unicast helpers: */
 struct sock *netlink_getsockbyfilp(struct file *filp);
-int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo);
+int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
+		long timeo, struct sock *ssk);
 void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
 int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
 
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 51c231a..ec7c2e8 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -124,7 +124,7 @@
 
 int		nfsd_notify_change(struct inode *, struct iattr *);
 int		nfsd_permission(struct svc_export *, struct dentry *, int);
-void		nfsd_sync_dir(struct dentry *dp);
+int		nfsd_sync_dir(struct dentry *dp);
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 #ifdef CONFIG_NFSD_V2_ACL
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 8903688..77adba7 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -145,8 +145,9 @@
 		} ok;
 		struct nfsd4_lock_denied        denied;
 	} u;
-
-	struct nfs4_stateowner *lk_stateowner;
+	/* The lk_replay_owner is the open owner in the open_to_lock_owner
+	 * case and the lock owner otherwise: */
+	struct nfs4_stateowner *lk_replay_owner;
 };
 #define lk_new_open_seqid       v.new.open_seqid
 #define lk_new_open_stateid     v.new.open_stateid
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 4726ef7..b959a45 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -84,7 +84,6 @@
 #include <linux/threads.h>
 #include <linux/bitmap.h>
 #include <linux/numa.h>
-#include <asm/bug.h>
 
 typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t;
 extern nodemask_t _unused_nodemask_arg_;
diff --git a/include/linux/parport.h b/include/linux/parport.h
index f67f838..008d736 100644
--- a/include/linux/parport.h
+++ b/include/linux/parport.h
@@ -128,6 +128,11 @@
        unsigned char statusdir;/* ciab.ddrb & 7 */
 };
 
+struct ip32_parport_state {
+	unsigned int dcr;
+	unsigned int ecr;
+};
+
 struct parport_state {
 	union {
 		struct pc_parport_state pc;
@@ -135,6 +140,7 @@
 		struct ax_parport_state ax;
 		struct amiga_parport_state amiga;
 		/* Atari has not state. */
+		struct ip32_parport_state ip32;
 		void *misc; 
 	} u;
 };
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0a44072..fe1a2b0 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -406,7 +406,6 @@
 struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
 int pci_find_capability (struct pci_dev *dev, int cap);
 int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
-int pci_find_ext_capability (struct pci_dev *dev, int cap);
 struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
 
 struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
@@ -626,7 +625,6 @@
 static inline void pci_unregister_driver(struct pci_driver *drv) { }
 static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
-static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
 
 /* Power management related routines */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 5403257..82b83da 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -394,14 +394,9 @@
 #define PCI_DEVICE_ID_NS_SC1100_SMI	0x0511
 #define PCI_DEVICE_ID_NS_SC1100_XBUS	0x0515
 #define PCI_DEVICE_ID_NS_87410		0xd001
-#define PCI_DEVICE_ID_NS_CS5535_IDE	0x002d
 
 #define PCI_DEVICE_ID_NS_CS5535_HOST_BRIDGE  0x0028
 #define PCI_DEVICE_ID_NS_CS5535_ISA_BRIDGE   0x002b
-#define PCI_DEVICE_ID_NS_CS5535_IDE          0x002d
-#define PCI_DEVICE_ID_NS_CS5535_AUDIO        0x002e
-#define PCI_DEVICE_ID_NS_CS5535_USB          0x002f
-#define PCI_DEVICE_ID_NS_CS5535_VIDEO        0x0030
 
 #define PCI_VENDOR_ID_TSENG		0x100c
 #define PCI_DEVICE_ID_TSENG_W32P_2	0x3202
@@ -511,8 +506,6 @@
 #define PCI_DEVICE_ID_AMD_CS5536_UOC    0x2097
 #define PCI_DEVICE_ID_AMD_CS5536_IDE    0x209A
 
-#define PCI_DEVICE_ID_AMD_CS5536_IDE	0x209A
-
 #define PCI_DEVICE_ID_AMD_LX_VIDEO  0x2081
 #define PCI_DEVICE_ID_AMD_LX_AES    0x2082
 
@@ -1094,6 +1087,7 @@
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000   0x0185
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO    0x0186
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO    0x0187
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL    0x0188
@@ -1677,6 +1671,9 @@
 #define PCI_DEVICE_ID_SIIG_2S1P_20x_550	0x2060
 #define PCI_DEVICE_ID_SIIG_2S1P_20x_650	0x2061
 #define PCI_DEVICE_ID_SIIG_2S1P_20x_850	0x2062
+#define PCI_DEVICE_ID_SIIG_8S_20x_550	0x2080
+#define PCI_DEVICE_ID_SIIG_8S_20x_650	0x2081
+#define PCI_DEVICE_ID_SIIG_8S_20x_850	0x2082
 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL	0x2050
 
 #define PCI_VENDOR_ID_RADISYS		0x1331
@@ -1836,6 +1833,7 @@
 #define PCI_VENDOR_ID_AFAVLAB		0x14db
 #define PCI_DEVICE_ID_AFAVLAB_P028	0x2180
 #define PCI_DEVICE_ID_AFAVLAB_P030	0x2182
+#define PCI_SUBDEVICE_ID_AFAVLAB_P061		0x2150
 
 #define PCI_VENDOR_ID_BROADCOM		0x14e4
 #define PCI_DEVICE_ID_TIGON3_5752	0x1600
@@ -1992,6 +1990,7 @@
 #define PCI_VENDOR_ID_DCI		0x6666
 #define PCI_DEVICE_ID_DCI_PCCOM4	0x0001
 #define PCI_DEVICE_ID_DCI_PCCOM8	0x0002
+#define PCI_DEVICE_ID_DCI_PCCOM2	0x0004
 
 #define PCI_VENDOR_ID_INTEL		0x8086
 #define PCI_DEVICE_ID_INTEL_EESSC	0x0008
@@ -2064,6 +2063,7 @@
 #define PCI_DEVICE_ID_INTEL_82801EB_5	0x24d5
 #define PCI_DEVICE_ID_INTEL_82801EB_6	0x24d6
 #define PCI_DEVICE_ID_INTEL_82801EB_11	0x24db
+#define PCI_DEVICE_ID_INTEL_82801EB_13	0x24dd
 #define PCI_DEVICE_ID_INTEL_ESB_1	0x25a1
 #define PCI_DEVICE_ID_INTEL_ESB_2	0x25a2
 #define PCI_DEVICE_ID_INTEL_ESB_4	0x25a4
@@ -2084,6 +2084,8 @@
 #define PCI_DEVICE_ID_INTEL_82915GM_IG	0x2592
 #define PCI_DEVICE_ID_INTEL_82945G_HB	0x2770
 #define PCI_DEVICE_ID_INTEL_82945G_IG	0x2772
+#define PCI_DEVICE_ID_INTEL_82945GM_HB	0x27A0
+#define PCI_DEVICE_ID_INTEL_82945GM_IG	0x27A2
 #define PCI_DEVICE_ID_INTEL_ICH6_0	0x2640
 #define PCI_DEVICE_ID_INTEL_ICH6_1	0x2641
 #define PCI_DEVICE_ID_INTEL_ICH6_2	0x2642
@@ -2103,6 +2105,13 @@
 #define PCI_DEVICE_ID_INTEL_ICH7_19	0x27dd
 #define PCI_DEVICE_ID_INTEL_ICH7_20	0x27de
 #define PCI_DEVICE_ID_INTEL_ICH7_21	0x27df
+#define PCI_DEVICE_ID_INTEL_ICH8_0	0x2810
+#define PCI_DEVICE_ID_INTEL_ICH8_1	0x2811
+#define PCI_DEVICE_ID_INTEL_ICH8_2	0x2812
+#define PCI_DEVICE_ID_INTEL_ICH8_3	0x2814
+#define PCI_DEVICE_ID_INTEL_ICH8_4	0x2815
+#define PCI_DEVICE_ID_INTEL_ICH8_5	0x283e
+#define PCI_DEVICE_ID_INTEL_ICH8_6	0x2850
 #define PCI_DEVICE_ID_INTEL_82855PM_HB	0x3340
 #define PCI_DEVICE_ID_INTEL_82830_HB	0x3575
 #define PCI_DEVICE_ID_INTEL_82830_CGC	0x3577
@@ -2146,6 +2155,7 @@
 #define PCI_DEVICE_ID_INTEL_82443GX_2	0x71a2
 #define PCI_DEVICE_ID_INTEL_82372FB_1	0x7601
 #define PCI_DEVICE_ID_INTEL_82454GX	0x84c4
+#define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
 #define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
 #define PCI_DEVICE_ID_INTEL_84460GX	0x84ea
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index 2c177e4..8a94c71 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -114,7 +114,7 @@
 
 struct packet_settings
 {
-	__u8			size;		/* packet size in (512 byte) sectors */
+	__u32			size;		/* packet size in (512 byte) sectors */
 	__u8			fp;		/* fixed packets */
 	__u8			link_loss;	/* the rest is specified
 						 * as per Mt Fuji */
@@ -169,8 +169,8 @@
 #if (PAGE_SIZE % CD_FRAMESIZE) != 0
 #error "PAGE_SIZE must be a multiple of CD_FRAMESIZE"
 #endif
-#define PACKET_MAX_SIZE		32
-#define PAGES_PER_PACKET	(PACKET_MAX_SIZE * CD_FRAMESIZE / PAGE_SIZE)
+#define PACKET_MAX_SIZE		128
+#define FRAMES_PER_PAGE		(PAGE_SIZE / CD_FRAMESIZE)
 #define PACKET_MAX_SECTORS	(PACKET_MAX_SIZE * CD_FRAMESIZE >> 9)
 
 enum packet_data_state {
@@ -219,7 +219,7 @@
 	atomic_t		io_errors;	/* Number of read/write errors during IO */
 
 	struct bio		*r_bios[PACKET_MAX_SIZE]; /* bios to use during data gathering */
-	struct page		*pages[PAGES_PER_PACKET];
+	struct page		*pages[PACKET_MAX_SIZE / FRAMES_PER_PAGE];
 
 	int			cache_valid;	/* If non-zero, the data for the zone defined */
 						/* by the sector variable is completely cached */
diff --git a/include/linux/poll.h b/include/linux/poll.h
index f6da702..8e8f609 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -92,7 +92,11 @@
 	memset(fdset, 0, FDS_BYTES(nr));
 }
 
-extern int do_select(int n, fd_set_bits *fds, long *timeout);
+#define MAX_INT64_SECONDS (((s64)(~((u64)0)>>1)/HZ)-1)
+
+extern int do_select(int n, fd_set_bits *fds, s64 *timeout);
+extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds,
+		       s64 *timeout);
 
 #endif /* KERNEL */
 
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 54faf52..95572c4 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -84,7 +84,6 @@
 void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock);
 
 /* error handlers for timer_create, nanosleep and settime */
-int do_posix_clock_notimer_create(struct k_itimer *timer);
 int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *,
 			       struct timespec __user *);
 int do_posix_clock_nosettime(const clockid_t, struct timespec *tp);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 4f34d3d..21e5a91 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -190,7 +190,6 @@
  */
 #define sb_dquot_ops				(NULL)
 #define sb_quotactl_ops				(NULL)
-#define sync_dquots_dev(dev,type)		(NULL)
 #define DQUOT_INIT(inode)			do { } while(0)
 #define DQUOT_DROP(inode)			do { } while(0)
 #define DQUOT_ALLOC_INODE(inode)		(0)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 981f9aa..b87aefa 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -240,11 +240,14 @@
  * This means that all preempt_disable code sequences, including NMI and
  * hardware-interrupt handlers, in progress on entry will have completed
  * before this primitive returns.  However, this does not guarantee that
- * softirq handlers will have completed, since in some kernels
+ * softirq handlers will have completed, since in some kernels, these
+ * handlers can run in process context, and can block.
  *
  * This primitive provides the guarantees made by the (deprecated)
  * synchronize_kernel() API.  In contrast, synchronize_rcu() only
  * guarantees that rcu_read_lock() sections will have completed.
+ * In "classic RCU", these two guarantees happen to be one and
+ * the same, but can differ in realtime RCU implementations.
  */
 #define synchronize_sched() synchronize_rcu()
 
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 7ab2cdb..015297f 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -60,8 +60,7 @@
  */
 
 extern void kernel_restart_prepare(char *cmd);
-extern void kernel_halt_prepare(void);
-extern void kernel_power_off_prepare(void);
+extern void kernel_shutdown_prepare(enum system_states state);
 
 extern void kernel_restart(char *cmd);
 extern void kernel_halt(void);
diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h
index 0a36050..806ec5b 100644
--- a/include/linux/reiserfs_acl.h
+++ b/include/linux/reiserfs_acl.h
@@ -58,9 +58,13 @@
 extern struct reiserfs_xattr_handler posix_acl_access_handler;
 #else
 
-#define reiserfs_get_acl NULL
 #define reiserfs_cache_default_acl(inode) 0
 
+static inline struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
+{
+	return NULL;
+}
+
 static inline int reiserfs_xattr_posix_acl_init(void)
 {
 	return 0;
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index e276c5b..7d51149 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1971,22 +1971,6 @@
 extern struct address_space_operations reiserfs_address_space_operations;
 
 /* fix_nodes.c */
-#ifdef CONFIG_REISERFS_CHECK
-void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s);
-void reiserfs_kfree(const void *vp, size_t size, struct super_block *s);
-#else
-static inline void *reiserfs_kmalloc(size_t size, int flags,
-				     struct super_block *s)
-{
-	return kmalloc(size, flags);
-}
-
-static inline void reiserfs_kfree(const void *vp, size_t size,
-				  struct super_block *s)
-{
-	kfree(vp);
-}
-#endif
 
 int fix_nodes(int n_op_mode, struct tree_balance *p_s_tb,
 	      struct item_head *p_s_ins_ih, const void *);
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 3e68592..31b4c0b 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -382,7 +382,6 @@
 					   on-disk FS format */
 
 	/* session statistics */
-	int s_kmallocs;
 	int s_disk_reads;
 	int s_disk_writes;
 	int s_fix_nodes;
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index c84354e..87280eb 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -43,8 +43,6 @@
 int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
 int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
 int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd);
-int reiserfs_permission_locked(struct inode *inode, int mask,
-			       struct nameidata *nd);
 
 int reiserfs_xattr_del(struct inode *, const char *);
 int reiserfs_xattr_get(const struct inode *, const char *, void *, size_t);
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 9d6fbee..d6b9bcd 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -91,7 +91,8 @@
  * Called from mm/vmscan.c to handle paging out
  */
 int page_referenced(struct page *, int is_locked);
-int try_to_unmap(struct page *);
+int try_to_unmap(struct page *, int ignore_refs);
+void remove_from_swap(struct page *page);
 
 /*
  * Called from mm/filemap_xip.c to unmap empty zero page
@@ -111,7 +112,7 @@
 #define anon_vma_link(vma)	do {} while (0)
 
 #define page_referenced(page,l) TestClearPageReferenced(page)
-#define try_to_unmap(page)	SWAP_FAIL
+#define try_to_unmap(page, refs) SWAP_FAIL
 
 #endif	/* CONFIG_MMU */
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2df1a1a..9c1da02 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -809,6 +809,7 @@
 	struct sighand_struct *sighand;
 
 	sigset_t blocked, real_blocked;
+	sigset_t saved_sigmask;		/* To be restored with TIF_RESTORE_SIGMASK */
 	struct sigpending pending;
 
 	unsigned long sas_ss_sp;
@@ -1097,7 +1098,7 @@
 extern void sigqueue_free(struct sigqueue *);
 extern int send_sigqueue(int, struct sigqueue *,  struct task_struct *);
 extern int send_group_sigqueue(int, struct sigqueue *,  struct task_struct *);
-extern int do_sigaction(int, const struct k_sigaction *, struct k_sigaction *);
+extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *);
 extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long);
 
 /* These can be the second arg to send_sig_info/send_group_sig_info.  */
diff --git a/include/linux/security.h b/include/linux/security.h
index ef75365..7cbef48 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1499,15 +1499,11 @@
 
 static inline int security_inode_alloc (struct inode *inode)
 {
-	if (unlikely (IS_PRIVATE (inode)))
-		return 0;
 	return security_ops->inode_alloc_security (inode);
 }
 
 static inline void security_inode_free (struct inode *inode)
 {
-	if (unlikely (IS_PRIVATE (inode)))
-		return;
 	security_ops->inode_free_security (inode);
 }
 
@@ -2617,6 +2613,25 @@
 	return cap_netlink_recv (skb);
 }
 
+static inline struct dentry *securityfs_create_dir(const char *name,
+					struct dentry *parent)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline struct dentry *securityfs_create_file(const char *name,
+						mode_t mode,
+						struct dentry *parent,
+						void *data,
+						struct file_operations *fops)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline void securityfs_remove(struct dentry *dentry)
+{
+}
+
 #endif	/* CONFIG_SECURITY */
 
 #ifdef CONFIG_SECURITY_NETWORK
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index cee302a..73b464f 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -26,7 +26,7 @@
 	unsigned char	regshift;	/* register shift */
 	unsigned char	iotype;		/* UPIO_* */
 	unsigned char	hub6;
-	unsigned int	flags;		/* UPF_* flags */
+	upf_t		flags;		/* UPF_* flags */
 };
 
 /*
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index ec35100..4041122 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -203,6 +203,8 @@
 	__u32	buf_overrun;
 };
 
+typedef unsigned int __bitwise__ upf_t;
+
 struct uart_port {
 	spinlock_t		lock;			/* port lock */
 	unsigned int		iobase;			/* in/out[bwl] */
@@ -230,36 +232,34 @@
 	unsigned long		sysrq;			/* sysrq timeout */
 #endif
 
-	unsigned int		flags;
+	upf_t			flags;
 
-#define UPF_FOURPORT		(1 << 1)
-#define UPF_SAK			(1 << 2)
-#define UPF_SPD_MASK		(0x1030)
-#define UPF_SPD_HI		(0x0010)
-#define UPF_SPD_VHI		(0x0020)
-#define UPF_SPD_CUST		(0x0030)
-#define UPF_SPD_SHI		(0x1000)
-#define UPF_SPD_WARP		(0x1010)
-#define UPF_SKIP_TEST		(1 << 6)
-#define UPF_AUTO_IRQ		(1 << 7)
-#define UPF_HARDPPS_CD		(1 << 11)
-#define UPF_LOW_LATENCY		(1 << 13)
-#define UPF_BUGGY_UART		(1 << 14)
-#define UPF_AUTOPROBE		(1 << 15)
-#define UPF_MAGIC_MULTIPLIER	(1 << 16)
-#define UPF_BOOT_ONLYMCA	(1 << 22)
-#define UPF_CONS_FLOW		(1 << 23)
-#define UPF_SHARE_IRQ		(1 << 24)
-#define UPF_BOOT_AUTOCONF	(1 << 28)
-#define UPF_IOREMAP		(1 << 31)
+#define UPF_FOURPORT		((__force upf_t) (1 << 1))
+#define UPF_SAK			((__force upf_t) (1 << 2))
+#define UPF_SPD_MASK		((__force upf_t) (0x1030))
+#define UPF_SPD_HI		((__force upf_t) (0x0010))
+#define UPF_SPD_VHI		((__force upf_t) (0x0020))
+#define UPF_SPD_CUST		((__force upf_t) (0x0030))
+#define UPF_SPD_SHI		((__force upf_t) (0x1000))
+#define UPF_SPD_WARP		((__force upf_t) (0x1010))
+#define UPF_SKIP_TEST		((__force upf_t) (1 << 6))
+#define UPF_AUTO_IRQ		((__force upf_t) (1 << 7))
+#define UPF_HARDPPS_CD		((__force upf_t) (1 << 11))
+#define UPF_LOW_LATENCY		((__force upf_t) (1 << 13))
+#define UPF_BUGGY_UART		((__force upf_t) (1 << 14))
+#define UPF_MAGIC_MULTIPLIER	((__force upf_t) (1 << 16))
+#define UPF_CONS_FLOW		((__force upf_t) (1 << 23))
+#define UPF_SHARE_IRQ		((__force upf_t) (1 << 24))
+#define UPF_BOOT_AUTOCONF	((__force upf_t) (1 << 28))
+#define UPF_IOREMAP		((__force upf_t) (1 << 31))
 
-#define UPF_CHANGE_MASK		(0x17fff)
-#define UPF_USR_MASK		(UPF_SPD_MASK|UPF_LOW_LATENCY)
+#define UPF_CHANGE_MASK		((__force upf_t) (0x17fff))
+#define UPF_USR_MASK		((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
 
 	unsigned int		mctrl;			/* current modem ctrl settings */
 	unsigned int		timeout;		/* character-based timeout */
 	unsigned int		type;			/* port type */
-	struct uart_ops		*ops;
+	const struct uart_ops	*ops;
 	unsigned int		custom_divisor;
 	unsigned int		line;			/* port index */
 	unsigned long		mapbase;		/* for ioremap */
@@ -289,6 +289,9 @@
 };
 
 #define UART_XMIT_SIZE	PAGE_SIZE
+
+typedef unsigned int __bitwise__ uif_t;
+
 /*
  * This is the state information which is only valid when the port
  * is open; it may be freed by the core driver once the device has
@@ -298,17 +301,16 @@
 struct uart_info {
 	struct tty_struct	*tty;
 	struct circ_buf		xmit;
-	unsigned int		flags;
+	uif_t			flags;
 
 /*
- * These are the flags that specific to info->flags, and reflect our
- * internal state.  They can not be accessed via port->flags.  Low
- * level drivers must not change these, but may query them instead.
+ * Definitions for info->flags.  These are _private_ to serial_core, and
+ * are specific to this structure.  They may be queried by low level drivers.
  */
-#define UIF_CHECK_CD		(1 << 25)
-#define UIF_CTS_FLOW		(1 << 26)
-#define UIF_NORMAL_ACTIVE	(1 << 29)
-#define UIF_INITIALIZED		(1 << 31)
+#define UIF_CHECK_CD		((__force uif_t) (1 << 25))
+#define UIF_CTS_FLOW		((__force uif_t) (1 << 26))
+#define UIF_NORMAL_ACTIVE	((__force uif_t) (1 << 29))
+#define UIF_INITIALIZED		((__force uif_t) (1 << 31))
 
 	int			blocked_open;
 
@@ -430,7 +432,7 @@
 		port->sysrq = 0;
 	}
 #endif
-	if (info->flags & UPF_SAK)
+	if (port->flags & UPF_SAK)
 		do_SAK(info->tty);
 	return 0;
 }
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 1fb77a9..8cf5293 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -76,7 +76,14 @@
 	kmem_cache_t	*cs_dmacachep;
 };
 extern struct cache_sizes malloc_sizes[];
+
+#ifndef CONFIG_DEBUG_SLAB
 extern void *__kmalloc(size_t, gfp_t);
+#else
+extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
+#define __kmalloc(size, flags) \
+    __kmalloc_track_caller(size, flags, __builtin_return_address(0))
+#endif
 
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 9dfa3ee..44153fd 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -17,7 +17,6 @@
 #include <linux/compiler.h>
 #include <linux/thread_info.h>
 #include <asm/smp.h>
-#include <asm/bug.h>
 
 /*
  * main cross-CPU interfaces, handles INIT, TLB flush, STOP, etc.
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index b68c11a..be4772e 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -48,7 +48,7 @@
 
 	/* per-flavor data */
 };
-#define RPCAUTH_CRED_LOCKED	0x0001
+#define RPCAUTH_CRED_NEW	0x0001
 #define RPCAUTH_CRED_UPTODATE	0x0002
 
 #define RPCAUTH_CRED_MAGIC	0x0f4aa4f0
@@ -83,9 +83,10 @@
 	struct rpc_cred_cache *	au_credcache;
 	/* per-flavor data */
 };
-#define RPC_AUTH_PROC_CREDS	0x0010		/* process creds (including
-						 * uid/gid, fs[ug]id, gids)
-						 */
+
+/* Flags for rpcauth_lookupcred() */
+#define RPCAUTH_LOOKUP_NEW		0x01	/* Accept an uninitialised cred */
+#define RPCAUTH_LOOKUP_ROOTCREDS	0x02	/* This really ought to go! */
 
 /*
  * Client authentication ops
@@ -105,6 +106,7 @@
 
 struct rpc_credops {
 	const char *		cr_name;	/* Name of the auth flavour */
+	int			(*cr_init)(struct rpc_auth *, struct rpc_cred *);
 	void			(*crdestroy)(struct rpc_cred *);
 
 	int			(*crmatch)(struct auth_cred *, struct rpc_cred *, int);
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index e4086ec..50cab2a 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -246,6 +246,7 @@
 	u32			prot;	/* protocol (UDP or TCP) */
 	struct sockaddr_in	addr;
 	struct svc_sock		*svsk;	/* where reply must go */
+	u32			daddr;	/* where reply must come from */
 	struct cache_deferred_req handle;
 	int			argslen;
 	u32			args[0];
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 5dc94e7..37c1c76 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -43,16 +43,20 @@
 /* kernel/power/swsusp.c */
 extern int software_suspend(void);
 
+#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
 extern int pm_prepare_console(void);
 extern void pm_restore_console(void);
-
+#else
+static inline int pm_prepare_console(void) { return 0; }
+static inline void pm_restore_console(void) {}
+#endif /* defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) */
 #else
 static inline int software_suspend(void)
 {
 	printk("Warning: fake suspend called\n");
 	return -EPERM;
 }
-#endif
+#endif /* CONFIG_PM */
 
 #ifdef CONFIG_SUSPEND_SMP
 extern void disable_nonboot_cpus(void);
diff --git a/include/linux/swap.h b/include/linux/swap.h
index e92054d..f3e17d5 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -167,6 +167,7 @@
 extern void FASTCALL(activate_page(struct page *));
 extern void FASTCALL(mark_page_accessed(struct page *));
 extern void lru_add_drain(void);
+extern int lru_add_drain_all(void);
 extern int rotate_reclaimable_page(struct page *page);
 extern void swap_setup(void);
 
@@ -175,16 +176,35 @@
 extern int shrink_all_memory(int);
 extern int vm_swappiness;
 
+#ifdef CONFIG_NUMA
+extern int zone_reclaim_mode;
+extern int zone_reclaim_interval;
+extern int zone_reclaim(struct zone *, gfp_t, unsigned int);
+#else
+#define zone_reclaim_mode 0
+static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_MIGRATION
 extern int isolate_lru_page(struct page *p);
 extern int putback_lru_pages(struct list_head *l);
+extern int migrate_page(struct page *, struct page *);
+extern void migrate_page_copy(struct page *, struct page *);
+extern int migrate_page_remove_references(struct page *, struct page *, int);
 extern int migrate_pages(struct list_head *l, struct list_head *t,
 		struct list_head *moved, struct list_head *failed);
+extern int fail_migrate_page(struct page *, struct page *);
 #else
 static inline int isolate_lru_page(struct page *p) { return -ENOSYS; }
 static inline int putback_lru_pages(struct list_head *l) { return 0; }
 static inline int migrate_pages(struct list_head *l, struct list_head *t,
 	struct list_head *moved, struct list_head *failed) { return -ENOSYS; }
+/* Possible settings for the migrate_page() method in address_operations */
+#define migrate_page NULL
+#define fail_migrate_page NULL
 #endif
 
 #ifdef CONFIG_MMU
@@ -233,6 +253,7 @@
 struct backing_dev_info;
 
 extern spinlock_t swap_lock;
+extern int remove_vma_swap(struct vm_area_struct *vma, struct page *page);
 
 /* linux/mm/thrash.c */
 extern struct mm_struct * swap_token_mm;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3eed473..d73501b 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -50,6 +50,8 @@
 struct tms;
 struct utimbuf;
 struct mq_attr;
+struct compat_stat;
+struct compat_timeval;
 
 #include <linux/config.h>
 #include <linux/types.h>
@@ -510,13 +512,61 @@
 asmlinkage long sys_ioprio_set(int which, int who, int ioprio);
 asmlinkage long sys_ioprio_get(int which, int who);
 asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
-					unsigned long maxnode);
+				unsigned long maxnode);
 asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
-			const unsigned long __user *from, const unsigned long __user *to);
+				const unsigned long __user *from,
+				const unsigned long __user *to);
+asmlinkage long sys_mbind(unsigned long start, unsigned long len,
+				unsigned long mode,
+				unsigned long __user *nmask,
+				unsigned long maxnode,
+				unsigned flags);
+asmlinkage long sys_get_mempolicy(int __user *policy,
+				unsigned long __user *nmask,
+				unsigned long maxnode,
+				unsigned long addr, unsigned long flags);
+
+asmlinkage long sys_inotify_init(void);
+asmlinkage long sys_inotify_add_watch(int fd, const char __user *path,
+					u32 mask);
+asmlinkage long sys_inotify_rm_watch(int fd, u32 wd);
 
 asmlinkage long sys_spu_run(int fd, __u32 __user *unpc,
 				 __u32 __user *ustatus);
 asmlinkage long sys_spu_create(const char __user *name,
 		unsigned int flags, mode_t mode);
 
+asmlinkage long sys_mknodat(int dfd, const char __user * filename, int mode,
+			    unsigned dev);
+asmlinkage long sys_mkdirat(int dfd, const char __user * pathname, int mode);
+asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag);
+asmlinkage long sys_symlinkat(const char __user * oldname,
+			      int newdfd, const char __user * newname);
+asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
+			   int newdfd, const char __user *newname);
+asmlinkage long sys_renameat(int olddfd, const char __user * oldname,
+			     int newdfd, const char __user * newname);
+asmlinkage long sys_futimesat(int dfd, char __user *filename,
+			      struct timeval __user *utimes);
+asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode);
+asmlinkage long sys_fchmodat(int dfd, const char __user * filename,
+			     mode_t mode);
+asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
+			     gid_t group, int flag);
+asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
+			   int mode);
+asmlinkage long sys_newfstatat(int dfd, char __user *filename,
+			       struct stat __user *statbuf, int flag);
+asmlinkage long sys_fstatat64(int dfd, char __user *filename,
+			       struct stat64 __user *statbuf, int flag);
+asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf,
+			       int bufsiz);
+asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename,
+				     struct compat_timeval __user *t);
+asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename,
+				      struct compat_stat __user *statbuf,
+				      int flag);
+asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
+				   int flags, int mode);
+
 #endif
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 7f47212..32a4139 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -182,6 +182,8 @@
 	VM_SWAP_TOKEN_TIMEOUT=28, /* default time for token time out */
 	VM_DROP_PAGECACHE=29,	/* int: nuke lots of pagecache */
 	VM_PERCPU_PAGELIST_FRACTION=30,/* int: fraction of pages in each percpu_pagelist */
+	VM_ZONE_RECLAIM_MODE=31, /* reclaim local zone memory before going off node */
+	VM_ZONE_RECLAIM_INTERVAL=32, /* time period to wait after reclaim failure */
 };
 
 
diff --git a/include/linux/time.h b/include/linux/time.h
index f2aca7e..d9cdba5 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -33,11 +33,34 @@
 #define NSEC_PER_SEC		1000000000L
 #define NSEC_PER_USEC		1000L
 
-static __inline__ int timespec_equal(struct timespec *a, struct timespec *b)
+static inline int timespec_equal(struct timespec *a, struct timespec *b)
 {
 	return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
 }
 
+/*
+ * lhs < rhs:  return <0
+ * lhs == rhs: return 0
+ * lhs > rhs:  return >0
+ */
+static inline int timespec_compare(struct timespec *lhs, struct timespec *rhs)
+{
+	if (lhs->tv_sec < rhs->tv_sec)
+		return -1;
+	if (lhs->tv_sec > rhs->tv_sec)
+		return 1;
+	return lhs->tv_nsec - rhs->tv_nsec;
+}
+
+static inline int timeval_compare(struct timeval *lhs, struct timeval *rhs)
+{
+	if (lhs->tv_sec < rhs->tv_sec)
+		return -1;
+	if (lhs->tv_sec > rhs->tv_sec)
+		return 1;
+	return lhs->tv_usec - rhs->tv_usec;
+}
+
 extern unsigned long mktime(const unsigned int year, const unsigned int mon,
 			    const unsigned int day, const unsigned int hour,
 			    const unsigned int min, const unsigned int sec);
@@ -48,7 +71,7 @@
  * Returns true if the timespec is norm, false if denorm:
  */
 #define timespec_valid(ts) \
-	(((ts)->tv_sec >= 0) && (((unsigned) (ts)->tv_nsec) < NSEC_PER_SEC))
+	(((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
 
 /*
  * 64-bit nanosec type. Large enough to span 292+ years in nanosecond
@@ -74,7 +97,7 @@
 extern int do_settimeofday(struct timespec *tv);
 extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
 #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
-extern long do_utimes(char __user *filename, struct timeval *times);
+extern long do_utimes(int dfd, char __user *filename, struct timeval *times);
 struct itimerval;
 extern int do_setitimer(int which, struct itimerval *value,
 			struct itimerval *ovalue);
diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h
index a52c8c6..33a6539 100644
--- a/include/linux/tipc_config.h
+++ b/include/linux/tipc_config.h
@@ -168,10 +168,13 @@
 #define TIPC_MAX_LINK_NAME	60	/* format = Z.C.N:interface-Z.C.N:interface */
 
 /*
- * Link priority limits (range from 0 to # priorities - 1)
+ * Link priority limits (min, default, max, media default)
  */
 
-#define TIPC_NUM_LINK_PRI 32
+#define TIPC_MIN_LINK_PRI	0
+#define TIPC_DEF_LINK_PRI	10
+#define TIPC_MAX_LINK_PRI	31
+#define TIPC_MEDIA_LINK_PRI	(TIPC_MAX_LINK_PRI + 1)
 
 /*
  * Link tolerance limits (min, default, max), in ms
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 315a516..e8eb004 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -56,6 +56,14 @@
 #define REMOTE_DISTANCE		20
 #define node_distance(from,to)	((from) == (to) ? LOCAL_DISTANCE : REMOTE_DISTANCE)
 #endif
+#ifndef RECLAIM_DISTANCE
+/*
+ * If the distance between nodes in a system is larger than RECLAIM_DISTANCE
+ * (in whatever arch specific measurement units returned by node_distance())
+ * then switch on zone reclaim on boot.
+ */
+#define RECLAIM_DISTANCE 20
+#endif
 #ifndef PENALTY_FOR_NODE_WITH_CPUS
 #define PENALTY_FOR_NODE_WITH_CPUS	(1)
 #endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 3787102..f45cd74 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -57,6 +57,9 @@
 	unsigned char *flag_buf_ptr;
 	int used;
 	int size;
+	int active;
+	int commit;
+	int read;
 	/* Data points here */
 	unsigned long data[0];
 };
@@ -64,6 +67,7 @@
 struct tty_bufhead {
 	struct work_struct		work;
 	struct semaphore pty_sem;
+	spinlock_t lock;
 	struct tty_buffer *head;	/* Queue head */
 	struct tty_buffer *tail;	/* Active buffer */
 	struct tty_buffer *free;	/* Free queue head */
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index be1400e..222faf9 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -17,7 +17,7 @@
 				   unsigned char ch, char flag)
 {
 	struct tty_buffer *tb = tty->buf.tail;
-	if (tb && tb->used < tb->size) {
+	if (tb && tb->active && tb->used < tb->size) {
 		tb->flag_buf_ptr[tb->used] = flag;
 		tb->char_buf_ptr[tb->used++] = ch;
 		return 1;
@@ -27,6 +27,13 @@
 
 _INLINE_ void tty_schedule_flip(struct tty_struct *tty)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&tty->buf.lock, flags);
+	if (tty->buf.tail != NULL) {
+		tty->buf.tail->active = 0;
+		tty->buf.tail->commit = tty->buf.tail->used;
+	}
+	spin_unlock_irqrestore(&tty->buf.lock, flags);
 	schedule_delayed_work(&tty->buf.work, 1);
 }
 
diff --git a/include/linux/types.h b/include/linux/types.h
index 21b9ce8..54ae2d5 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -8,6 +8,8 @@
 	(((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
 #define DECLARE_BITMAP(name,bits) \
 	unsigned long name[BITS_TO_LONGS(bits)]
+
+#define BITS_PER_BYTE 8
 #endif
 
 #include <linux/posix_types.h>
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index 7a6babe..b0ffe43 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -148,11 +148,11 @@
 #define UFS_USEEFT  ((__u16)65535)
 
 #define UFS_FSOK      0x7c269d38
-#define UFS_FSACTIVE  ((char)0x00)
-#define UFS_FSCLEAN   ((char)0x01)
-#define UFS_FSSTABLE  ((char)0x02)
-#define UFS_FSOSF1    ((char)0x03)	/* is this correct for DEC OSF/1? */
-#define UFS_FSBAD     ((char)0xff)
+#define UFS_FSACTIVE  ((__s8)0x00)
+#define UFS_FSCLEAN   ((__s8)0x01)
+#define UFS_FSSTABLE  ((__s8)0x02)
+#define UFS_FSOSF1    ((__s8)0x03)	/* is this correct for DEC OSF/1? */
+#define UFS_FSBAD     ((__s8)0xff)
 
 /* From here to next blank line, s_flags for ufs_sb_info */
 /* directory entry encoding */
@@ -502,8 +502,7 @@
 /*
  * Convert cylinder group to base address of its global summary info.
  */
-#define fs_cs(indx) \
-	s_csp[(indx) >> uspi->s_csshift][(indx) & ~uspi->s_csmask]
+#define fs_cs(indx) s_csp[(indx)]
 
 /*
  * Cylinder group block for a file system.
@@ -913,6 +912,7 @@
 extern void ufs_delete_inode (struct inode *);
 extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
 extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
+extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create);
 
 /* namei.c */
 extern struct file_operations ufs_dir_operations;
diff --git a/include/linux/ufs_fs_sb.h b/include/linux/ufs_fs_sb.h
index c1be4c2..8ff13c1 100644
--- a/include/linux/ufs_fs_sb.h
+++ b/include/linux/ufs_fs_sb.h
@@ -25,7 +25,7 @@
 
 struct ufs_sb_info {
 	struct ufs_sb_private_info * s_uspi;	
-	struct ufs_csum	* s_csp[UFS_MAXCSBUFS];
+	struct ufs_csum	* s_csp;
 	unsigned s_bytesex;
 	unsigned s_flags;
 	struct buffer_head ** s_ucg;
diff --git a/include/linux/usb_ch9.h b/include/linux/usb_ch9.h
index ee21e6b..a2aacfc 100644
--- a/include/linux/usb_ch9.h
+++ b/include/linux/usb_ch9.h
@@ -535,9 +535,11 @@
 	 */
 	USB_STATE_NOTATTACHED = 0,
 
-	/* the chapter 9 device states */
+	/* chapter 9 and authentication (wireless) device states */
 	USB_STATE_ATTACHED,
-	USB_STATE_POWERED,
+	USB_STATE_POWERED,			/* wired */
+	USB_STATE_UNAUTHENTICATED,		/* auth */
+	USB_STATE_RECONNECTING,			/* auth */
 	USB_STATE_DEFAULT,			/* limited function */
 	USB_STATE_ADDRESS,
 	USB_STATE_CONFIGURED,			/* most functions */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index ce40675..5208b12d 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -315,6 +315,7 @@
 #define V4L2_PIX_FMT_SN9C10X  v4l2_fourcc('S','9','1','0') /* SN9C10x compression */
 #define V4L2_PIX_FMT_PWC1     v4l2_fourcc('P','W','C','1') /* pwc older webcam */
 #define V4L2_PIX_FMT_PWC2     v4l2_fourcc('P','W','C','2') /* pwc newer webcam */
+#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */
 
 /*
  *	F O R M A T   E N U M E R A T I O N
@@ -548,7 +549,7 @@
 struct v4l2_clip
 {
 	struct v4l2_rect        c;
-	struct v4l2_clip	*next;
+	struct v4l2_clip	__user *next;
 };
 
 struct v4l2_window
@@ -628,6 +629,7 @@
 #define V4L2_STD_NTSC_M         ((v4l2_std_id)0x00001000)
 #define V4L2_STD_NTSC_M_JP      ((v4l2_std_id)0x00002000)
 #define V4L2_STD_NTSC_443       ((v4l2_std_id)0x00004000)
+#define V4L2_STD_NTSC_M_KR      ((v4l2_std_id)0x00008000)
 
 #define V4L2_STD_SECAM_B        ((v4l2_std_id)0x00010000)
 #define V4L2_STD_SECAM_D        ((v4l2_std_id)0x00020000)
@@ -660,7 +662,8 @@
 				 V4L2_STD_PAL_H		|\
 				 V4L2_STD_PAL_I)
 #define V4L2_STD_NTSC           (V4L2_STD_NTSC_M	|\
-				 V4L2_STD_NTSC_M_JP)
+				 V4L2_STD_NTSC_M_JP     |\
+				 V4L2_STD_NTSC_M_KR)
 #define V4L2_STD_SECAM_DK      	(V4L2_STD_SECAM_D	|\
 				 V4L2_STD_SECAM_K	|\
 				 V4L2_STD_SECAM_K1)
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index bbfac86..89d743c 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -33,7 +33,7 @@
 #define RFCOMM_DEFAULT_MTU	127
 #define RFCOMM_DEFAULT_CREDITS	7
 
-#define RFCOMM_MAX_L2CAP_MTU	1024
+#define RFCOMM_MAX_L2CAP_MTU	1013
 #define RFCOMM_MAX_CREDITS	40
 
 #define RFCOMM_SKB_HEAD_RESERVE	8
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index df05f46..9a92aef 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -803,9 +803,9 @@
 #define IEEE80211_24GHZ_MAX_CHANNEL 14
 #define IEEE80211_24GHZ_CHANNELS    14
 
-#define IEEE80211_52GHZ_MIN_CHANNEL 36
+#define IEEE80211_52GHZ_MIN_CHANNEL 34
 #define IEEE80211_52GHZ_MAX_CHANNEL 165
-#define IEEE80211_52GHZ_CHANNELS    32
+#define IEEE80211_52GHZ_CHANNELS    131
 
 enum {
 	IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
index 05a8408..1880e46 100644
--- a/include/net/irda/irda.h
+++ b/include/net/irda/irda.h
@@ -82,9 +82,9 @@
 #define IRDA_ASSERT_LABEL(label)
 #endif /* CONFIG_IRDA_DEBUG */
 
-#define IRDA_WARNING(args...) printk(KERN_WARNING args)
-#define IRDA_MESSAGE(args...) printk(KERN_INFO args)
-#define IRDA_ERROR(args...)   printk(KERN_ERR args)
+#define IRDA_WARNING(args...) do { if (net_ratelimit()) printk(KERN_WARNING args); } while (0)
+#define IRDA_MESSAGE(args...) do { if (net_ratelimit()) printk(KERN_INFO args); } while (0)
+#define IRDA_ERROR(args...)   do { if (net_ratelimit()) printk(KERN_ERR args); } while (0)
 
 /*
  *  Magic numbers used by Linux-IrDA. Random numbers which must be unique to 
diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h
index f55e86e..2127cae 100644
--- a/include/net/irda/irlap.h
+++ b/include/net/irda/irlap.h
@@ -50,6 +50,9 @@
 /* May be different when we get VFIR */
 #define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER)
 
+/* Each IrDA device gets a random 32 bits IRLAP device address */
+#define LAP_ALEN 4
+
 #define BROADCAST  0xffffffff /* Broadcast device address */
 #define CBROADCAST 0xfe       /* Connection broadcast address */
 #define XID_FORMAT 0x01       /* Discovery XID format */
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 67856eb..dac43b1 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -88,12 +88,6 @@
 extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
 extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
 
-static inline struct nf_conntrack_l3proto *
-__nf_ct_l3proto_find(u_int16_t l3proto)
-{
-	return nf_ct_l3protos[l3proto];
-}
-
 extern struct nf_conntrack_l3proto *
 nf_ct_l3proto_find_get(u_int16_t l3proto);
 
@@ -103,4 +97,13 @@
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
 extern struct nf_conntrack_l3proto nf_conntrack_generic_l3proto;
+
+static inline struct nf_conntrack_l3proto *
+__nf_ct_l3proto_find(u_int16_t l3proto)
+{
+	if (unlikely(l3proto >= AF_MAX))
+		return &nf_conntrack_generic_l3proto;
+	return nf_ct_l3protos[l3proto];
+}
+
 #endif /*_NF_CONNTRACK_L3PROTO_H*/
diff --git a/include/net/route.h b/include/net/route.h
index e3e5436..9c04f15 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -170,8 +170,8 @@
 	return ip_route_output_flow(rp, &fl, sk, 0);
 }
 
-static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport,
-				    struct sock *sk)
+static inline int ip_route_newports(struct rtable **rp, u8 protocol,
+				    u16 sport, u16 dport, struct sock *sk)
 {
 	if (sport != (*rp)->fl.fl_ip_sport ||
 	    dport != (*rp)->fl.fl_ip_dport) {
@@ -180,6 +180,7 @@
 		memcpy(&fl, &(*rp)->fl, sizeof(fl));
 		fl.fl_ip_sport = sport;
 		fl.fl_ip_dport = dport;
+		fl.proto = protocol;
 		ip_rt_put(*rp);
 		*rp = NULL;
 		return ip_route_output_flow(rp, &fl, sk, 0);
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index a553f39..e673b2c 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -175,6 +175,8 @@
 void sctp_icmp_proto_unreachable(struct sock *sk,
 				 struct sctp_association *asoc,
 				 struct sctp_transport *t);
+void sctp_backlog_migrate(struct sctp_association *assoc,
+			  struct sock *oldsk, struct sock *newsk);
 
 /*
  *  Section:  Macros, externs, and inlines
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index f5c22d7..072f407 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -127,9 +127,9 @@
 	 * RTO.Alpha		    - 1/8  (3 when converted to right shifts.)
 	 * RTO.Beta		    - 1/4  (2 when converted to right shifts.)
 	 */
-	__u32 rto_initial;
-	__u32 rto_min;
-	__u32 rto_max;
+	unsigned long rto_initial;
+	unsigned long rto_min;
+	unsigned long rto_max;
 
 	/* Note: rto_alpha and rto_beta are really defined as inverse
 	 * powers of two to facilitate integer operations.
@@ -140,12 +140,18 @@
 	/* Max.Burst		    - 4 */
 	int max_burst;
 
-	/* Valid.Cookie.Life	    - 60  seconds  */
-	int valid_cookie_life;
-
 	/* Whether Cookie Preservative is enabled(1) or not(0) */
 	int cookie_preserve_enable;
 
+	/* Valid.Cookie.Life	    - 60  seconds  */
+	unsigned long valid_cookie_life;
+
+	/* Delayed SACK timeout  200ms default*/
+	unsigned long sack_timeout;
+
+	/* HB.interval		    - 30 seconds  */
+	unsigned long hb_interval;
+
 	/* Association.Max.Retrans  - 10 attempts
 	 * Path.Max.Retrans	    - 5	 attempts (per destination address)
 	 * Max.Init.Retransmits	    - 8	 attempts
@@ -168,12 +174,6 @@
 	 */
 	int rcvbuf_policy;
 
-	/* Delayed SACK timeout  200ms default*/
-	int sack_timeout;
-
-	/* HB.interval		    - 30 seconds  */
-	int hb_interval;
-
 	/* The following variables are implementation specific.	 */
 
 	/* Default initialization values to be applied to new associations. */
@@ -405,8 +405,9 @@
 /* The format of our cookie that we send to our peer. */
 struct sctp_signed_cookie {
 	__u8 signature[SCTP_SECRET_SIZE];
+	__u32 __pad;		/* force sctp_cookie alignment to 64 bits */
 	struct sctp_cookie c;
-};
+} __attribute__((packed));
 
 /* This is another convenience type to allocate memory for address
  * params for the maximum size and pass such structures around
@@ -699,7 +700,7 @@
 	__u8 ecn_ce_done;	/* Have we processed the ECN CE bit? */
 	__u8 pdiscard;		/* Discard the whole packet now? */
 	__u8 tsn_gap_acked;	/* Is this chunk acked by a GAP ACK? */
-	__u8 fast_retransmit;	 /* Is this chunk fast retransmitted? */
+	__s8 fast_retransmit;	 /* Is this chunk fast retransmitted? */
 	__u8 tsn_missing_report; /* Data chunk missing counter. */
 };
 
@@ -827,7 +828,7 @@
 	__u32 rtt;		/* This is the most recent RTT.	 */
 
 	/* RTO	       : The current retransmission timeout value.  */
-	__u32 rto;
+	unsigned long rto;
 
 	/* RTTVAR      : The current RTT variation.  */
 	__u32 rttvar;
@@ -877,22 +878,10 @@
 	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
 	 * the destination address every heartbeat interval.
 	 */
-	__u32 hbinterval;
-
-	/* This is the max_retrans value for the transport and will
-	 * be initialized from the assocs value.  This can be changed
-	 * using SCTP_SET_PEER_ADDR_PARAMS socket option.
-	 */
-	__u16 pathmaxrxt;
-
-	/* PMTU	      : The current known path MTU.  */
-	__u32 pathmtu;
+	unsigned long hbinterval;
 
 	/* SACK delay timeout */
-	__u32 sackdelay;
-
-	/* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
-	__u32 param_flags;
+	unsigned long sackdelay;
 
 	/* When was the last time (in jiffies) that we heard from this
 	 * transport?  We use this to pick new active and retran paths.
@@ -904,6 +893,18 @@
 	 */
 	unsigned long last_time_ecne_reduced;
 
+	/* This is the max_retrans value for the transport and will
+	 * be initialized from the assocs value.  This can be changed
+	 * using SCTP_SET_PEER_ADDR_PARAMS socket option.
+	 */
+	__u16 pathmaxrxt;
+
+	/* PMTU	      : The current known path MTU.  */
+	__u32 pathmtu;
+
+	/* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
+	__u32 param_flags;
+
 	/* The number of times INIT has been sent on this transport. */
 	int init_sent_count;
 
@@ -1249,6 +1250,14 @@
 	int last_key;
 	int key_changed_at;
 
+ 	/* digest:  This is a digest of the sctp cookie.  This field is
+ 	 * 	    only used on the receive path when we try to validate
+ 	 * 	    that the cookie has not been tampered with.  We put
+ 	 * 	    this here so we pre-allocate this once and can re-use
+ 	 * 	    on every receive.
+ 	 */
+ 	__u8 digest[SCTP_SIGNATURE_SIZE];
+ 
 	/* sendbuf acct. policy.	*/
 	__u32 sndbuf_policy;
 
@@ -1499,9 +1508,9 @@
 	 * These values will be initialized by system defaults, but can
 	 * be modified via the SCTP_RTOINFO socket option.
 	 */
-	__u32 rto_initial;
-	__u32 rto_max;
-	__u32 rto_min;
+	unsigned long rto_initial;
+	unsigned long rto_max;
+	unsigned long rto_min;
 
 	/* Maximum number of new data packets that can be sent in a burst.  */
 	int max_burst;
@@ -1519,13 +1528,13 @@
 	__u16 init_retries;
 
 	/* The largest timeout or RTO value to use in attempting an INIT */
-	__u16 max_init_timeo;
+	unsigned long max_init_timeo;
 
 	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
 	 * the destination address every heartbeat interval. This value
 	 * will be inherited by all new transports.
 	 */
-	__u32 hbinterval;
+	unsigned long hbinterval;
 
 	/* This is the max_retrans value for new transports in the
 	 * association.
@@ -1537,13 +1546,14 @@
 	 */
 	__u32 pathmtu;
 
-	/* SACK delay timeout */
-	__u32 sackdelay;
-
 	/* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
 	__u32 param_flags;
 
-	int timeouts[SCTP_NUM_TIMEOUT_TYPES];
+	/* SACK delay timeout */
+	unsigned long sackdelay;
+
+
+	unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES];
 	struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES];
 
 	/* Transport to which SHUTDOWN chunk was last sent.  */
@@ -1648,7 +1658,10 @@
 	/* How many duplicated TSNs have we seen?  */
 	int numduptsns;
 
-	/* Number of seconds of idle time before an association is closed.  */
+	/* Number of seconds of idle time before an association is closed.
+	 * In the association context, this is really used as a boolean
+	 * since the real timeout is stored in the timeouts array
+	 */
 	__u32 autoclose;
 
 	/* These are to support
diff --git a/include/net/sock.h b/include/net/sock.h
index 1806e5b..3075803 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1354,12 +1354,12 @@
  *	Enable debug/info messages 
  */
 
-#if 0
-#define NETDEBUG(fmt, args...)	do { } while (0)
-#define LIMIT_NETDEBUG(fmt, args...) do { } while(0)
-#else
+#ifdef CONFIG_NETDEBUG
 #define NETDEBUG(fmt, args...)	printk(fmt,##args)
 #define LIMIT_NETDEBUG(fmt, args...) do { if (net_ratelimit()) printk(fmt,##args); } while(0)
+#else
+#define NETDEBUG(fmt, args...)	do { } while (0)
+#define LIMIT_NETDEBUG(fmt, args...) do { } while(0)
 #endif
 
 /*
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index e94ca4d..290e3b4 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -275,7 +275,7 @@
 			    int data_direction, void *buffer, unsigned bufflen,
 			    struct scsi_sense_hdr *, int timeout, int retries);
 extern int scsi_execute_async(struct scsi_device *sdev,
-			      const unsigned char *cmd, int data_direction,
+			      const unsigned char *cmd, int cmd_len, int data_direction,
 			      void *buffer, unsigned bufflen, int use_sg,
 			      int timeout, int retries, void *privdata,
 			      void (*done)(void *, char *, int, int),
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 467274a..8279929 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -554,7 +554,6 @@
 	/*
 	 * ordered write support
 	 */
-	unsigned ordered_flush:1;
 	unsigned ordered_tag:1;
 
 	/*
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index 2b5930b..fb5a2ff 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -22,6 +22,7 @@
 
 #include <linux/config.h>
 #include <linux/transport_class.h>
+#include <linux/mutex.h>
 
 struct scsi_transport_template;
 struct scsi_target;
diff --git a/init/Kconfig b/init/Kconfig
index b9923b1..38416a1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -31,19 +31,8 @@
 	  you say Y here, you will be offered the choice of using features or
 	  drivers that are currently considered to be in the alpha-test phase.
 
-config CLEAN_COMPILE
-	bool "Select only drivers expected to compile cleanly" if EXPERIMENTAL
-	default y
-	help
-	  Select this option if you don't even want to see the option
-	  to configure known-broken drivers.
-
-	  If unsure, say Y
-
 config BROKEN
 	bool
-	depends on !CLEAN_COMPILE
-	default y
 
 config BROKEN_ON_SMP
 	bool
@@ -180,7 +169,6 @@
 config AUDIT
 	bool "Auditing support"
 	depends on NET
-	default y if SECURITY_SELINUX
 	help
 	  Enable auditing infrastructure that can be used with another
 	  kernel subsystem, such as SELinux (which requires this for
diff --git a/init/initramfs.c b/init/initramfs.c
index 0c5d9a3..637344b 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -466,10 +466,32 @@
 extern char __initramfs_start[], __initramfs_end[];
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/initrd.h>
+#include <linux/kexec.h>
 
 static void __init free_initrd(void)
 {
-	free_initrd_mem(initrd_start, initrd_end);
+#ifdef CONFIG_KEXEC
+	unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
+	unsigned long crashk_end   = (unsigned long)__va(crashk_res.end);
+
+	/*
+	 * If the initrd region is overlapped with crashkernel reserved region,
+	 * free only memory that is not part of crashkernel region.
+	 */
+	if (initrd_start < crashk_end && initrd_end > crashk_start) {
+		/*
+		 * Initialize initrd memory region since the kexec boot does
+		 * not do.
+		 */
+		memset((void *)initrd_start, 0, initrd_end - initrd_start);
+		if (initrd_start < crashk_start)
+			free_initrd_mem(initrd_start, crashk_start);
+		if (initrd_end > crashk_end)
+			free_initrd_mem(crashk_end, initrd_end);
+	} else
+#endif
+		free_initrd_mem(initrd_start, initrd_end);
+
 	initrd_start = 0;
 	initrd_end = 0;
 }
diff --git a/init/main.c b/init/main.c
index 7c79da5..4c194c4 100644
--- a/init/main.c
+++ b/init/main.c
@@ -668,7 +668,6 @@
 	 */
 	child_reaper = current;
 
-	/* Sets up cpus_possible() */
 	smp_prepare_cpus(max_cpus);
 
 	do_pre_smp_initcalls();
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 59302fc..fd2e26b 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -1018,7 +1018,8 @@
 				goto out;
 			}
 
-			ret = netlink_attachskb(sock, nc, 0, MAX_SCHEDULE_TIMEOUT);
+			ret = netlink_attachskb(sock, nc, 0,
+					MAX_SCHEDULE_TIMEOUT, NULL);
 			if (ret == 1)
 		       		goto retry;
 			if (ret) {
diff --git a/ipc/shm.c b/ipc/shm.c
index 4c28d2d..9162123 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -870,6 +870,7 @@
 	 * could possibly have landed at. Also cast things to loff_t to
 	 * prevent overflows and make comparisions vs. equal-width types.
 	 */
+	size = PAGE_ALIGN(size);
 	while (vma && (loff_t)(vma->vm_end - addr) <= size) {
 		next = vma->vm_next;
 
diff --git a/kernel/audit.c b/kernel/audit.c
index d13ab7d..0a813d2 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -42,8 +42,8 @@
  */
 
 #include <linux/init.h>
-#include <asm/atomic.h>
 #include <asm/types.h>
+#include <asm/atomic.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/err.h>
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index d8a6850..685c251 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -30,8 +30,8 @@
  */
 
 #include <linux/init.h>
-#include <asm/atomic.h>
 #include <asm/types.h>
+#include <asm/atomic.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/mount.h>
diff --git a/kernel/compat.c b/kernel/compat.c
index 256e5d9..8c9cd88 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -23,7 +23,6 @@
 #include <linux/security.h>
 
 #include <asm/uaccess.h>
-#include <asm/bug.h>
 
 int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
 {
@@ -871,3 +870,31 @@
 }
 
 #endif /* __ARCH_WANT_COMPAT_SYS_TIME */
+
+#ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize)
+{
+	sigset_t newset;
+	compat_sigset_t newset32;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
+		return -EFAULT;
+	sigset_from_compat(&newset, &newset32);
+	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+	spin_lock_irq(&current->sighand->siglock);
+	current->saved_sigmask = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
+}
+#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index fe2f71f..ba42b0a 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -641,7 +641,7 @@
  * task has been modifying its cpuset.
  */
 
-void cpuset_update_task_memory_state()
+void cpuset_update_task_memory_state(void)
 {
 	int my_cpusets_mem_gen;
 	struct task_struct *tsk = current;
diff --git a/kernel/fork.c b/kernel/fork.c
index 4ae8cfc..8e88b37 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -446,6 +446,55 @@
 	}
 }
 
+/*
+ * Allocate a new mm structure and copy contents from the
+ * mm structure of the passed in task structure.
+ */
+static struct mm_struct *dup_mm(struct task_struct *tsk)
+{
+	struct mm_struct *mm, *oldmm = current->mm;
+	int err;
+
+	if (!oldmm)
+		return NULL;
+
+	mm = allocate_mm();
+	if (!mm)
+		goto fail_nomem;
+
+	memcpy(mm, oldmm, sizeof(*mm));
+
+	if (!mm_init(mm))
+		goto fail_nomem;
+
+	if (init_new_context(tsk, mm))
+		goto fail_nocontext;
+
+	err = dup_mmap(mm, oldmm);
+	if (err)
+		goto free_pt;
+
+	mm->hiwater_rss = get_mm_rss(mm);
+	mm->hiwater_vm = mm->total_vm;
+
+	return mm;
+
+free_pt:
+	mmput(mm);
+
+fail_nomem:
+	return NULL;
+
+fail_nocontext:
+	/*
+	 * If init_new_context() failed, we cannot use mmput() to free the mm
+	 * because it calls destroy_context()
+	 */
+	mm_free_pgd(mm);
+	free_mm(mm);
+	return NULL;
+}
+
 static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
 {
 	struct mm_struct * mm, *oldmm;
@@ -473,43 +522,17 @@
 	}
 
 	retval = -ENOMEM;
-	mm = allocate_mm();
+	mm = dup_mm(tsk);
 	if (!mm)
 		goto fail_nomem;
 
-	/* Copy the current MM stuff.. */
-	memcpy(mm, oldmm, sizeof(*mm));
-	if (!mm_init(mm))
-		goto fail_nomem;
-
-	if (init_new_context(tsk,mm))
-		goto fail_nocontext;
-
-	retval = dup_mmap(mm, oldmm);
-	if (retval)
-		goto free_pt;
-
-	mm->hiwater_rss = get_mm_rss(mm);
-	mm->hiwater_vm = mm->total_vm;
-
 good_mm:
 	tsk->mm = mm;
 	tsk->active_mm = mm;
 	return 0;
 
-free_pt:
-	mmput(mm);
 fail_nomem:
 	return retval;
-
-fail_nocontext:
-	/*
-	 * If init_new_context() failed, we cannot use mmput() to free the mm
-	 * because it calls destroy_context()
-	 */
-	mm_free_pgd(mm);
-	free_mm(mm);
-	return retval;
 }
 
 static inline struct fs_struct *__copy_fs_struct(struct fs_struct *old)
@@ -597,32 +620,17 @@
 	return newf;
 }
 
-static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
+/*
+ * Allocate a new files structure and copy contents from the
+ * passed in files structure.
+ */
+static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
 {
-	struct files_struct *oldf, *newf;
+	struct files_struct *newf;
 	struct file **old_fds, **new_fds;
-	int open_files, size, i, error = 0, expand;
+	int open_files, size, i, expand;
 	struct fdtable *old_fdt, *new_fdt;
 
-	/*
-	 * A background process may not have any files ...
-	 */
-	oldf = current->files;
-	if (!oldf)
-		goto out;
-
-	if (clone_flags & CLONE_FILES) {
-		atomic_inc(&oldf->count);
-		goto out;
-	}
-
-	/*
-	 * Note: we may be using current for both targets (See exec.c)
-	 * This works because we cache current->files (old) as oldf. Don't
-	 * break this.
-	 */
-	tsk->files = NULL;
-	error = -ENOMEM;
 	newf = alloc_files();
 	if (!newf)
 		goto out;
@@ -651,9 +659,9 @@
 	if (expand) {
 		spin_unlock(&oldf->file_lock);
 		spin_lock(&newf->file_lock);
-		error = expand_files(newf, open_files-1);
+		*errorp = expand_files(newf, open_files-1);
 		spin_unlock(&newf->file_lock);
-		if (error < 0)
+		if (*errorp < 0)
 			goto out_release;
 		new_fdt = files_fdtable(newf);
 		/*
@@ -702,10 +710,8 @@
 		memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
 	}
 
-	tsk->files = newf;
-	error = 0;
 out:
-	return error;
+	return newf;
 
 out_release:
 	free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
@@ -715,6 +721,40 @@
 	goto out;
 }
 
+static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
+{
+	struct files_struct *oldf, *newf;
+	int error = 0;
+
+	/*
+	 * A background process may not have any files ...
+	 */
+	oldf = current->files;
+	if (!oldf)
+		goto out;
+
+	if (clone_flags & CLONE_FILES) {
+		atomic_inc(&oldf->count);
+		goto out;
+	}
+
+	/*
+	 * Note: we may be using current for both targets (See exec.c)
+	 * This works because we cache current->files (old) as oldf. Don't
+	 * break this.
+	 */
+	tsk->files = NULL;
+	error = -ENOMEM;
+	newf = dup_fd(oldf, &error);
+	if (!newf)
+		goto out;
+
+	tsk->files = newf;
+	error = 0;
+out:
+	return error;
+}
+
 /*
  *	Helper to unshare the files of the current task.
  *	We don't want to expose copy_files internals to
@@ -802,7 +842,7 @@
 	init_sigpending(&sig->shared_pending);
 	INIT_LIST_HEAD(&sig->posix_timers);
 
-	hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC);
+	hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_REL);
 	sig->it_real_incr.tv64 = 0;
 	sig->real_timer.function = it_real_fn;
 	sig->real_timer.data = tsk;
@@ -1323,3 +1363,249 @@
 			sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN,
 			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
 }
+
+
+/*
+ * Check constraints on flags passed to the unshare system call and
+ * force unsharing of additional process context as appropriate.
+ */
+static inline void check_unshare_flags(unsigned long *flags_ptr)
+{
+	/*
+	 * If unsharing a thread from a thread group, must also
+	 * unshare vm.
+	 */
+	if (*flags_ptr & CLONE_THREAD)
+		*flags_ptr |= CLONE_VM;
+
+	/*
+	 * If unsharing vm, must also unshare signal handlers.
+	 */
+	if (*flags_ptr & CLONE_VM)
+		*flags_ptr |= CLONE_SIGHAND;
+
+	/*
+	 * If unsharing signal handlers and the task was created
+	 * using CLONE_THREAD, then must unshare the thread
+	 */
+	if ((*flags_ptr & CLONE_SIGHAND) &&
+	    (atomic_read(&current->signal->count) > 1))
+		*flags_ptr |= CLONE_THREAD;
+
+	/*
+	 * If unsharing namespace, must also unshare filesystem information.
+	 */
+	if (*flags_ptr & CLONE_NEWNS)
+		*flags_ptr |= CLONE_FS;
+}
+
+/*
+ * Unsharing of tasks created with CLONE_THREAD is not supported yet
+ */
+static int unshare_thread(unsigned long unshare_flags)
+{
+	if (unshare_flags & CLONE_THREAD)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Unshare the filesystem structure if it is being shared
+ */
+static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
+{
+	struct fs_struct *fs = current->fs;
+
+	if ((unshare_flags & CLONE_FS) &&
+	    (fs && atomic_read(&fs->count) > 1)) {
+		*new_fsp = __copy_fs_struct(current->fs);
+		if (!*new_fsp)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * Unshare the namespace structure if it is being shared
+ */
+static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs)
+{
+	struct namespace *ns = current->namespace;
+
+	if ((unshare_flags & CLONE_NEWNS) &&
+	    (ns && atomic_read(&ns->count) > 1)) {
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		*new_nsp = dup_namespace(current, new_fs ? new_fs : current->fs);
+		if (!*new_nsp)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * Unsharing of sighand for tasks created with CLONE_SIGHAND is not
+ * supported yet
+ */
+static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp)
+{
+	struct sighand_struct *sigh = current->sighand;
+
+	if ((unshare_flags & CLONE_SIGHAND) &&
+	    (sigh && atomic_read(&sigh->count) > 1))
+		return -EINVAL;
+	else
+		return 0;
+}
+
+/*
+ * Unshare vm if it is being shared
+ */
+static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp)
+{
+	struct mm_struct *mm = current->mm;
+
+	if ((unshare_flags & CLONE_VM) &&
+	    (mm && atomic_read(&mm->mm_users) > 1)) {
+		*new_mmp = dup_mm(current);
+		if (!*new_mmp)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * Unshare file descriptor table if it is being shared
+ */
+static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp)
+{
+	struct files_struct *fd = current->files;
+	int error = 0;
+
+	if ((unshare_flags & CLONE_FILES) &&
+	    (fd && atomic_read(&fd->count) > 1)) {
+		*new_fdp = dup_fd(fd, &error);
+		if (!*new_fdp)
+			return error;
+	}
+
+	return 0;
+}
+
+/*
+ * Unsharing of semundo for tasks created with CLONE_SYSVSEM is not
+ * supported yet
+ */
+static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **new_ulistp)
+{
+	if (unshare_flags & CLONE_SYSVSEM)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * unshare allows a process to 'unshare' part of the process
+ * context which was originally shared using clone.  copy_*
+ * functions used by do_fork() cannot be used here directly
+ * because they modify an inactive task_struct that is being
+ * constructed. Here we are modifying the current, active,
+ * task_struct.
+ */
+asmlinkage long sys_unshare(unsigned long unshare_flags)
+{
+	int err = 0;
+	struct fs_struct *fs, *new_fs = NULL;
+	struct namespace *ns, *new_ns = NULL;
+	struct sighand_struct *sigh, *new_sigh = NULL;
+	struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
+	struct files_struct *fd, *new_fd = NULL;
+	struct sem_undo_list *new_ulist = NULL;
+
+	check_unshare_flags(&unshare_flags);
+
+	if ((err = unshare_thread(unshare_flags)))
+		goto bad_unshare_out;
+	if ((err = unshare_fs(unshare_flags, &new_fs)))
+		goto bad_unshare_cleanup_thread;
+	if ((err = unshare_namespace(unshare_flags, &new_ns, new_fs)))
+		goto bad_unshare_cleanup_fs;
+	if ((err = unshare_sighand(unshare_flags, &new_sigh)))
+		goto bad_unshare_cleanup_ns;
+	if ((err = unshare_vm(unshare_flags, &new_mm)))
+		goto bad_unshare_cleanup_sigh;
+	if ((err = unshare_fd(unshare_flags, &new_fd)))
+		goto bad_unshare_cleanup_vm;
+	if ((err = unshare_semundo(unshare_flags, &new_ulist)))
+		goto bad_unshare_cleanup_fd;
+
+	if (new_fs || new_ns || new_sigh || new_mm || new_fd || new_ulist) {
+
+		task_lock(current);
+
+		if (new_fs) {
+			fs = current->fs;
+			current->fs = new_fs;
+			new_fs = fs;
+		}
+
+		if (new_ns) {
+			ns = current->namespace;
+			current->namespace = new_ns;
+			new_ns = ns;
+		}
+
+		if (new_sigh) {
+			sigh = current->sighand;
+			current->sighand = new_sigh;
+			new_sigh = sigh;
+		}
+
+		if (new_mm) {
+			mm = current->mm;
+			active_mm = current->active_mm;
+			current->mm = new_mm;
+			current->active_mm = new_mm;
+			activate_mm(active_mm, new_mm);
+			new_mm = mm;
+		}
+
+		if (new_fd) {
+			fd = current->files;
+			current->files = new_fd;
+			new_fd = fd;
+		}
+
+		task_unlock(current);
+	}
+
+bad_unshare_cleanup_fd:
+	if (new_fd)
+		put_files_struct(new_fd);
+
+bad_unshare_cleanup_vm:
+	if (new_mm)
+		mmput(new_mm);
+
+bad_unshare_cleanup_sigh:
+	if (new_sigh)
+		if (atomic_dec_and_test(&new_sigh->count))
+			kmem_cache_free(sighand_cachep, new_sigh);
+
+bad_unshare_cleanup_ns:
+	if (new_ns)
+		put_namespace(new_ns);
+
+bad_unshare_cleanup_fs:
+	if (new_fs)
+		put_fs_struct(new_fs);
+
+bad_unshare_cleanup_thread:
+bad_unshare_out:
+	return err;
+}
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index f1c4155..2b6e175 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -21,6 +21,12 @@
  *  Credits:
  *	based on kernel/timer.c
  *
+ *	Help, testing, suggestions, bugfixes, improvements were
+ *	provided by:
+ *
+ *	George Anzinger, Andrew Morton, Steven Rostedt, Roman Zippel
+ *	et. al.
+ *
  *  For licencing details see kernel-base/COPYING
  */
 
@@ -66,6 +72,12 @@
 
 /*
  * The timer bases:
+ *
+ * Note: If we want to add new timer bases, we have to skip the two
+ * clock ids captured by the cpu-timers. We do this by holding empty
+ * entries rather than doing math adjustment of the clock ids.
+ * This ensures that we capture erroneous accesses to these clock ids
+ * rather than moving them into the range of valid clock id's.
  */
 
 #define MAX_HRTIMER_BASES 2
@@ -483,29 +495,25 @@
 }
 
 /**
- * hrtimer_rebase - rebase an initialized hrtimer to a different base
- *
- * @timer:	the timer to be rebased
- * @clock_id:	the clock to be used
- */
-void hrtimer_rebase(struct hrtimer *timer, const clockid_t clock_id)
-{
-	struct hrtimer_base *bases;
-
-	bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
-	timer->base = &bases[clock_id];
-}
-
-/**
  * hrtimer_init - initialize a timer to the given clock
  *
  * @timer:	the timer to be initialized
  * @clock_id:	the clock to be used
+ * @mode:	timer mode abs/rel
  */
-void hrtimer_init(struct hrtimer *timer, const clockid_t clock_id)
+void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+		  enum hrtimer_mode mode)
 {
+	struct hrtimer_base *bases;
+
 	memset(timer, 0, sizeof(struct hrtimer));
-	hrtimer_rebase(timer, clock_id);
+
+	bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
+
+	if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS)
+		clock_id = CLOCK_MONOTONIC;
+
+	timer->base = &bases[clock_id];
 }
 
 /**
@@ -550,6 +558,7 @@
 		fn = timer->function;
 		data = timer->data;
 		set_curr_timer(base, timer);
+		timer->state = HRTIMER_RUNNING;
 		__remove_hrtimer(timer, base);
 		spin_unlock_irq(&base->lock);
 
@@ -565,6 +574,10 @@
 
 		spin_lock_irq(&base->lock);
 
+		/* Another CPU has added back the timer */
+		if (timer->state != HRTIMER_RUNNING)
+			continue;
+
 		if (restart == HRTIMER_RESTART)
 			enqueue_hrtimer(timer, base);
 		else
@@ -638,8 +651,7 @@
 	return schedule_hrtimer(timer, mode);
 }
 
-static long __sched
-nanosleep_restart(struct restart_block *restart, clockid_t clockid)
+static long __sched nanosleep_restart(struct restart_block *restart)
 {
 	struct timespec __user *rmtp;
 	struct timespec tu;
@@ -649,7 +661,7 @@
 
 	restart->fn = do_no_restart_syscall;
 
-	hrtimer_init(&timer, clockid);
+	hrtimer_init(&timer, (clockid_t) restart->arg3, HRTIMER_ABS);
 
 	timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0;
 
@@ -669,16 +681,6 @@
 	return -ERESTART_RESTARTBLOCK;
 }
 
-static long __sched nanosleep_restart_mono(struct restart_block *restart)
-{
-	return nanosleep_restart(restart, CLOCK_MONOTONIC);
-}
-
-static long __sched nanosleep_restart_real(struct restart_block *restart)
-{
-	return nanosleep_restart(restart, CLOCK_REALTIME);
-}
-
 long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
 		       const enum hrtimer_mode mode, const clockid_t clockid)
 {
@@ -687,7 +689,7 @@
 	struct timespec tu;
 	ktime_t rem;
 
-	hrtimer_init(&timer, clockid);
+	hrtimer_init(&timer, clockid, mode);
 
 	timer.expires = timespec_to_ktime(*rqtp);
 
@@ -695,7 +697,7 @@
 	if (rem.tv64 <= 0)
 		return 0;
 
-	/* Absolute timers do not update the rmtp value: */
+	/* Absolute timers do not update the rmtp value and restart: */
 	if (mode == HRTIMER_ABS)
 		return -ERESTARTNOHAND;
 
@@ -705,11 +707,11 @@
 		return -EFAULT;
 
 	restart = &current_thread_info()->restart_block;
-	restart->fn = (clockid == CLOCK_MONOTONIC) ?
-		nanosleep_restart_mono : nanosleep_restart_real;
+	restart->fn = nanosleep_restart;
 	restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF;
 	restart->arg1 = timer.expires.tv64 >> 32;
 	restart->arg2 = (unsigned long) rmtp;
+	restart->arg3 = (unsigned long) timer.base->index;
 
 	return -ERESTART_RESTARTBLOCK;
 }
@@ -736,10 +738,8 @@
 	struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu);
 	int i;
 
-	for (i = 0; i < MAX_HRTIMER_BASES; i++) {
+	for (i = 0; i < MAX_HRTIMER_BASES; i++, base++)
 		spin_lock_init(&base->lock);
-		base++;
-	}
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/kernel/intermodule.c b/kernel/intermodule.c
index 0cbe633..55b1e5b 100644
--- a/kernel/intermodule.c
+++ b/kernel/intermodule.c
@@ -179,3 +179,6 @@
 EXPORT_SYMBOL(inter_module_unregister);
 EXPORT_SYMBOL(inter_module_get_request);
 EXPORT_SYMBOL(inter_module_put);
+
+MODULE_LICENSE("GPL");
+
diff --git a/kernel/itimer.c b/kernel/itimer.c
index c2c05c4..379be2f 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -49,9 +49,11 @@
 
 	switch (which) {
 	case ITIMER_REAL:
+		spin_lock_irq(&tsk->sighand->siglock);
 		value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
 		value->it_interval =
 			ktime_to_timeval(tsk->signal->it_real_incr);
+		spin_unlock_irq(&tsk->sighand->siglock);
 		break;
 	case ITIMER_VIRTUAL:
 		read_lock(&tasklist_lock);
@@ -150,18 +152,25 @@
 
 	switch (which) {
 	case ITIMER_REAL:
+again:
+		spin_lock_irq(&tsk->sighand->siglock);
 		timer = &tsk->signal->real_timer;
-		hrtimer_cancel(timer);
 		if (ovalue) {
 			ovalue->it_value = itimer_get_remtime(timer);
 			ovalue->it_interval
 				= ktime_to_timeval(tsk->signal->it_real_incr);
 		}
+		/* We are sharing ->siglock with it_real_fn() */
+		if (hrtimer_try_to_cancel(timer) < 0) {
+			spin_unlock_irq(&tsk->sighand->siglock);
+			goto again;
+		}
 		tsk->signal->it_real_incr =
 			timeval_to_ktime(value->it_interval);
 		expires = timeval_to_ktime(value->it_value);
 		if (expires.tv64 != 0)
 			hrtimer_start(timer, expires, HRTIMER_REL);
+		spin_unlock_irq(&tsk->sighand->siglock);
 		break;
 	case ITIMER_VIRTUAL:
 		nval = timeval_to_cputime(&value->it_value);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 3ea6325..fef1af8 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -344,23 +344,6 @@
 	spin_unlock_irqrestore(&kretprobe_lock, flags);
 }
 
-/*
- * This kprobe pre_handler is registered with every kretprobe. When probe
- * hits it will set up the return probe.
- */
-static int __kprobes pre_handler_kretprobe(struct kprobe *p,
-					   struct pt_regs *regs)
-{
-	struct kretprobe *rp = container_of(p, struct kretprobe, kp);
-	unsigned long flags = 0;
-
-	/*TODO: consider to only swap the RA after the last pre_handler fired */
-	spin_lock_irqsave(&kretprobe_lock, flags);
-	arch_prepare_kretprobe(rp, regs);
-	spin_unlock_irqrestore(&kretprobe_lock, flags);
-	return 0;
-}
-
 static inline void free_rp_inst(struct kretprobe *rp)
 {
 	struct kretprobe_instance *ri;
@@ -578,6 +561,23 @@
 
 #ifdef ARCH_SUPPORTS_KRETPROBES
 
+/*
+ * This kprobe pre_handler is registered with every kretprobe. When probe
+ * hits it will set up the return probe.
+ */
+static int __kprobes pre_handler_kretprobe(struct kprobe *p,
+					   struct pt_regs *regs)
+{
+	struct kretprobe *rp = container_of(p, struct kretprobe, kp);
+	unsigned long flags = 0;
+
+	/*TODO: consider to only swap the RA after the last pre_handler fired */
+	spin_lock_irqsave(&kretprobe_lock, flags);
+	arch_prepare_kretprobe(rp, regs);
+	spin_unlock_irqrestore(&kretprobe_lock, flags);
+	return 0;
+}
+
 int __kprobes register_kretprobe(struct kretprobe *rp)
 {
 	int ret = 0;
@@ -631,12 +631,12 @@
 	unregister_kprobe(&rp->kp);
 	/* No race here */
 	spin_lock_irqsave(&kretprobe_lock, flags);
-	free_rp_inst(rp);
 	while ((ri = get_used_rp_inst(rp)) != NULL) {
 		ri->rp = NULL;
 		hlist_del(&ri->uflist);
 	}
 	spin_unlock_irqrestore(&kretprobe_lock, flags);
+	free_rp_inst(rp);
 }
 
 static int __init init_kprobes(void)
diff --git a/kernel/module.c b/kernel/module.c
index 618ed6e..5aad477 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1670,6 +1670,9 @@
 		goto free_mod;
 	}
 
+	/* Userspace could have altered the string after the strlen_user() */
+	args[arglen - 1] = '\0';
+
 	if (find_module(mod->name)) {
 		err = -EEXIST;
 		goto free_mod;
@@ -2092,7 +2095,8 @@
 	unsigned int i;
 
 	for (i = 0; i < mod->num_symtab; i++)
-		if (strcmp(name, mod->strtab+mod->symtab[i].st_name) == 0)
+		if (strcmp(name, mod->strtab+mod->symtab[i].st_name) == 0 &&
+		    mod->symtab[i].st_info != 'U')
 			return mod->symtab[i].st_value;
 	return 0;
 }
diff --git a/kernel/panic.c b/kernel/panic.c
index c5c4ab2..126dc43 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -130,6 +130,7 @@
 #endif
 	local_irq_enable();
 	for (i = 0;;) {
+		touch_softlockup_watchdog();
 		i += panic_blink(i);
 		mdelay(1);
 		i++;
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 197208b..216f574 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -194,9 +194,7 @@
 
 static int common_timer_create(struct k_itimer *new_timer)
 {
-	hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock);
-	new_timer->it.real.timer.data = new_timer;
-	new_timer->it.real.timer.function = posix_timer_fn;
+	hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0);
 	return 0;
 }
 
@@ -290,7 +288,8 @@
 		info->si_overrun = timr->it_overrun_last;
 	}
 
-	unlock_timer(timr, flags);
+	if (timr)
+		unlock_timer(timr, flags);
 }
 
 int posix_timer_event(struct k_itimer *timr,int si_private)
@@ -692,6 +691,7 @@
 		 struct itimerspec *new_setting, struct itimerspec *old_setting)
 {
 	struct hrtimer *timer = &timr->it.real.timer;
+	enum hrtimer_mode mode;
 
 	if (old_setting)
 		common_timer_get(timr, old_setting);
@@ -713,14 +713,10 @@
 	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec)
 		return 0;
 
-	/* Posix madness. Only absolute CLOCK_REALTIME timers
-	 * are affected by clock sets. So we must reiniatilize
-	 * the timer.
-	 */
-	if (timr->it_clock == CLOCK_REALTIME && (flags & TIMER_ABSTIME))
-		hrtimer_rebase(timer, CLOCK_REALTIME);
-	else
-		hrtimer_rebase(timer, CLOCK_MONOTONIC);
+	mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
+	hrtimer_init(&timr->it.real.timer, timr->it_clock, mode);
+	timr->it.real.timer.data = timr;
+	timr->it.real.timer.function = posix_timer_fn;
 
 	timer->expires = timespec_to_ktime(new_setting->it_value);
 
@@ -728,11 +724,15 @@
 	timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
 
 	/* SIGEV_NONE timers are not queued ! See common_timer_get */
-	if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+	if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
+		/* Setup correct expiry time for relative timers */
+		if (mode == HRTIMER_REL)
+			timer->expires = ktime_add(timer->expires,
+						   timer->base->get_time());
 		return 0;
+	}
 
-	hrtimer_start(timer, timer->expires, (flags & TIMER_ABSTIME) ?
-		      HRTIMER_ABS : HRTIMER_REL);
+	hrtimer_start(timer, timer->expires, mode);
 	return 0;
 }
 
@@ -875,12 +875,6 @@
 }
 EXPORT_SYMBOL_GPL(do_posix_clock_nosettime);
 
-int do_posix_clock_notimer_create(struct k_itimer *timer)
-{
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(do_posix_clock_notimer_create);
-
 int do_posix_clock_nonanosleep(const clockid_t clock, int flags,
 			       struct timespec *t, struct timespec __user *r)
 {
@@ -947,21 +941,8 @@
 static int common_nsleep(const clockid_t which_clock, int flags,
 			 struct timespec *tsave, struct timespec __user *rmtp)
 {
-	int mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
-	int clockid = which_clock;
-
-	switch (which_clock) {
-	case CLOCK_REALTIME:
-		/* Posix madness. Only absolute timers on clock realtime
-		   are affected by clock set. */
-		if (mode != HRTIMER_ABS)
-			clockid = CLOCK_MONOTONIC;
-	case CLOCK_MONOTONIC:
-		break;
-	default:
-		return -EINVAL;
-	}
-	return hrtimer_nanosleep(tsave, rmtp, mode, clockid);
+	return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
+				 HRTIMER_ABS : HRTIMER_REL, which_clock);
 }
 
 asmlinkage long
diff --git a/kernel/power/console.c b/kernel/power/console.c
index 7ff375e..623786d 100644
--- a/kernel/power/console.c
+++ b/kernel/power/console.c
@@ -9,18 +9,13 @@
 #include <linux/console.h>
 #include "power.h"
 
-static int new_loglevel = 10;
-static int orig_loglevel;
-#ifdef SUSPEND_CONSOLE
+#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
+#define SUSPEND_CONSOLE	(MAX_NR_CONSOLES-1)
+
 static int orig_fgconsole, orig_kmsg;
-#endif
 
 int pm_prepare_console(void)
 {
-	orig_loglevel = console_loglevel;
-	console_loglevel = new_loglevel;
-
-#ifdef SUSPEND_CONSOLE
 	acquire_console_sem();
 
 	orig_fgconsole = fg_console;
@@ -41,18 +36,15 @@
 	}
 	orig_kmsg = kmsg_redirect;
 	kmsg_redirect = SUSPEND_CONSOLE;
-#endif
 	return 0;
 }
 
 void pm_restore_console(void)
 {
-	console_loglevel = orig_loglevel;
-#ifdef SUSPEND_CONSOLE
 	acquire_console_sem();
 	set_console(orig_fgconsole);
 	release_console_sem();
 	kmsg_redirect = orig_kmsg;
-#endif
 	return;
 }
+#endif
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index e24446f..0b43847 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -53,7 +53,7 @@
 
 	switch(mode) {
 	case PM_DISK_PLATFORM:
-		kernel_power_off_prepare();
+		kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
 		error = pm_ops->enter(PM_SUSPEND_DISK);
 		break;
 	case PM_DISK_SHUTDOWN:
@@ -95,13 +95,6 @@
 		goto thaw;
 	}
 
-	if (pm_disk_mode == PM_DISK_PLATFORM) {
-		if (pm_ops && pm_ops->prepare) {
-			if ((error = pm_ops->prepare(PM_SUSPEND_DISK)))
-				goto thaw;
-		}
-	}
-
 	/* Free memory before shutting down devices. */
 	if (!(error = swsusp_shrink_memory()))
 		return 0;
@@ -367,14 +360,14 @@
 
 static ssize_t image_size_show(struct subsystem * subsys, char *buf)
 {
-	return sprintf(buf, "%u\n", image_size);
+	return sprintf(buf, "%lu\n", image_size);
 }
 
 static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n)
 {
-	unsigned int size;
+	unsigned long size;
 
-	if (sscanf(buf, "%u", &size) == 1) {
+	if (sscanf(buf, "%lu", &size) == 1) {
 		image_size = size;
 		return n;
 	}
diff --git a/kernel/power/main.c b/kernel/power/main.c
index d253f3a..9cb235c 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -133,10 +133,10 @@
 static void suspend_finish(suspend_state_t state)
 {
 	device_resume();
-	if (pm_ops && pm_ops->finish)
-		pm_ops->finish(state);
 	thaw_processes();
 	enable_nonboot_cpus();
+	if (pm_ops && pm_ops->finish)
+		pm_ops->finish(state);
 	pm_restore_console();
 }
 
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 7e8492f..388dba6 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -1,14 +1,6 @@
 #include <linux/suspend.h>
 #include <linux/utsname.h>
 
-/* With SUSPEND_CONSOLE defined suspend looks *really* cool, but
-   we probably do not take enough locks for switching consoles, etc,
-   so bad things might happen.
-*/
-#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
-#define SUSPEND_CONSOLE	(MAX_NR_CONSOLES-1)
-#endif
-
 struct swsusp_info {
 	struct new_utsname	uts;
 	u32			version_code;
@@ -42,17 +34,14 @@
 
 extern struct subsystem power_subsys;
 
-extern int pm_prepare_console(void);
-extern void pm_restore_console(void);
-
 /* References to section boundaries */
 extern const void __nosave_begin, __nosave_end;
 
 extern unsigned int nr_copy_pages;
 extern struct pbe *pagedir_nosave;
 
-/* Preferred image size in MB (default 500) */
-extern unsigned int image_size;
+/* Preferred image size in bytes (default 500 MB) */
+extern unsigned long image_size;
 
 extern asmlinkage int swsusp_arch_suspend(void);
 extern asmlinkage int swsusp_arch_resume(void);
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 55a18d2..4e90905 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -70,12 +70,12 @@
 #include "power.h"
 
 /*
- * Preferred image size in MB (tunable via /sys/power/image_size).
+ * Preferred image size in bytes (tunable via /sys/power/image_size).
  * When it is set to N, swsusp will do its best to ensure the image
- * size will not exceed N MB, but if that is impossible, it will
+ * size will not exceed N bytes, but if that is impossible, it will
  * try to create the smallest image possible.
  */
-unsigned int image_size = 500;
+unsigned long image_size = 500 * 1024 * 1024;
 
 #ifdef CONFIG_HIGHMEM
 unsigned int count_highmem_pages(void);
@@ -590,7 +590,7 @@
 			if (!tmp)
 				return -ENOMEM;
 			pages += tmp;
-		} else if (size > (image_size * 1024 * 1024) / PAGE_SIZE) {
+		} else if (size > image_size / PAGE_SIZE) {
 			tmp = shrink_all_memory(SHRINK_BITE);
 			pages += tmp;
 		}
@@ -743,7 +743,6 @@
 	if (!bio)
 		return -ENOMEM;
 	bio->bi_sector = page_off * (PAGE_SIZE >> 9);
-	bio_get(bio);
 	bio->bi_bdev = resume_bdev;
 	bio->bi_end_io = end_io;
 
@@ -753,14 +752,13 @@
 		goto Done;
 	}
 
-	if (rw == WRITE)
-		bio_set_pages_dirty(bio);
 
 	atomic_set(&io_done, 1);
 	submit_bio(rw | (1 << BIO_RW_SYNC), bio);
 	while (atomic_read(&io_done))
 		yield();
-
+	if (rw == READ)
+		bio_set_pages_dirty(bio);
  Done:
 	bio_put(bio);
 	return error;
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 7732199..7712912 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -114,16 +114,16 @@
 {
 	struct list_head *p;
 
-	spin_lock(&rcu_torture_lock);
+	spin_lock_bh(&rcu_torture_lock);
 	if (list_empty(&rcu_torture_freelist)) {
 		atomic_inc(&n_rcu_torture_alloc_fail);
-		spin_unlock(&rcu_torture_lock);
+		spin_unlock_bh(&rcu_torture_lock);
 		return NULL;
 	}
 	atomic_inc(&n_rcu_torture_alloc);
 	p = rcu_torture_freelist.next;
 	list_del_init(p);
-	spin_unlock(&rcu_torture_lock);
+	spin_unlock_bh(&rcu_torture_lock);
 	return container_of(p, struct rcu_torture, rtort_free);
 }
 
@@ -134,9 +134,9 @@
 rcu_torture_free(struct rcu_torture *p)
 {
 	atomic_inc(&n_rcu_torture_free);
-	spin_lock(&rcu_torture_lock);
+	spin_lock_bh(&rcu_torture_lock);
 	list_add_tail(&p->rtort_free, &rcu_torture_freelist);
-	spin_unlock(&rcu_torture_lock);
+	spin_unlock_bh(&rcu_torture_lock);
 }
 
 static void
diff --git a/kernel/sched.c b/kernel/sched.c
index 788ecce..87d93be 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -215,7 +215,6 @@
 	 */
 	unsigned long nr_running;
 #ifdef CONFIG_SMP
-	unsigned long prio_bias;
 	unsigned long cpu_load[3];
 #endif
 	unsigned long long nr_switches;
@@ -669,68 +668,13 @@
 	return prio;
 }
 
-#ifdef CONFIG_SMP
-static inline void inc_prio_bias(runqueue_t *rq, int prio)
-{
-	rq->prio_bias += MAX_PRIO - prio;
-}
-
-static inline void dec_prio_bias(runqueue_t *rq, int prio)
-{
-	rq->prio_bias -= MAX_PRIO - prio;
-}
-
-static inline void inc_nr_running(task_t *p, runqueue_t *rq)
-{
-	rq->nr_running++;
-	if (rt_task(p)) {
-		if (p != rq->migration_thread)
-			/*
-			 * The migration thread does the actual balancing. Do
-			 * not bias by its priority as the ultra high priority
-			 * will skew balancing adversely.
-			 */
-			inc_prio_bias(rq, p->prio);
-	} else
-		inc_prio_bias(rq, p->static_prio);
-}
-
-static inline void dec_nr_running(task_t *p, runqueue_t *rq)
-{
-	rq->nr_running--;
-	if (rt_task(p)) {
-		if (p != rq->migration_thread)
-			dec_prio_bias(rq, p->prio);
-	} else
-		dec_prio_bias(rq, p->static_prio);
-}
-#else
-static inline void inc_prio_bias(runqueue_t *rq, int prio)
-{
-}
-
-static inline void dec_prio_bias(runqueue_t *rq, int prio)
-{
-}
-
-static inline void inc_nr_running(task_t *p, runqueue_t *rq)
-{
-	rq->nr_running++;
-}
-
-static inline void dec_nr_running(task_t *p, runqueue_t *rq)
-{
-	rq->nr_running--;
-}
-#endif
-
 /*
  * __activate_task - move a task to the runqueue.
  */
 static inline void __activate_task(task_t *p, runqueue_t *rq)
 {
 	enqueue_task(p, rq->active);
-	inc_nr_running(p, rq);
+	rq->nr_running++;
 }
 
 /*
@@ -739,7 +683,7 @@
 static inline void __activate_idle_task(task_t *p, runqueue_t *rq)
 {
 	enqueue_task_head(p, rq->active);
-	inc_nr_running(p, rq);
+	rq->nr_running++;
 }
 
 static int recalc_task_prio(task_t *p, unsigned long long now)
@@ -863,7 +807,7 @@
  */
 static void deactivate_task(struct task_struct *p, runqueue_t *rq)
 {
-	dec_nr_running(p, rq);
+	rq->nr_running--;
 	dequeue_task(p, p->array);
 	p->array = NULL;
 }
@@ -1007,61 +951,27 @@
  * We want to under-estimate the load of migration sources, to
  * balance conservatively.
  */
-static unsigned long __source_load(int cpu, int type, enum idle_type idle)
-{
-	runqueue_t *rq = cpu_rq(cpu);
-	unsigned long running = rq->nr_running;
-	unsigned long source_load, cpu_load = rq->cpu_load[type-1],
-		load_now = running * SCHED_LOAD_SCALE;
-
-	if (type == 0)
-		source_load = load_now;
-	else
-		source_load = min(cpu_load, load_now);
-
-	if (running > 1 || (idle == NOT_IDLE && running))
-		/*
-		 * If we are busy rebalancing the load is biased by
-		 * priority to create 'nice' support across cpus. When
-		 * idle rebalancing we should only bias the source_load if
-		 * there is more than one task running on that queue to
-		 * prevent idle rebalance from trying to pull tasks from a
-		 * queue with only one running task.
-		 */
-		source_load = source_load * rq->prio_bias / running;
-
-	return source_load;
-}
-
 static inline unsigned long source_load(int cpu, int type)
 {
-	return __source_load(cpu, type, NOT_IDLE);
+	runqueue_t *rq = cpu_rq(cpu);
+	unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE;
+	if (type == 0)
+		return load_now;
+
+	return min(rq->cpu_load[type-1], load_now);
 }
 
 /*
  * Return a high guess at the load of a migration-target cpu
  */
-static inline unsigned long __target_load(int cpu, int type, enum idle_type idle)
-{
-	runqueue_t *rq = cpu_rq(cpu);
-	unsigned long running = rq->nr_running;
-	unsigned long target_load, cpu_load = rq->cpu_load[type-1],
-		load_now = running * SCHED_LOAD_SCALE;
-
-	if (type == 0)
-		target_load = load_now;
-	else
-		target_load = max(cpu_load, load_now);
-
-	if (running > 1 || (idle == NOT_IDLE && running))
-		target_load = target_load * rq->prio_bias / running;
-
-	return target_load;
-}
-
 static inline unsigned long target_load(int cpu, int type)
 {
-	return __target_load(cpu, type, NOT_IDLE);
+	runqueue_t *rq = cpu_rq(cpu);
+	unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE;
+	if (type == 0)
+		return load_now;
+
+	return max(rq->cpu_load[type-1], load_now);
 }
 
 /*
@@ -1530,7 +1440,7 @@
 				list_add_tail(&p->run_list, &current->run_list);
 				p->array = current->array;
 				p->array->nr_active++;
-				inc_nr_running(p, rq);
+				rq->nr_running++;
 			}
 			set_need_resched();
 		} else
@@ -1875,9 +1785,9 @@
 	       runqueue_t *this_rq, prio_array_t *this_array, int this_cpu)
 {
 	dequeue_task(p, src_array);
-	dec_nr_running(p, src_rq);
+	src_rq->nr_running--;
 	set_task_cpu(p, this_cpu);
-	inc_nr_running(p, this_rq);
+	this_rq->nr_running++;
 	enqueue_task(p, this_array);
 	p->timestamp = (p->timestamp - src_rq->timestamp_last_tick)
 				+ this_rq->timestamp_last_tick;
@@ -2056,9 +1966,9 @@
 
 			/* Bias balancing toward cpus of our domain */
 			if (local_group)
-				load = __target_load(i, load_idx, idle);
+				load = target_load(i, load_idx);
 			else
-				load = __source_load(i, load_idx, idle);
+				load = source_load(i, load_idx);
 
 			avg_load += load;
 		}
@@ -2171,7 +2081,7 @@
 	int i;
 
 	for_each_cpu_mask(i, group->cpumask) {
-		load = __source_load(i, 0, idle);
+		load = source_load(i, 0);
 
 		if (load > max_load) {
 			max_load = load;
@@ -3571,10 +3481,8 @@
 		goto out_unlock;
 	}
 	array = p->array;
-	if (array) {
+	if (array)
 		dequeue_task(p, array);
-		dec_prio_bias(rq, p->static_prio);
-	}
 
 	old_prio = p->prio;
 	new_prio = NICE_TO_PRIO(nice);
@@ -3584,7 +3492,6 @@
 
 	if (array) {
 		enqueue_task(p, array);
-		inc_prio_bias(rq, p->static_prio);
 		/*
 		 * If the task increased its priority or is running and
 		 * lowered its priority, then reschedule its CPU:
@@ -3850,6 +3757,10 @@
 asmlinkage long sys_sched_setscheduler(pid_t pid, int policy,
 				       struct sched_param __user *param)
 {
+	/* negative values for policy are not valid */
+	if (policy < 0)
+		return -EINVAL;
+
 	return do_sched_setscheduler(pid, policy, param);
 }
 
@@ -4027,7 +3938,7 @@
 		goto out_unlock;
 
 	retval = 0;
-	cpus_and(*mask, p->cpus_allowed, cpu_possible_map);
+	cpus_and(*mask, p->cpus_allowed, cpu_online_map);
 
 out_unlock:
 	read_unlock(&tasklist_lock);
@@ -5137,7 +5048,7 @@
 #define SEARCH_SCOPE		2
 #define MIN_CACHE_SIZE		(64*1024U)
 #define DEFAULT_CACHE_SIZE	(5*1024*1024U)
-#define ITERATIONS		2
+#define ITERATIONS		1
 #define SIZE_THRESH		130
 #define COST_THRESH		130
 
@@ -5476,9 +5387,9 @@
 				break;
 			}
 		/*
-		 * Increase the cachesize in 5% steps:
+		 * Increase the cachesize in 10% steps:
 		 */
-		size = size * 20 / 19;
+		size = size * 10 / 9;
 	}
 
 	if (migration_debug)
@@ -5547,13 +5458,15 @@
 			-1
 #endif
 		);
-	printk("migration_cost=");
-	for (distance = 0; distance <= max_distance; distance++) {
-		if (distance)
-			printk(",");
-		printk("%ld", (long)migration_cost[distance] / 1000);
+	if (system_state == SYSTEM_BOOTING) {
+		printk("migration_cost=");
+		for (distance = 0; distance <= max_distance; distance++) {
+			if (distance)
+				printk(",");
+			printk("%ld", (long)migration_cost[distance] / 1000);
+		}
+		printk("\n");
 	}
-	printk("\n");
 	j1 = jiffies;
 	if (migration_debug)
 		printk("migration: %ld seconds\n", (j1-j0)/HZ);
@@ -6105,7 +6018,7 @@
 	runqueue_t *rq;
 	int i, j, k;
 
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_cpu(i) {
 		prio_array_t *array;
 
 		rq = cpu_rq(i);
diff --git a/kernel/signal.c b/kernel/signal.c
index 5dafbd3..ea15410 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -283,7 +283,7 @@
 	return(q);
 }
 
-static inline void __sigqueue_free(struct sigqueue *q)
+static void __sigqueue_free(struct sigqueue *q)
 {
 	if (q->flags & SIGQUEUE_PREALLOC)
 		return;
@@ -2430,7 +2430,7 @@
 }
 
 int
-do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
+do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
 {
 	struct k_sigaction *k;
 	sigset_t mask;
@@ -2454,6 +2454,8 @@
 		*oact = *k;
 
 	if (act) {
+		sigdelsetmask(&act->sa.sa_mask,
+			      sigmask(SIGKILL) | sigmask(SIGSTOP));
 		/*
 		 * POSIX 3.3.1.3:
 		 *  "Setting a signal action to SIG_IGN for a signal that is
@@ -2479,8 +2481,6 @@
 			read_lock(&tasklist_lock);
 			spin_lock_irq(&t->sighand->siglock);
 			*k = *act;
-			sigdelsetmask(&k->sa.sa_mask,
-				      sigmask(SIGKILL) | sigmask(SIGSTOP));
 			sigemptyset(&mask);
 			sigaddset(&mask, sig);
 			rm_from_queue_full(&mask, &t->signal->shared_pending);
@@ -2495,8 +2495,6 @@
 		}
 
 		*k = *act;
-		sigdelsetmask(&k->sa.sa_mask,
-			      sigmask(SIGKILL) | sigmask(SIGSTOP));
 	}
 
 	spin_unlock_irq(&current->sighand->siglock);
@@ -2702,6 +2700,7 @@
 
 	new_sa.sa.sa_handler = handler;
 	new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;
+	sigemptyset(&new_sa.sa.sa_mask);
 
 	ret = do_sigaction(sig, &new_sa, &old_sa);
 
@@ -2721,6 +2720,32 @@
 
 #endif
 
+#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
+asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
+{
+	sigset_t newset;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset, unewset, sizeof(newset)))
+		return -EFAULT;
+	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+	spin_lock_irq(&current->sighand->siglock);
+	current->saved_sigmask = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
+}
+#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
+
 void __init signals_init(void)
 {
 	sigqueue_cachep =
diff --git a/kernel/sys.c b/kernel/sys.c
index d09cac2..f91218a 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -428,7 +428,7 @@
 {
 #ifdef CONFIG_KEXEC
 	struct kimage *image;
-	image = xchg(&kexec_image, 0);
+	image = xchg(&kexec_image, NULL);
 	if (!image) {
 		return;
 	}
@@ -440,23 +440,25 @@
 }
 EXPORT_SYMBOL_GPL(kernel_kexec);
 
+void kernel_shutdown_prepare(enum system_states state)
+{
+	notifier_call_chain(&reboot_notifier_list,
+		(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);
+	system_state = state;
+	device_shutdown();
+}
 /**
  *	kernel_halt - halt the system
  *
  *	Shutdown everything and perform a clean system halt.
  */
-void kernel_halt_prepare(void)
-{
-	notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
-	system_state = SYSTEM_HALT;
-	device_shutdown();
-}
 void kernel_halt(void)
 {
-	kernel_halt_prepare();
+	kernel_shutdown_prepare(SYSTEM_HALT);
 	printk(KERN_EMERG "System halted.\n");
 	machine_halt();
 }
+
 EXPORT_SYMBOL_GPL(kernel_halt);
 
 /**
@@ -464,20 +466,13 @@
  *
  *	Shutdown everything and perform a clean system power_off.
  */
-void kernel_power_off_prepare(void)
-{
-	notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
-	system_state = SYSTEM_POWER_OFF;
-	device_shutdown();
-}
 void kernel_power_off(void)
 {
-	kernel_power_off_prepare();
+	kernel_shutdown_prepare(SYSTEM_POWER_OFF);
 	printk(KERN_EMERG "Power down.\n");
 	machine_power_off();
 }
 EXPORT_SYMBOL_GPL(kernel_power_off);
-
 /*
  * Reboot system call: for obvious reasons only root may call it,
  * and even root needs to set up some magic numbers in the registers
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index f5d69b6..71dd6f6 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -870,6 +870,27 @@
 		.strategy	= &sysctl_jiffies,
 	},
 #endif
+#ifdef CONFIG_NUMA
+	{
+		.ctl_name	= VM_ZONE_RECLAIM_MODE,
+		.procname	= "zone_reclaim_mode",
+		.data		= &zone_reclaim_mode,
+		.maxlen		= sizeof(zone_reclaim_mode),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
+	{
+		.ctl_name	= VM_ZONE_RECLAIM_INTERVAL,
+		.procname	= "zone_reclaim_interval",
+		.data		= &zone_reclaim_interval,
+		.maxlen		= sizeof(zone_reclaim_interval),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+		.strategy	= &sysctl_jiffies,
+	},
+#endif
 	{ .ctl_name = 0 }
 };
 
diff --git a/kernel/time.c b/kernel/time.c
index 7477b1d..8045391 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -155,7 +155,7 @@
 	static int firsttime = 1;
 	int error = 0;
 
-	if (!timespec_valid(tv))
+	if (tv && !timespec_valid(tv))
 		return -EINVAL;
 
 	error = security_settime(tv, tz);
@@ -637,15 +637,16 @@
  *
  * Returns the timespec representation of the nsec parameter.
  */
-inline struct timespec ns_to_timespec(const nsec_t nsec)
+struct timespec ns_to_timespec(const nsec_t nsec)
 {
 	struct timespec ts;
 
-	if (nsec)
-		ts.tv_sec = div_long_long_rem_signed(nsec, NSEC_PER_SEC,
-						     &ts.tv_nsec);
-	else
-		ts.tv_sec = ts.tv_nsec = 0;
+	if (!nsec)
+		return (struct timespec) {0, 0};
+
+	ts.tv_sec = div_long_long_rem_signed(nsec, NSEC_PER_SEC, &ts.tv_nsec);
+	if (unlikely(nsec < 0))
+		set_normalized_timespec(&ts, ts.tv_sec, ts.tv_nsec);
 
 	return ts;
 }
diff --git a/kernel/timer.c b/kernel/timer.c
index 4f1cb0a..b9dad39 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -495,7 +495,7 @@
 	base = &__get_cpu_var(tvec_bases);
 	spin_lock(&base->t_base.lock);
 	expires = base->timer_jiffies + (LONG_MAX >> 1);
-	list = 0;
+	list = NULL;
 
 	/* Look for timer events in tv1. */
 	j = base->timer_jiffies & TVR_MASK;
diff --git a/kernel/user.c b/kernel/user.c
index 89e562f..d9deae4 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/key.h>
+#include <linux/interrupt.h>
 
 /*
  * UID task count cache, to get fast user lookup in "alloc_uid"
@@ -27,6 +28,16 @@
 
 static kmem_cache_t *uid_cachep;
 static struct list_head uidhash_table[UIDHASH_SZ];
+
+/*
+ * The uidhash_lock is mostly taken from process context, but it is
+ * occasionally also taken from softirq/tasklet context, when
+ * task-structs get RCU-freed. Hence all locking must be softirq-safe.
+ * But free_uid() is also called with local interrupts disabled, and running
+ * local_bh_enable() with local interrupts disabled is an error - we'll run
+ * softirq callbacks, and they can unconditionally enable interrupts, and
+ * the caller of free_uid() didn't expect that..
+ */
 static DEFINE_SPINLOCK(uidhash_lock);
 
 struct user_struct root_user = {
@@ -82,15 +93,19 @@
 struct user_struct *find_user(uid_t uid)
 {
 	struct user_struct *ret;
+	unsigned long flags;
 
-	spin_lock(&uidhash_lock);
+	spin_lock_irqsave(&uidhash_lock, flags);
 	ret = uid_hash_find(uid, uidhashentry(uid));
-	spin_unlock(&uidhash_lock);
+	spin_unlock_irqrestore(&uidhash_lock, flags);
 	return ret;
 }
 
 void free_uid(struct user_struct *up)
 {
+	unsigned long flags;
+
+	local_irq_save(flags);
 	if (up && atomic_dec_and_lock(&up->__count, &uidhash_lock)) {
 		uid_hash_remove(up);
 		key_put(up->uid_keyring);
@@ -98,6 +113,7 @@
 		kmem_cache_free(uid_cachep, up);
 		spin_unlock(&uidhash_lock);
 	}
+	local_irq_restore(flags);
 }
 
 struct user_struct * alloc_uid(uid_t uid)
@@ -105,9 +121,9 @@
 	struct list_head *hashent = uidhashentry(uid);
 	struct user_struct *up;
 
-	spin_lock(&uidhash_lock);
+	spin_lock_irq(&uidhash_lock);
 	up = uid_hash_find(uid, hashent);
-	spin_unlock(&uidhash_lock);
+	spin_unlock_irq(&uidhash_lock);
 
 	if (!up) {
 		struct user_struct *new;
@@ -137,7 +153,7 @@
 		 * Before adding this, check whether we raced
 		 * on adding the same user already..
 		 */
-		spin_lock(&uidhash_lock);
+		spin_lock_irq(&uidhash_lock);
 		up = uid_hash_find(uid, hashent);
 		if (up) {
 			key_put(new->uid_keyring);
@@ -147,7 +163,7 @@
 			uid_hash_insert(new, hashent);
 			up = new;
 		}
-		spin_unlock(&uidhash_lock);
+		spin_unlock_irq(&uidhash_lock);
 
 	}
 	return up;
@@ -183,9 +199,9 @@
 		INIT_LIST_HEAD(uidhash_table + n);
 
 	/* Insert the root user immediately (init already runs as root) */
-	spin_lock(&uidhash_lock);
+	spin_lock_irq(&uidhash_lock);
 	uid_hash_insert(&root_user, uidhashentry(0));
-	spin_unlock(&uidhash_lock);
+	spin_unlock_irq(&uidhash_lock);
 
 	return 0;
 }
diff --git a/lib/Makefile b/lib/Makefile
index 8535f4d..648b2c1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -9,7 +9,7 @@
 
 lib-y	+= kobject.o kref.o kobject_uevent.o klist.o
 
-obj-y += sort.o parser.o halfmd4.o
+obj-y += sort.o parser.o halfmd4.o iomap_copy.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c
index a5d2cdc..fd355a9 100644
--- a/lib/int_sqrt.c
+++ b/lib/int_sqrt.c
@@ -15,7 +15,7 @@
 	op = x;
 	res = 0;
 
-	one = 1 << 30;
+	one = 1UL << (BITS_PER_LONG - 2);
 	while (one > op)
 		one >>= 2;
 
diff --git a/lib/iomap_copy.c b/lib/iomap_copy.c
new file mode 100644
index 0000000..a6b1e27
--- /dev/null
+++ b/lib/iomap_copy.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 PathScale, Inc.  All Rights Reserved.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+
+/**
+ * __iowrite32_copy - copy data to MMIO space, in 32-bit units
+ * @to: destination, in MMIO space (must be 32-bit aligned)
+ * @from: source (must be 32-bit aligned)
+ * @count: number of 32-bit quantities to copy
+ *
+ * Copy data from kernel space to MMIO space, in units of 32 bits at a
+ * time.  Order of access is not guaranteed, nor is a memory barrier
+ * performed afterwards.
+ */
+void __attribute__((weak)) __iowrite32_copy(void __iomem *to,
+					    const void *from,
+					    size_t count)
+{
+	u32 __iomem *dst = to;
+	const u32 *src = from;
+	const u32 *end = src + count;
+
+	while (src < end)
+		__raw_writel(*src++, dst++);
+}
+EXPORT_SYMBOL_GPL(__iowrite32_copy);
diff --git a/lib/kobject.c b/lib/kobject.c
index 7a0e680..efe67fa 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -72,6 +72,8 @@
 	 * Add 1 to strlen for leading '/' of each level.
 	 */
 	do {
+		if (kobject_name(parent) == NULL)
+			return 0;
 		length += strlen(kobject_name(parent)) + 1;
 		parent = parent->parent;
 	} while (parent);
@@ -107,6 +109,8 @@
 	int len;
 
 	len = get_kobj_path_length(kobj);
+	if (len == 0)
+		return NULL;
 	path = kmalloc(len, gfp_mask);
 	if (!path)
 		return NULL;
@@ -162,6 +166,11 @@
 		return -ENOENT;
 	if (!kobj->k_name)
 		kobj->k_name = kobj->name;
+	if (!kobj->k_name) {
+		pr_debug("kobject attempted to be registered with no name!\n");
+		WARN_ON(1);
+		return -EINVAL;
+	}
 	parent = kobject_get(kobj->parent);
 
 	pr_debug("kobject %s: registering. parent: %s, set: %s\n",
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index f56e27a..1b1985c 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -22,7 +22,7 @@
 #include <linux/kobject.h>
 #include <net/sock.h>
 
-#define BUFFER_SIZE	1024	/* buffer for the variables */
+#define BUFFER_SIZE	2048	/* buffer for the variables */
 #define NUM_ENVP	32	/* number of env pointers */
 
 #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index c8bb8cc..d8b6bb4 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -72,9 +72,9 @@
 
 	for (;;) {
 		for (i = 0; i < loops_per_jiffy * HZ; i++) {
-			cpu_relax();
 			if (__raw_spin_trylock(&lock->raw_lock))
 				return;
+			__delay(1);
 		}
 		/* lockup suspected: */
 		if (print_once) {
@@ -144,9 +144,9 @@
 
 	for (;;) {
 		for (i = 0; i < loops_per_jiffy * HZ; i++) {
-			cpu_relax();
 			if (__raw_read_trylock(&lock->raw_lock))
 				return;
+			__delay(1);
 		}
 		/* lockup suspected: */
 		if (print_once) {
@@ -217,9 +217,9 @@
 
 	for (;;) {
 		for (i = 0; i < loops_per_jiffy * HZ; i++) {
-			cpu_relax();
 			if (__raw_write_trylock(&lock->raw_lock))
 				return;
+			__delay(1);
 		}
 		/* lockup suspected: */
 		if (print_once) {
diff --git a/lib/ts_bm.c b/lib/ts_bm.c
index 8a8b3a1..c4c1ac5 100644
--- a/lib/ts_bm.c
+++ b/lib/ts_bm.c
@@ -94,10 +94,28 @@
 	return UINT_MAX;
 }
 
+static int subpattern(u8 *pattern, int i, int j, int g)
+{
+	int x = i+g-1, y = j+g-1, ret = 0;
+
+	while(pattern[x--] == pattern[y--]) {
+		if (y < 0) {
+			ret = 1;
+			break;
+		}
+		if (--g == 0) {
+			ret = pattern[i-1] != pattern[j-1];
+			break;
+		}
+	}
+
+	return ret;
+}
+
 static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern,
 			       unsigned int len)
 {
-	int i, j, ended, l[ASIZE];
+	int i, j, g;
 
 	for (i = 0; i < ASIZE; i++)
 		bm->bad_shift[i] = len;
@@ -106,23 +124,15 @@
 
 	/* Compute the good shift array, used to match reocurrences 
 	 * of a subpattern */
-	for (i = 1; i < bm->patlen; i++) {
-		for (j = 0; j < bm->patlen && bm->pattern[bm->patlen - 1 - j]
-				== bm->pattern[bm->patlen - 1 - i - j]; j++);
-		l[i] = j;
-	}  
-
 	bm->good_shift[0] = 1;
 	for (i = 1; i < bm->patlen; i++)
 		bm->good_shift[i] = bm->patlen;
-	for (i = bm->patlen - 1; i > 0; i--)
-		bm->good_shift[l[i]] = i;
-	ended = 0;
-	for (i = 0; i < bm->patlen; i++) {
-		if (l[i] == bm->patlen - 1 - i)
-			ended = i;
-		if (ended)
-			bm->good_shift[i] = ended;
+        for (i = bm->patlen-1, g = 1; i > 0; g++, i--) {
+		for (j = i-1; j >= 1-g ; j--)
+			if (subpattern(bm->pattern, i, j, g)) {
+				bm->good_shift[g] = bm->patlen-j-g;
+				break;
+			}
 	}
 }
 
diff --git a/mm/filemap.c b/mm/filemap.c
index a965b6b..44da3d4 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -94,6 +94,7 @@
  *    ->private_lock		(try_to_unmap_one)
  *    ->tree_lock		(try_to_unmap_one)
  *    ->zone.lru_lock		(follow_page->mark_page_accessed)
+ *    ->zone.lru_lock		(check_pte_range->isolate_lru_page)
  *    ->private_lock		(page_remove_rmap->set_page_dirty)
  *    ->tree_lock		(page_remove_rmap->set_page_dirty)
  *    ->inode_lock		(page_remove_rmap->set_page_dirty)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index b21d78c..67f2951 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -107,7 +107,7 @@
 	set_page_count(page, 1);
 	page[1].mapping = (void *)free_huge_page;
 	for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); ++i)
-		clear_highpage(&page[i]);
+		clear_user_highpage(&page[i], addr);
 	return page;
 }
 
@@ -391,12 +391,7 @@
 
 	if (!new_page) {
 		page_cache_release(old_page);
-
-		/* Logically this is OOM, not a SIGBUS, but an OOM
-		 * could cause the kernel to go killing other
-		 * processes which won't help the hugepage situation
-		 * at all (?) */
-		return VM_FAULT_SIGBUS;
+		return VM_FAULT_OOM;
 	}
 
 	spin_unlock(&mm->page_table_lock);
@@ -444,6 +439,7 @@
 		page = alloc_huge_page(vma, address);
 		if (!page) {
 			hugetlb_put_quota(mapping);
+			ret = VM_FAULT_OOM;
 			goto out;
 		}
 
diff --git a/mm/memory.c b/mm/memory.c
index 7a11ddd..2bee1f2 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1871,6 +1871,7 @@
 		goto out;
 
 	entry = pte_to_swp_entry(orig_pte);
+again:
 	page = lookup_swap_cache(entry);
 	if (!page) {
  		swapin_readahead(entry, address, vma);
@@ -1894,6 +1895,12 @@
 
 	mark_page_accessed(page);
 	lock_page(page);
+	if (!PageSwapCache(page)) {
+		/* Page migration has occured */
+		unlock_page(page);
+		page_cache_release(page);
+		goto again;
+	}
 
 	/*
 	 * Back out if somebody else already faulted in this pte.
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 3171f88..3bd7fb7 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -95,6 +95,9 @@
 #define MPOL_MF_INVERT (MPOL_MF_INTERNAL << 1)		/* Invert check for nodemask */
 #define MPOL_MF_STATS (MPOL_MF_INTERNAL << 2)		/* Gather statistics */
 
+/* The number of pages to migrate per call to migrate_pages() */
+#define MIGRATE_CHUNK_SIZE 256
+
 static kmem_cache_t *policy_cache;
 static kmem_cache_t *sn_cache;
 
@@ -185,8 +188,8 @@
 }
 
 static void gather_stats(struct page *, void *);
-static void migrate_page_add(struct vm_area_struct *vma,
-	struct page *page, struct list_head *pagelist, unsigned long flags);
+static void migrate_page_add(struct page *page, struct list_head *pagelist,
+				unsigned long flags);
 
 /* Scan through pages checking if pages follow certain conditions. */
 static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
@@ -208,6 +211,17 @@
 		page = vm_normal_page(vma, addr, *pte);
 		if (!page)
 			continue;
+		/*
+		 * The check for PageReserved here is important to avoid
+		 * handling zero pages and other pages that may have been
+		 * marked special by the system.
+		 *
+		 * If the PageReserved would not be checked here then f.e.
+		 * the location of the zero page could have an influence
+		 * on MPOL_MF_STRICT, zero pages would be counted for
+		 * the per node stats, and there would be useless attempts
+		 * to put zero pages on the migration list.
+		 */
 		if (PageReserved(page))
 			continue;
 		nid = page_to_nid(page);
@@ -216,11 +230,8 @@
 
 		if (flags & MPOL_MF_STATS)
 			gather_stats(page, private);
-		else if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
-			spin_unlock(ptl);
-			migrate_page_add(vma, page, private, flags);
-			spin_lock(ptl);
-		}
+		else if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+			migrate_page_add(page, private, flags);
 		else
 			break;
 	} while (pte++, addr += PAGE_SIZE, addr != end);
@@ -309,6 +320,10 @@
 	int err;
 	struct vm_area_struct *first, *vma, *prev;
 
+	/* Clear the LRU lists so pages can be isolated */
+	if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+		lru_add_drain_all();
+
 	first = find_vma(mm, start);
 	if (!first)
 		return ERR_PTR(-EFAULT);
@@ -519,72 +534,103 @@
  * page migration
  */
 
-/* Check if we are the only process mapping the page in question */
-static inline int single_mm_mapping(struct mm_struct *mm,
-			struct address_space *mapping)
-{
-	struct vm_area_struct *vma;
-	struct prio_tree_iter iter;
-	int rc = 1;
-
-	spin_lock(&mapping->i_mmap_lock);
-	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, 0, ULONG_MAX)
-		if (mm != vma->vm_mm) {
-			rc = 0;
-			goto out;
-		}
-	list_for_each_entry(vma, &mapping->i_mmap_nonlinear, shared.vm_set.list)
-		if (mm != vma->vm_mm) {
-			rc = 0;
-			goto out;
-		}
-out:
-	spin_unlock(&mapping->i_mmap_lock);
-	return rc;
-}
-
-/*
- * Add a page to be migrated to the pagelist
- */
-static void migrate_page_add(struct vm_area_struct *vma,
-	struct page *page, struct list_head *pagelist, unsigned long flags)
+static void migrate_page_add(struct page *page, struct list_head *pagelist,
+				unsigned long flags)
 {
 	/*
-	 * Avoid migrating a page that is shared by others and not writable.
+	 * Avoid migrating a page that is shared with others.
 	 */
-	if ((flags & MPOL_MF_MOVE_ALL) || !page->mapping || PageAnon(page) ||
-	    mapping_writably_mapped(page->mapping) ||
-	    single_mm_mapping(vma->vm_mm, page->mapping)) {
-		int rc = isolate_lru_page(page);
-
-		if (rc == 1)
+	if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) {
+		if (isolate_lru_page(page))
 			list_add(&page->lru, pagelist);
-		/*
-		 * If the isolate attempt was not successful then we just
-		 * encountered an unswappable page. Something must be wrong.
-	 	 */
-		WARN_ON(rc == 0);
 	}
 }
 
-static int swap_pages(struct list_head *pagelist)
+/*
+ * Migrate the list 'pagelist' of pages to a certain destination.
+ *
+ * Specify destination with either non-NULL vma or dest_node >= 0
+ * Return the number of pages not migrated or error code
+ */
+static int migrate_pages_to(struct list_head *pagelist,
+			struct vm_area_struct *vma, int dest)
 {
+	LIST_HEAD(newlist);
 	LIST_HEAD(moved);
 	LIST_HEAD(failed);
-	int n;
+	int err = 0;
+	int nr_pages;
+	struct page *page;
+	struct list_head *p;
 
-	n = migrate_pages(pagelist, NULL, &moved, &failed);
-	putback_lru_pages(&failed);
-	putback_lru_pages(&moved);
+redo:
+	nr_pages = 0;
+	list_for_each(p, pagelist) {
+		if (vma)
+			page = alloc_page_vma(GFP_HIGHUSER, vma, vma->vm_start);
+		else
+			page = alloc_pages_node(dest, GFP_HIGHUSER, 0);
 
-	return n;
+		if (!page) {
+			err = -ENOMEM;
+			goto out;
+		}
+		list_add(&page->lru, &newlist);
+		nr_pages++;
+		if (nr_pages > MIGRATE_CHUNK_SIZE);
+			break;
+	}
+	err = migrate_pages(pagelist, &newlist, &moved, &failed);
+
+	putback_lru_pages(&moved);	/* Call release pages instead ?? */
+
+	if (err >= 0 && list_empty(&newlist) && !list_empty(pagelist))
+		goto redo;
+out:
+	/* Return leftover allocated pages */
+	while (!list_empty(&newlist)) {
+		page = list_entry(newlist.next, struct page, lru);
+		list_del(&page->lru);
+		__free_page(page);
+	}
+	list_splice(&failed, pagelist);
+	if (err < 0)
+		return err;
+
+	/* Calculate number of leftover pages */
+	nr_pages = 0;
+	list_for_each(p, pagelist)
+		nr_pages++;
+	return nr_pages;
 }
 
 /*
- * For now migrate_pages simply swaps out the pages from nodes that are in
- * the source set but not in the target set. In the future, we would
- * want a function that moves pages between the two nodesets in such
- * a way as to preserve the physical layout as much as possible.
+ * Migrate pages from one node to a target node.
+ * Returns error or the number of pages not migrated.
+ */
+int migrate_to_node(struct mm_struct *mm, int source, int dest, int flags)
+{
+	nodemask_t nmask;
+	LIST_HEAD(pagelist);
+	int err = 0;
+
+	nodes_clear(nmask);
+	node_set(source, nmask);
+
+	check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nmask,
+			flags | MPOL_MF_DISCONTIG_OK, &pagelist);
+
+	if (!list_empty(&pagelist)) {
+		err = migrate_pages_to(&pagelist, NULL, dest);
+		if (!list_empty(&pagelist))
+			putback_lru_pages(&pagelist);
+	}
+	return err;
+}
+
+/*
+ * Move pages between the two nodesets so as to preserve the physical
+ * layout as much as possible.
  *
  * Returns the number of page that could not be moved.
  */
@@ -592,22 +638,76 @@
 	const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags)
 {
 	LIST_HEAD(pagelist);
-	int count = 0;
-	nodemask_t nodes;
+	int busy = 0;
+	int err = 0;
+	nodemask_t tmp;
 
-	nodes_andnot(nodes, *from_nodes, *to_nodes);
+  	down_read(&mm->mmap_sem);
 
-	down_read(&mm->mmap_sem);
-	check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nodes,
-			flags | MPOL_MF_DISCONTIG_OK, &pagelist);
+/*
+ * Find a 'source' bit set in 'tmp' whose corresponding 'dest'
+ * bit in 'to' is not also set in 'tmp'.  Clear the found 'source'
+ * bit in 'tmp', and return that <source, dest> pair for migration.
+ * The pair of nodemasks 'to' and 'from' define the map.
+ *
+ * If no pair of bits is found that way, fallback to picking some
+ * pair of 'source' and 'dest' bits that are not the same.  If the
+ * 'source' and 'dest' bits are the same, this represents a node
+ * that will be migrating to itself, so no pages need move.
+ *
+ * If no bits are left in 'tmp', or if all remaining bits left
+ * in 'tmp' correspond to the same bit in 'to', return false
+ * (nothing left to migrate).
+ *
+ * This lets us pick a pair of nodes to migrate between, such that
+ * if possible the dest node is not already occupied by some other
+ * source node, minimizing the risk of overloading the memory on a
+ * node that would happen if we migrated incoming memory to a node
+ * before migrating outgoing memory source that same node.
+ *
+ * A single scan of tmp is sufficient.  As we go, we remember the
+ * most recent <s, d> pair that moved (s != d).  If we find a pair
+ * that not only moved, but what's better, moved to an empty slot
+ * (d is not set in tmp), then we break out then, with that pair.
+ * Otherwise when we finish scannng from_tmp, we at least have the
+ * most recent <s, d> pair that moved.  If we get all the way through
+ * the scan of tmp without finding any node that moved, much less
+ * moved to an empty node, then there is nothing left worth migrating.
+ */
 
-	if (!list_empty(&pagelist)) {
-		count = swap_pages(&pagelist);
-		putback_lru_pages(&pagelist);
+	tmp = *from_nodes;
+	while (!nodes_empty(tmp)) {
+		int s,d;
+		int source = -1;
+		int dest = 0;
+
+		for_each_node_mask(s, tmp) {
+			d = node_remap(s, *from_nodes, *to_nodes);
+			if (s == d)
+				continue;
+
+			source = s;	/* Node moved. Memorize */
+			dest = d;
+
+			/* dest not in remaining from nodes? */
+			if (!node_isset(dest, tmp))
+				break;
+		}
+		if (source == -1)
+			break;
+
+		node_clear(source, tmp);
+		err = migrate_to_node(mm, source, dest, flags);
+		if (err > 0)
+			busy += err;
+		if (err < 0)
+			break;
 	}
 
 	up_read(&mm->mmap_sem);
-	return count;
+	if (err < 0)
+		return err;
+	return busy;
 }
 
 long do_mbind(unsigned long start, unsigned long len,
@@ -667,8 +767,9 @@
 		int nr_failed = 0;
 
 		err = mbind_range(vma, start, end, new);
+
 		if (!list_empty(&pagelist))
-			nr_failed = swap_pages(&pagelist);
+			nr_failed = migrate_pages_to(&pagelist, vma, -1);
 
 		if (!err && nr_failed && (flags & MPOL_MF_STRICT))
 			err = -EIO;
@@ -1000,6 +1101,33 @@
 	return nid;
 }
 
+/*
+ * Depending on the memory policy provide a node from which to allocate the
+ * next slab entry.
+ */
+unsigned slab_node(struct mempolicy *policy)
+{
+	switch (policy->policy) {
+	case MPOL_INTERLEAVE:
+		return interleave_nodes(policy);
+
+	case MPOL_BIND:
+		/*
+		 * Follow bind policy behavior and start allocation at the
+		 * first node.
+		 */
+		return policy->v.zonelist->zones[0]->zone_pgdat->node_id;
+
+	case MPOL_PREFERRED:
+		if (policy->v.preferred_node >= 0)
+			return policy->v.preferred_node;
+		/* Fall through */
+
+	default:
+		return numa_node_id();
+	}
+}
+
 /* Do static interleaving for a VMA with known offset. */
 static unsigned offset_il_node(struct mempolicy *pol,
 		struct vm_area_struct *vma, unsigned long off)
@@ -1031,6 +1159,7 @@
 		return interleave_nodes(pol);
 }
 
+#ifdef CONFIG_HUGETLBFS
 /* Return a zonelist suitable for a huge page allocation. */
 struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr)
 {
@@ -1044,6 +1173,7 @@
 	}
 	return zonelist_policy(GFP_HIGHUSER, pol);
 }
+#endif
 
 /* Allocate a page in interleaved policy.
    Own path because it needs to do special accounting. */
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 14bd4ec..b05ab8f 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -271,6 +271,7 @@
 	if (printk_ratelimit()) {
 		printk("oom-killer: gfp_mask=0x%x, order=%d\n",
 			gfp_mask, order);
+		dump_stack();
 		show_mem();
 	}
 
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 5240e42..945559f 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -46,7 +46,7 @@
 static long ratelimit_pages = 32;
 
 static long total_pages;	/* The total number of pages in the machine. */
-static int dirty_exceeded;	/* Dirty mem may be over limit */
+static int dirty_exceeded __cacheline_aligned_in_smp;	/* Dirty mem may be over limit */
 
 /*
  * When balance_dirty_pages decides that the caller needs to perform some
@@ -212,7 +212,8 @@
 		if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh)
 			break;
 
-		dirty_exceeded = 1;
+		if (!dirty_exceeded)
+			dirty_exceeded = 1;
 
 		/* Note: nr_reclaimable denotes nr_dirty + nr_unstable.
 		 * Unstable writes are a feature of certain networked
@@ -234,7 +235,7 @@
 		blk_congestion_wait(WRITE, HZ/10);
 	}
 
-	if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh)
+	if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh && dirty_exceeded)
 		dirty_exceeded = 0;
 
 	if (writeback_in_progress(bdi))
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c2e2974..dde04ff 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -878,7 +878,9 @@
 				mark = (*z)->pages_high;
 			if (!zone_watermark_ok(*z, order, mark,
 				    classzone_idx, alloc_flags))
-				continue;
+				if (!zone_reclaim_mode ||
+				    !zone_reclaim(*z, gfp_mask, order))
+					continue;
 		}
 
 		page = buffered_rmqueue(zonelist, *z, order, gfp_mask);
@@ -1211,18 +1213,21 @@
 {
 	int cpu = 0;
 
-	memset(ret, 0, sizeof(*ret));
+	memset(ret, 0, nr * sizeof(unsigned long));
 	cpus_and(*cpumask, *cpumask, cpu_online_map);
 
 	cpu = first_cpu(*cpumask);
 	while (cpu < NR_CPUS) {
 		unsigned long *in, *out, off;
 
+		if (!cpu_isset(cpu, *cpumask))
+			continue;
+
 		in = (unsigned long *)&per_cpu(page_states, cpu);
 
 		cpu = next_cpu(cpu, *cpumask);
 
-		if (cpu < NR_CPUS)
+		if (likely(cpu < NR_CPUS))
 			prefetch(&per_cpu(page_states, cpu));
 
 		out = (unsigned long *)ret;
@@ -1595,13 +1600,22 @@
 	prev_node = local_node;
 	nodes_clear(used_mask);
 	while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
+		int distance = node_distance(local_node, node);
+
+		/*
+		 * If another node is sufficiently far away then it is better
+		 * to reclaim pages in a zone before going off node.
+		 */
+		if (distance > RECLAIM_DISTANCE)
+			zone_reclaim_mode = 1;
+
 		/*
 		 * We don't want to pressure a particular node.
 		 * So adding penalty to the first node in same
 		 * distance group to make it round-robin.
 		 */
-		if (node_distance(local_node, node) !=
-				node_distance(local_node, prev_node))
+
+		if (distance != node_distance(local_node, prev_node))
 			node_load[node] += load;
 		prev_node = node;
 		load--;
@@ -1788,7 +1802,7 @@
 	memmap_init_zone((size), (nid), (zone), (start_pfn))
 #endif
 
-static int __meminit zone_batchsize(struct zone *zone)
+static int __cpuinit zone_batchsize(struct zone *zone)
 {
 	int batch;
 
@@ -1875,14 +1889,13 @@
  * not check if the processor is online before following the pageset pointer.
  * Other parts of the kernel may not check if the zone is available.
  */
-static struct per_cpu_pageset
-	boot_pageset[NR_CPUS];
+static struct per_cpu_pageset boot_pageset[NR_CPUS];
 
 /*
  * Dynamically allocate memory for the
  * per cpu pageset array in struct zone.
  */
-static int __meminit process_zones(int cpu)
+static int __cpuinit process_zones(int cpu)
 {
 	struct zone *zone, *dzone;
 
@@ -1923,7 +1936,7 @@
 	}
 }
 
-static int __meminit pageset_cpuup_callback(struct notifier_block *nfb,
+static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb,
 		unsigned long action,
 		void *hcpu)
 {
diff --git a/mm/rmap.c b/mm/rmap.c
index dfbb89f..df2c41c 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -33,7 +33,7 @@
  *     mapping->i_mmap_lock
  *       anon_vma->lock
  *         mm->page_table_lock or pte_lock
- *           zone->lru_lock (in mark_page_accessed)
+ *           zone->lru_lock (in mark_page_accessed, isolate_lru_page)
  *           swap_lock (in swap_duplicate, swap_info_get)
  *             mmlist_lock (in mmput, drain_mmlist and others)
  *             mapping->private_lock (in __set_page_dirty_buffers)
@@ -52,6 +52,7 @@
 #include <linux/init.h>
 #include <linux/rmap.h>
 #include <linux/rcupdate.h>
+#include <linux/module.h>
 
 #include <asm/tlbflush.h>
 
@@ -205,6 +206,36 @@
 	return anon_vma;
 }
 
+#ifdef CONFIG_MIGRATION
+/*
+ * Remove an anonymous page from swap replacing the swap pte's
+ * through real pte's pointing to valid pages and then releasing
+ * the page from the swap cache.
+ *
+ * Must hold page lock on page.
+ */
+void remove_from_swap(struct page *page)
+{
+	struct anon_vma *anon_vma;
+	struct vm_area_struct *vma;
+
+	if (!PageAnon(page) || !PageSwapCache(page))
+		return;
+
+	anon_vma = page_lock_anon_vma(page);
+	if (!anon_vma)
+		return;
+
+	list_for_each_entry(vma, &anon_vma->head, anon_vma_node)
+		remove_vma_swap(vma, page);
+
+	spin_unlock(&anon_vma->lock);
+
+	delete_from_swap_cache(page);
+}
+EXPORT_SYMBOL(remove_from_swap);
+#endif
+
 /*
  * At what user virtual address is page expected in vma?
  */
@@ -541,7 +572,8 @@
  * Subfunctions of try_to_unmap: try_to_unmap_one called
  * repeatedly from either try_to_unmap_anon or try_to_unmap_file.
  */
-static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
+static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
+				int ignore_refs)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long address;
@@ -564,7 +596,8 @@
 	 * skipped over this mm) then we should reactivate it.
 	 */
 	if ((vma->vm_flags & VM_LOCKED) ||
-			ptep_clear_flush_young(vma, address, pte)) {
+			(ptep_clear_flush_young(vma, address, pte)
+				&& !ignore_refs)) {
 		ret = SWAP_FAIL;
 		goto out_unmap;
 	}
@@ -698,7 +731,7 @@
 	pte_unmap_unlock(pte - 1, ptl);
 }
 
-static int try_to_unmap_anon(struct page *page)
+static int try_to_unmap_anon(struct page *page, int ignore_refs)
 {
 	struct anon_vma *anon_vma;
 	struct vm_area_struct *vma;
@@ -709,7 +742,7 @@
 		return ret;
 
 	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
-		ret = try_to_unmap_one(page, vma);
+		ret = try_to_unmap_one(page, vma, ignore_refs);
 		if (ret == SWAP_FAIL || !page_mapped(page))
 			break;
 	}
@@ -726,7 +759,7 @@
  *
  * This function is only called from try_to_unmap for object-based pages.
  */
-static int try_to_unmap_file(struct page *page)
+static int try_to_unmap_file(struct page *page, int ignore_refs)
 {
 	struct address_space *mapping = page->mapping;
 	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
@@ -740,7 +773,7 @@
 
 	spin_lock(&mapping->i_mmap_lock);
 	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
-		ret = try_to_unmap_one(page, vma);
+		ret = try_to_unmap_one(page, vma, ignore_refs);
 		if (ret == SWAP_FAIL || !page_mapped(page))
 			goto out;
 	}
@@ -825,16 +858,16 @@
  * SWAP_AGAIN	- we missed a mapping, try again later
  * SWAP_FAIL	- the page is unswappable
  */
-int try_to_unmap(struct page *page)
+int try_to_unmap(struct page *page, int ignore_refs)
 {
 	int ret;
 
 	BUG_ON(!PageLocked(page));
 
 	if (PageAnon(page))
-		ret = try_to_unmap_anon(page);
+		ret = try_to_unmap_anon(page, ignore_refs);
 	else
-		ret = try_to_unmap_file(page);
+		ret = try_to_unmap_file(page, ignore_refs);
 
 	if (!page_mapped(page))
 		ret = SWAP_SUCCESS;
diff --git a/mm/shmem.c b/mm/shmem.c
index ce501bc..f7ac7b8 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1028,6 +1028,14 @@
 			page_cache_release(swappage);
 			goto repeat;
 		}
+		if (!PageSwapCache(swappage)) {
+			/* Page migration has occured */
+			shmem_swp_unmap(entry);
+			spin_unlock(&info->lock);
+			unlock_page(swappage);
+			page_cache_release(swappage);
+			goto repeat;
+		}
 		if (PageWriteback(swappage)) {
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
diff --git a/mm/slab.c b/mm/slab.c
index 9374293..add05d8 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -55,7 +55,7 @@
  *
  * SMP synchronization:
  *  constructors and destructors are called without any locking.
- *  Several members in kmem_cache_t and struct slab never change, they
+ *  Several members in struct kmem_cache and struct slab never change, they
  *	are accessed without any locking.
  *  The per-cpu arrays are never accessed from the wrong cpu, no locking,
  *  	and local interrupts are disabled so slab code is preempt-safe.
@@ -68,7 +68,7 @@
  * Further notes from the original documentation:
  *
  * 11 April '97.  Started multi-threading - markhe
- *	The global cache-chain is protected by the semaphore 'cache_chain_sem'.
+ *	The global cache-chain is protected by the mutex 'cache_chain_mutex'.
  *	The sem is only needed when accessing/extending the cache-chain, which
  *	can never happen inside an interrupt (kmem_cache_create(),
  *	kmem_cache_shrink() and kmem_cache_reap()).
@@ -103,6 +103,8 @@
 #include	<linux/rcupdate.h>
 #include	<linux/string.h>
 #include	<linux/nodemask.h>
+#include	<linux/mempolicy.h>
+#include	<linux/mutex.h>
 
 #include	<asm/uaccess.h>
 #include	<asm/cacheflush.h>
@@ -242,7 +244,7 @@
  */
 struct slab_rcu {
 	struct rcu_head head;
-	kmem_cache_t *cachep;
+	struct kmem_cache *cachep;
 	void *addr;
 };
 
@@ -292,6 +294,7 @@
 	unsigned long next_reap;
 	int free_touched;
 	unsigned int free_limit;
+	unsigned int colour_next;	/* Per-node cache coloring */
 	spinlock_t list_lock;
 	struct array_cache *shared;	/* shared per node */
 	struct array_cache **alien;	/* on other nodes */
@@ -314,6 +317,8 @@
  */
 static __always_inline int index_of(const size_t size)
 {
+	extern void __bad_size(void);
+
 	if (__builtin_constant_p(size)) {
 		int i = 0;
 
@@ -324,25 +329,23 @@
 		i++;
 #include "linux/kmalloc_sizes.h"
 #undef CACHE
-		{
-			extern void __bad_size(void);
-			__bad_size();
-		}
+		__bad_size();
 	} else
-		BUG();
+		__bad_size();
 	return 0;
 }
 
 #define INDEX_AC index_of(sizeof(struct arraycache_init))
 #define INDEX_L3 index_of(sizeof(struct kmem_list3))
 
-static inline void kmem_list3_init(struct kmem_list3 *parent)
+static void kmem_list3_init(struct kmem_list3 *parent)
 {
 	INIT_LIST_HEAD(&parent->slabs_full);
 	INIT_LIST_HEAD(&parent->slabs_partial);
 	INIT_LIST_HEAD(&parent->slabs_free);
 	parent->shared = NULL;
 	parent->alien = NULL;
+	parent->colour_next = 0;
 	spin_lock_init(&parent->list_lock);
 	parent->free_objects = 0;
 	parent->free_touched = 0;
@@ -362,7 +365,7 @@
 	} while (0)
 
 /*
- * kmem_cache_t
+ * struct kmem_cache
  *
  * manages a cache.
  */
@@ -373,7 +376,7 @@
 	unsigned int batchcount;
 	unsigned int limit;
 	unsigned int shared;
-	unsigned int objsize;
+	unsigned int buffer_size;
 /* 2) touched by every alloc & free from the backend */
 	struct kmem_list3 *nodelists[MAX_NUMNODES];
 	unsigned int flags;	/* constant flags */
@@ -389,16 +392,15 @@
 
 	size_t colour;		/* cache colouring range */
 	unsigned int colour_off;	/* colour offset */
-	unsigned int colour_next;	/* cache colouring */
-	kmem_cache_t *slabp_cache;
+	struct kmem_cache *slabp_cache;
 	unsigned int slab_size;
 	unsigned int dflags;	/* dynamic flags */
 
 	/* constructor func */
-	void (*ctor) (void *, kmem_cache_t *, unsigned long);
+	void (*ctor) (void *, struct kmem_cache *, unsigned long);
 
 	/* de-constructor func */
-	void (*dtor) (void *, kmem_cache_t *, unsigned long);
+	void (*dtor) (void *, struct kmem_cache *, unsigned long);
 
 /* 4) cache creation/removal */
 	const char *name;
@@ -421,8 +423,14 @@
 	atomic_t freemiss;
 #endif
 #if DEBUG
-	int dbghead;
-	int reallen;
+	/*
+	 * If debugging is enabled, then the allocator can add additional
+	 * fields and/or padding to every object. buffer_size contains the total
+	 * object size including these internal fields, the following two
+	 * variables contain the offset to the user object and its size.
+	 */
+	int obj_offset;
+	int obj_size;
 #endif
 };
 
@@ -493,50 +501,50 @@
 
 /* memory layout of objects:
  * 0		: objp
- * 0 .. cachep->dbghead - BYTES_PER_WORD - 1: padding. This ensures that
+ * 0 .. cachep->obj_offset - BYTES_PER_WORD - 1: padding. This ensures that
  * 		the end of an object is aligned with the end of the real
  * 		allocation. Catches writes behind the end of the allocation.
- * cachep->dbghead - BYTES_PER_WORD .. cachep->dbghead - 1:
+ * cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1:
  * 		redzone word.
- * cachep->dbghead: The real object.
- * cachep->objsize - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long]
- * cachep->objsize - 1* BYTES_PER_WORD: last caller address [BYTES_PER_WORD long]
+ * cachep->obj_offset: The real object.
+ * cachep->buffer_size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long]
+ * cachep->buffer_size - 1* BYTES_PER_WORD: last caller address [BYTES_PER_WORD long]
  */
-static int obj_dbghead(kmem_cache_t *cachep)
+static int obj_offset(struct kmem_cache *cachep)
 {
-	return cachep->dbghead;
+	return cachep->obj_offset;
 }
 
-static int obj_reallen(kmem_cache_t *cachep)
+static int obj_size(struct kmem_cache *cachep)
 {
-	return cachep->reallen;
+	return cachep->obj_size;
 }
 
-static unsigned long *dbg_redzone1(kmem_cache_t *cachep, void *objp)
+static unsigned long *dbg_redzone1(struct kmem_cache *cachep, void *objp)
 {
 	BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
-	return (unsigned long*) (objp+obj_dbghead(cachep)-BYTES_PER_WORD);
+	return (unsigned long*) (objp+obj_offset(cachep)-BYTES_PER_WORD);
 }
 
-static unsigned long *dbg_redzone2(kmem_cache_t *cachep, void *objp)
+static unsigned long *dbg_redzone2(struct kmem_cache *cachep, void *objp)
 {
 	BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
 	if (cachep->flags & SLAB_STORE_USER)
-		return (unsigned long *)(objp + cachep->objsize -
+		return (unsigned long *)(objp + cachep->buffer_size -
 					 2 * BYTES_PER_WORD);
-	return (unsigned long *)(objp + cachep->objsize - BYTES_PER_WORD);
+	return (unsigned long *)(objp + cachep->buffer_size - BYTES_PER_WORD);
 }
 
-static void **dbg_userword(kmem_cache_t *cachep, void *objp)
+static void **dbg_userword(struct kmem_cache *cachep, void *objp)
 {
 	BUG_ON(!(cachep->flags & SLAB_STORE_USER));
-	return (void **)(objp + cachep->objsize - BYTES_PER_WORD);
+	return (void **)(objp + cachep->buffer_size - BYTES_PER_WORD);
 }
 
 #else
 
-#define obj_dbghead(x)			0
-#define obj_reallen(cachep)		(cachep->objsize)
+#define obj_offset(x)			0
+#define obj_size(cachep)		(cachep->buffer_size)
 #define dbg_redzone1(cachep, objp)	({BUG(); (unsigned long *)NULL;})
 #define dbg_redzone2(cachep, objp)	({BUG(); (unsigned long *)NULL;})
 #define dbg_userword(cachep, objp)	({BUG(); (void **)NULL;})
@@ -589,6 +597,18 @@
 	return (struct slab *)page->lru.prev;
 }
 
+static inline struct kmem_cache *virt_to_cache(const void *obj)
+{
+	struct page *page = virt_to_page(obj);
+	return page_get_cache(page);
+}
+
+static inline struct slab *virt_to_slab(const void *obj)
+{
+	struct page *page = virt_to_page(obj);
+	return page_get_slab(page);
+}
+
 /* These are the default caches for kmalloc. Custom caches can have other sizes. */
 struct cache_sizes malloc_sizes[] = {
 #define CACHE(x) { .cs_size = (x) },
@@ -617,21 +637,21 @@
     { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
 
 /* internal cache of cache description objs */
-static kmem_cache_t cache_cache = {
+static struct kmem_cache cache_cache = {
 	.batchcount = 1,
 	.limit = BOOT_CPUCACHE_ENTRIES,
 	.shared = 1,
-	.objsize = sizeof(kmem_cache_t),
+	.buffer_size = sizeof(struct kmem_cache),
 	.flags = SLAB_NO_REAP,
 	.spinlock = SPIN_LOCK_UNLOCKED,
 	.name = "kmem_cache",
 #if DEBUG
-	.reallen = sizeof(kmem_cache_t),
+	.obj_size = sizeof(struct kmem_cache),
 #endif
 };
 
 /* Guard access to the cache-chain. */
-static struct semaphore cache_chain_sem;
+static DEFINE_MUTEX(cache_chain_mutex);
 static struct list_head cache_chain;
 
 /*
@@ -655,17 +675,17 @@
 
 static DEFINE_PER_CPU(struct work_struct, reap_work);
 
-static void free_block(kmem_cache_t *cachep, void **objpp, int len, int node);
-static void enable_cpucache(kmem_cache_t *cachep);
+static void free_block(struct kmem_cache *cachep, void **objpp, int len, int node);
+static void enable_cpucache(struct kmem_cache *cachep);
 static void cache_reap(void *unused);
-static int __node_shrink(kmem_cache_t *cachep, int node);
+static int __node_shrink(struct kmem_cache *cachep, int node);
 
-static inline struct array_cache *ac_data(kmem_cache_t *cachep)
+static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
 {
 	return cachep->array[smp_processor_id()];
 }
 
-static inline kmem_cache_t *__find_general_cachep(size_t size, gfp_t gfpflags)
+static inline struct kmem_cache *__find_general_cachep(size_t size, gfp_t gfpflags)
 {
 	struct cache_sizes *csizep = malloc_sizes;
 
@@ -689,43 +709,80 @@
 	return csizep->cs_cachep;
 }
 
-kmem_cache_t *kmem_find_general_cachep(size_t size, gfp_t gfpflags)
+struct kmem_cache *kmem_find_general_cachep(size_t size, gfp_t gfpflags)
 {
 	return __find_general_cachep(size, gfpflags);
 }
 EXPORT_SYMBOL(kmem_find_general_cachep);
 
-/* Cal the num objs, wastage, and bytes left over for a given slab size. */
-static void cache_estimate(unsigned long gfporder, size_t size, size_t align,
-			   int flags, size_t *left_over, unsigned int *num)
+static size_t slab_mgmt_size(size_t nr_objs, size_t align)
 {
-	int i;
-	size_t wastage = PAGE_SIZE << gfporder;
-	size_t extra = 0;
-	size_t base = 0;
+	return ALIGN(sizeof(struct slab)+nr_objs*sizeof(kmem_bufctl_t), align);
+}
 
-	if (!(flags & CFLGS_OFF_SLAB)) {
-		base = sizeof(struct slab);
-		extra = sizeof(kmem_bufctl_t);
+/* Calculate the number of objects and left-over bytes for a given
+   buffer size. */
+static void cache_estimate(unsigned long gfporder, size_t buffer_size,
+			   size_t align, int flags, size_t *left_over,
+			   unsigned int *num)
+{
+	int nr_objs;
+	size_t mgmt_size;
+	size_t slab_size = PAGE_SIZE << gfporder;
+
+	/*
+	 * The slab management structure can be either off the slab or
+	 * on it. For the latter case, the memory allocated for a
+	 * slab is used for:
+	 *
+	 * - The struct slab
+	 * - One kmem_bufctl_t for each object
+	 * - Padding to respect alignment of @align
+	 * - @buffer_size bytes for each object
+	 *
+	 * If the slab management structure is off the slab, then the
+	 * alignment will already be calculated into the size. Because
+	 * the slabs are all pages aligned, the objects will be at the
+	 * correct alignment when allocated.
+	 */
+	if (flags & CFLGS_OFF_SLAB) {
+		mgmt_size = 0;
+		nr_objs = slab_size / buffer_size;
+
+		if (nr_objs > SLAB_LIMIT)
+			nr_objs = SLAB_LIMIT;
+	} else {
+		/*
+		 * Ignore padding for the initial guess. The padding
+		 * is at most @align-1 bytes, and @buffer_size is at
+		 * least @align. In the worst case, this result will
+		 * be one greater than the number of objects that fit
+		 * into the memory allocation when taking the padding
+		 * into account.
+		 */
+		nr_objs = (slab_size - sizeof(struct slab)) /
+			  (buffer_size + sizeof(kmem_bufctl_t));
+
+		/*
+		 * This calculated number will be either the right
+		 * amount, or one greater than what we want.
+		 */
+		if (slab_mgmt_size(nr_objs, align) + nr_objs*buffer_size
+		       > slab_size)
+			nr_objs--;
+
+		if (nr_objs > SLAB_LIMIT)
+			nr_objs = SLAB_LIMIT;
+
+		mgmt_size = slab_mgmt_size(nr_objs, align);
 	}
-	i = 0;
-	while (i * size + ALIGN(base + i * extra, align) <= wastage)
-		i++;
-	if (i > 0)
-		i--;
-
-	if (i > SLAB_LIMIT)
-		i = SLAB_LIMIT;
-
-	*num = i;
-	wastage -= i * size;
-	wastage -= ALIGN(base + i * extra, align);
-	*left_over = wastage;
+	*num = nr_objs;
+	*left_over = slab_size - nr_objs*buffer_size - mgmt_size;
 }
 
 #define slab_error(cachep, msg) __slab_error(__FUNCTION__, cachep, msg)
 
-static void __slab_error(const char *function, kmem_cache_t *cachep, char *msg)
+static void __slab_error(const char *function, struct kmem_cache *cachep, char *msg)
 {
 	printk(KERN_ERR "slab error in %s(): cache `%s': %s\n",
 	       function, cachep->name, msg);
@@ -772,7 +829,9 @@
 }
 
 #ifdef CONFIG_NUMA
-static inline struct array_cache **alloc_alien_cache(int node, int limit)
+static void *__cache_alloc_node(struct kmem_cache *, gfp_t, int);
+
+static struct array_cache **alloc_alien_cache(int node, int limit)
 {
 	struct array_cache **ac_ptr;
 	int memsize = sizeof(void *) * MAX_NUMNODES;
@@ -799,7 +858,7 @@
 	return ac_ptr;
 }
 
-static inline void free_alien_cache(struct array_cache **ac_ptr)
+static void free_alien_cache(struct array_cache **ac_ptr)
 {
 	int i;
 
@@ -812,8 +871,8 @@
 	kfree(ac_ptr);
 }
 
-static inline void __drain_alien_cache(kmem_cache_t *cachep,
-				       struct array_cache *ac, int node)
+static void __drain_alien_cache(struct kmem_cache *cachep,
+				struct array_cache *ac, int node)
 {
 	struct kmem_list3 *rl3 = cachep->nodelists[node];
 
@@ -825,14 +884,14 @@
 	}
 }
 
-static void drain_alien_cache(kmem_cache_t *cachep, struct kmem_list3 *l3)
+static void drain_alien_cache(struct kmem_cache *cachep, struct array_cache **alien)
 {
 	int i = 0;
 	struct array_cache *ac;
 	unsigned long flags;
 
 	for_each_online_node(i) {
-		ac = l3->alien[i];
+		ac = alien[i];
 		if (ac) {
 			spin_lock_irqsave(&ac->lock, flags);
 			__drain_alien_cache(cachep, ac, i);
@@ -841,23 +900,32 @@
 	}
 }
 #else
-#define alloc_alien_cache(node, limit) do { } while (0)
-#define free_alien_cache(ac_ptr) do { } while (0)
-#define drain_alien_cache(cachep, l3) do { } while (0)
+
+#define drain_alien_cache(cachep, alien) do { } while (0)
+
+static inline struct array_cache **alloc_alien_cache(int node, int limit)
+{
+	return (struct array_cache **) 0x01020304ul;
+}
+
+static inline void free_alien_cache(struct array_cache **ac_ptr)
+{
+}
+
 #endif
 
 static int __devinit cpuup_callback(struct notifier_block *nfb,
 				    unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
-	kmem_cache_t *cachep;
+	struct kmem_cache *cachep;
 	struct kmem_list3 *l3 = NULL;
 	int node = cpu_to_node(cpu);
 	int memsize = sizeof(struct kmem_list3);
 
 	switch (action) {
 	case CPU_UP_PREPARE:
-		down(&cache_chain_sem);
+		mutex_lock(&cache_chain_mutex);
 		/* we need to do this right in the beginning since
 		 * alloc_arraycache's are going to use this list.
 		 * kmalloc_node allows us to add the slab to the right
@@ -877,6 +945,11 @@
 				l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
 				    ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
 
+				/*
+				 * The l3s don't come and go as CPUs come and
+				 * go.  cache_chain_mutex is sufficient
+				 * protection here.
+				 */
 				cachep->nodelists[node] = l3;
 			}
 
@@ -891,53 +964,82 @@
 		   & array cache's */
 		list_for_each_entry(cachep, &cache_chain, next) {
 			struct array_cache *nc;
+			struct array_cache *shared;
+			struct array_cache **alien;
 
 			nc = alloc_arraycache(node, cachep->limit,
-					      cachep->batchcount);
+						cachep->batchcount);
 			if (!nc)
 				goto bad;
+			shared = alloc_arraycache(node,
+					cachep->shared * cachep->batchcount,
+					0xbaadf00d);
+			if (!shared)
+				goto bad;
+
+			alien = alloc_alien_cache(node, cachep->limit);
+			if (!alien)
+				goto bad;
 			cachep->array[cpu] = nc;
 
 			l3 = cachep->nodelists[node];
 			BUG_ON(!l3);
-			if (!l3->shared) {
-				if (!(nc = alloc_arraycache(node,
-							    cachep->shared *
-							    cachep->batchcount,
-							    0xbaadf00d)))
-					goto bad;
 
-				/* we are serialised from CPU_DEAD or
-				   CPU_UP_CANCELLED by the cpucontrol lock */
-				l3->shared = nc;
+			spin_lock_irq(&l3->list_lock);
+			if (!l3->shared) {
+				/*
+				 * We are serialised from CPU_DEAD or
+				 * CPU_UP_CANCELLED by the cpucontrol lock
+				 */
+				l3->shared = shared;
+				shared = NULL;
 			}
+#ifdef CONFIG_NUMA
+			if (!l3->alien) {
+				l3->alien = alien;
+				alien = NULL;
+			}
+#endif
+			spin_unlock_irq(&l3->list_lock);
+
+			kfree(shared);
+			free_alien_cache(alien);
 		}
-		up(&cache_chain_sem);
+		mutex_unlock(&cache_chain_mutex);
 		break;
 	case CPU_ONLINE:
 		start_cpu_timer(cpu);
 		break;
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
+		/*
+		 * Even if all the cpus of a node are down, we don't free the
+		 * kmem_list3 of any cache. This to avoid a race between
+		 * cpu_down, and a kmalloc allocation from another cpu for
+		 * memory from the node of the cpu going down.  The list3
+		 * structure is usually allocated from kmem_cache_create() and
+		 * gets destroyed at kmem_cache_destroy().
+		 */
 		/* fall thru */
 	case CPU_UP_CANCELED:
-		down(&cache_chain_sem);
+		mutex_lock(&cache_chain_mutex);
 
 		list_for_each_entry(cachep, &cache_chain, next) {
 			struct array_cache *nc;
+			struct array_cache *shared;
+			struct array_cache **alien;
 			cpumask_t mask;
 
 			mask = node_to_cpumask(node);
-			spin_lock_irq(&cachep->spinlock);
 			/* cpu is dead; no one can alloc from it. */
 			nc = cachep->array[cpu];
 			cachep->array[cpu] = NULL;
 			l3 = cachep->nodelists[node];
 
 			if (!l3)
-				goto unlock_cache;
+				goto free_array_cache;
 
-			spin_lock(&l3->list_lock);
+			spin_lock_irq(&l3->list_lock);
 
 			/* Free limit for this kmem_list3 */
 			l3->free_limit -= cachep->batchcount;
@@ -945,41 +1047,51 @@
 				free_block(cachep, nc->entry, nc->avail, node);
 
 			if (!cpus_empty(mask)) {
-				spin_unlock(&l3->list_lock);
-				goto unlock_cache;
+				spin_unlock_irq(&l3->list_lock);
+				goto free_array_cache;
 			}
 
-			if (l3->shared) {
+			shared = l3->shared;
+			if (shared) {
 				free_block(cachep, l3->shared->entry,
 					   l3->shared->avail, node);
-				kfree(l3->shared);
 				l3->shared = NULL;
 			}
-			if (l3->alien) {
-				drain_alien_cache(cachep, l3);
-				free_alien_cache(l3->alien);
-				l3->alien = NULL;
-			}
 
-			/* free slabs belonging to this node */
-			if (__node_shrink(cachep, node)) {
-				cachep->nodelists[node] = NULL;
-				spin_unlock(&l3->list_lock);
-				kfree(l3);
-			} else {
-				spin_unlock(&l3->list_lock);
+			alien = l3->alien;
+			l3->alien = NULL;
+
+			spin_unlock_irq(&l3->list_lock);
+
+			kfree(shared);
+			if (alien) {
+				drain_alien_cache(cachep, alien);
+				free_alien_cache(alien);
 			}
-		      unlock_cache:
-			spin_unlock_irq(&cachep->spinlock);
+free_array_cache:
 			kfree(nc);
 		}
-		up(&cache_chain_sem);
+		/*
+		 * In the previous loop, all the objects were freed to
+		 * the respective cache's slabs,  now we can go ahead and
+		 * shrink each nodelist to its limit.
+		 */
+		list_for_each_entry(cachep, &cache_chain, next) {
+			l3 = cachep->nodelists[node];
+			if (!l3)
+				continue;
+			spin_lock_irq(&l3->list_lock);
+			/* free slabs belonging to this node */
+			__node_shrink(cachep, node);
+			spin_unlock_irq(&l3->list_lock);
+		}
+		mutex_unlock(&cache_chain_mutex);
 		break;
 #endif
 	}
 	return NOTIFY_OK;
       bad:
-	up(&cache_chain_sem);
+	mutex_unlock(&cache_chain_mutex);
 	return NOTIFY_BAD;
 }
 
@@ -988,7 +1100,7 @@
 /*
  * swap the static kmem_list3 with kmalloced memory
  */
-static void init_list(kmem_cache_t *cachep, struct kmem_list3 *list, int nodeid)
+static void init_list(struct kmem_cache *cachep, struct kmem_list3 *list, int nodeid)
 {
 	struct kmem_list3 *ptr;
 
@@ -1028,14 +1140,14 @@
 
 	/* Bootstrap is tricky, because several objects are allocated
 	 * from caches that do not exist yet:
-	 * 1) initialize the cache_cache cache: it contains the kmem_cache_t
+	 * 1) initialize the cache_cache cache: it contains the struct kmem_cache
 	 *    structures of all caches, except cache_cache itself: cache_cache
 	 *    is statically allocated.
 	 *    Initially an __init data area is used for the head array and the
 	 *    kmem_list3 structures, it's replaced with a kmalloc allocated
 	 *    array at the end of the bootstrap.
 	 * 2) Create the first kmalloc cache.
-	 *    The kmem_cache_t for the new cache is allocated normally.
+	 *    The struct kmem_cache for the new cache is allocated normally.
 	 *    An __init data area is used for the head array.
 	 * 3) Create the remaining kmalloc caches, with minimally sized
 	 *    head arrays.
@@ -1047,22 +1159,20 @@
 	 */
 
 	/* 1) create the cache_cache */
-	init_MUTEX(&cache_chain_sem);
 	INIT_LIST_HEAD(&cache_chain);
 	list_add(&cache_cache.next, &cache_chain);
 	cache_cache.colour_off = cache_line_size();
 	cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
 	cache_cache.nodelists[numa_node_id()] = &initkmem_list3[CACHE_CACHE];
 
-	cache_cache.objsize = ALIGN(cache_cache.objsize, cache_line_size());
+	cache_cache.buffer_size = ALIGN(cache_cache.buffer_size, cache_line_size());
 
-	cache_estimate(0, cache_cache.objsize, cache_line_size(), 0,
+	cache_estimate(0, cache_cache.buffer_size, cache_line_size(), 0,
 		       &left_over, &cache_cache.num);
 	if (!cache_cache.num)
 		BUG();
 
 	cache_cache.colour = left_over / cache_cache.colour_off;
-	cache_cache.colour_next = 0;
 	cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +
 				      sizeof(struct slab), cache_line_size());
 
@@ -1129,8 +1239,8 @@
 		ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
 
 		local_irq_disable();
-		BUG_ON(ac_data(&cache_cache) != &initarray_cache.cache);
-		memcpy(ptr, ac_data(&cache_cache),
+		BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);
+		memcpy(ptr, cpu_cache_get(&cache_cache),
 		       sizeof(struct arraycache_init));
 		cache_cache.array[smp_processor_id()] = ptr;
 		local_irq_enable();
@@ -1138,9 +1248,9 @@
 		ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
 
 		local_irq_disable();
-		BUG_ON(ac_data(malloc_sizes[INDEX_AC].cs_cachep)
+		BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep)
 		       != &initarray_generic.cache);
-		memcpy(ptr, ac_data(malloc_sizes[INDEX_AC].cs_cachep),
+		memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),
 		       sizeof(struct arraycache_init));
 		malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
 		    ptr;
@@ -1167,18 +1277,18 @@
 
 	/* 6) resize the head arrays to their final sizes */
 	{
-		kmem_cache_t *cachep;
-		down(&cache_chain_sem);
+		struct kmem_cache *cachep;
+		mutex_lock(&cache_chain_mutex);
 		list_for_each_entry(cachep, &cache_chain, next)
 		    enable_cpucache(cachep);
-		up(&cache_chain_sem);
+		mutex_unlock(&cache_chain_mutex);
 	}
 
 	/* Done! */
 	g_cpucache_up = FULL;
 
 	/* Register a cpu startup notifier callback
-	 * that initializes ac_data for all new cpus
+	 * that initializes cpu_cache_get for all new cpus
 	 */
 	register_cpu_notifier(&cpucache_notifier);
 
@@ -1210,7 +1320,7 @@
  * did not request dmaable memory, we might get it, but that
  * would be relatively rare and ignorable.
  */
-static void *kmem_getpages(kmem_cache_t *cachep, gfp_t flags, int nodeid)
+static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
 	struct page *page;
 	void *addr;
@@ -1236,7 +1346,7 @@
 /*
  * Interface to system's page release.
  */
-static void kmem_freepages(kmem_cache_t *cachep, void *addr)
+static void kmem_freepages(struct kmem_cache *cachep, void *addr)
 {
 	unsigned long i = (1 << cachep->gfporder);
 	struct page *page = virt_to_page(addr);
@@ -1258,7 +1368,7 @@
 static void kmem_rcu_free(struct rcu_head *head)
 {
 	struct slab_rcu *slab_rcu = (struct slab_rcu *)head;
-	kmem_cache_t *cachep = slab_rcu->cachep;
+	struct kmem_cache *cachep = slab_rcu->cachep;
 
 	kmem_freepages(cachep, slab_rcu->addr);
 	if (OFF_SLAB(cachep))
@@ -1268,12 +1378,12 @@
 #if DEBUG
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
-static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr,
+static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr,
 			    unsigned long caller)
 {
-	int size = obj_reallen(cachep);
+	int size = obj_size(cachep);
 
-	addr = (unsigned long *)&((char *)addr)[obj_dbghead(cachep)];
+	addr = (unsigned long *)&((char *)addr)[obj_offset(cachep)];
 
 	if (size < 5 * sizeof(unsigned long))
 		return;
@@ -1301,10 +1411,10 @@
 }
 #endif
 
-static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val)
+static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val)
 {
-	int size = obj_reallen(cachep);
-	addr = &((char *)addr)[obj_dbghead(cachep)];
+	int size = obj_size(cachep);
+	addr = &((char *)addr)[obj_offset(cachep)];
 
 	memset(addr, val, size);
 	*(unsigned char *)(addr + size - 1) = POISON_END;
@@ -1323,7 +1433,7 @@
 
 #if DEBUG
 
-static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
+static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines)
 {
 	int i, size;
 	char *realobj;
@@ -1341,8 +1451,8 @@
 			     (unsigned long)*dbg_userword(cachep, objp));
 		printk("\n");
 	}
-	realobj = (char *)objp + obj_dbghead(cachep);
-	size = obj_reallen(cachep);
+	realobj = (char *)objp + obj_offset(cachep);
+	size = obj_size(cachep);
 	for (i = 0; i < size && lines; i += 16, lines--) {
 		int limit;
 		limit = 16;
@@ -1352,14 +1462,14 @@
 	}
 }
 
-static void check_poison_obj(kmem_cache_t *cachep, void *objp)
+static void check_poison_obj(struct kmem_cache *cachep, void *objp)
 {
 	char *realobj;
 	int size, i;
 	int lines = 0;
 
-	realobj = (char *)objp + obj_dbghead(cachep);
-	size = obj_reallen(cachep);
+	realobj = (char *)objp + obj_offset(cachep);
+	size = obj_size(cachep);
 
 	for (i = 0; i < size; i++) {
 		char exp = POISON_FREE;
@@ -1392,20 +1502,20 @@
 		/* Print some data about the neighboring objects, if they
 		 * exist:
 		 */
-		struct slab *slabp = page_get_slab(virt_to_page(objp));
+		struct slab *slabp = virt_to_slab(objp);
 		int objnr;
 
-		objnr = (objp - slabp->s_mem) / cachep->objsize;
+		objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size;
 		if (objnr) {
-			objp = slabp->s_mem + (objnr - 1) * cachep->objsize;
-			realobj = (char *)objp + obj_dbghead(cachep);
+			objp = slabp->s_mem + (objnr - 1) * cachep->buffer_size;
+			realobj = (char *)objp + obj_offset(cachep);
 			printk(KERN_ERR "Prev obj: start=%p, len=%d\n",
 			       realobj, size);
 			print_objinfo(cachep, objp, 2);
 		}
 		if (objnr + 1 < cachep->num) {
-			objp = slabp->s_mem + (objnr + 1) * cachep->objsize;
-			realobj = (char *)objp + obj_dbghead(cachep);
+			objp = slabp->s_mem + (objnr + 1) * cachep->buffer_size;
+			realobj = (char *)objp + obj_offset(cachep);
 			printk(KERN_ERR "Next obj: start=%p, len=%d\n",
 			       realobj, size);
 			print_objinfo(cachep, objp, 2);
@@ -1414,25 +1524,23 @@
 }
 #endif
 
-/* Destroy all the objs in a slab, and release the mem back to the system.
- * Before calling the slab must have been unlinked from the cache.
- * The cache-lock is not held/needed.
- */
-static void slab_destroy(kmem_cache_t *cachep, struct slab *slabp)
-{
-	void *addr = slabp->s_mem - slabp->colouroff;
-
 #if DEBUG
+/**
+ * slab_destroy_objs - call the registered destructor for each object in
+ *      a slab that is to be destroyed.
+ */
+static void slab_destroy_objs(struct kmem_cache *cachep, struct slab *slabp)
+{
 	int i;
 	for (i = 0; i < cachep->num; i++) {
-		void *objp = slabp->s_mem + cachep->objsize * i;
+		void *objp = slabp->s_mem + cachep->buffer_size * i;
 
 		if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
-			if ((cachep->objsize % PAGE_SIZE) == 0
+			if ((cachep->buffer_size % PAGE_SIZE) == 0
 			    && OFF_SLAB(cachep))
 				kernel_map_pages(virt_to_page(objp),
-						 cachep->objsize / PAGE_SIZE,
+						 cachep->buffer_size / PAGE_SIZE,
 						 1);
 			else
 				check_poison_obj(cachep, objp);
@@ -1449,18 +1557,32 @@
 					   "was overwritten");
 		}
 		if (cachep->dtor && !(cachep->flags & SLAB_POISON))
-			(cachep->dtor) (objp + obj_dbghead(cachep), cachep, 0);
+			(cachep->dtor) (objp + obj_offset(cachep), cachep, 0);
 	}
+}
 #else
+static void slab_destroy_objs(struct kmem_cache *cachep, struct slab *slabp)
+{
 	if (cachep->dtor) {
 		int i;
 		for (i = 0; i < cachep->num; i++) {
-			void *objp = slabp->s_mem + cachep->objsize * i;
+			void *objp = slabp->s_mem + cachep->buffer_size * i;
 			(cachep->dtor) (objp, cachep, 0);
 		}
 	}
+}
 #endif
 
+/**
+ * Destroy all the objs in a slab, and release the mem back to the system.
+ * Before calling the slab must have been unlinked from the cache.
+ * The cache-lock is not held/needed.
+ */
+static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp)
+{
+	void *addr = slabp->s_mem - slabp->colouroff;
+
+	slab_destroy_objs(cachep, slabp);
 	if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) {
 		struct slab_rcu *slab_rcu;
 
@@ -1475,9 +1597,9 @@
 	}
 }
 
-/* For setting up all the kmem_list3s for cache whose objsize is same
+/* For setting up all the kmem_list3s for cache whose buffer_size is same
    as size of kmem_list3. */
-static inline void set_up_list3s(kmem_cache_t *cachep, int index)
+static void set_up_list3s(struct kmem_cache *cachep, int index)
 {
 	int node;
 
@@ -1490,15 +1612,20 @@
 }
 
 /**
- * calculate_slab_order - calculate size (page order) of slabs and the number
- *                        of objects per slab.
+ * calculate_slab_order - calculate size (page order) of slabs
+ * @cachep: pointer to the cache that is being created
+ * @size: size of objects to be created in this cache.
+ * @align: required alignment for the objects.
+ * @flags: slab allocation flags
+ *
+ * Also calculates the number of objects per slab.
  *
  * This could be made much more intelligent.  For now, try to avoid using
  * high order pages for slabs.  When the gfp() functions are more friendly
  * towards high-order requests, this should be changed.
  */
-static inline size_t calculate_slab_order(kmem_cache_t *cachep, size_t size,
-					  size_t align, gfp_t flags)
+static inline size_t calculate_slab_order(struct kmem_cache *cachep,
+			size_t size, size_t align, unsigned long flags)
 {
 	size_t left_over = 0;
 
@@ -1569,13 +1696,13 @@
  * cacheline.  This can be beneficial if you're counting cycles as closely
  * as davem.
  */
-kmem_cache_t *
+struct kmem_cache *
 kmem_cache_create (const char *name, size_t size, size_t align,
-	unsigned long flags, void (*ctor)(void*, kmem_cache_t *, unsigned long),
-	void (*dtor)(void*, kmem_cache_t *, unsigned long))
+	unsigned long flags, void (*ctor)(void*, struct kmem_cache *, unsigned long),
+	void (*dtor)(void*, struct kmem_cache *, unsigned long))
 {
 	size_t left_over, slab_size, ralign;
-	kmem_cache_t *cachep = NULL;
+	struct kmem_cache *cachep = NULL;
 	struct list_head *p;
 
 	/*
@@ -1590,10 +1717,16 @@
 		BUG();
 	}
 
-	down(&cache_chain_sem);
+	/*
+	 * Prevent CPUs from coming and going.
+	 * lock_cpu_hotplug() nests outside cache_chain_mutex
+	 */
+	lock_cpu_hotplug();
+
+	mutex_lock(&cache_chain_mutex);
 
 	list_for_each(p, &cache_chain) {
-		kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
+		struct kmem_cache *pc = list_entry(p, struct kmem_cache, next);
 		mm_segment_t old_fs = get_fs();
 		char tmp;
 		int res;
@@ -1608,7 +1741,7 @@
 		set_fs(old_fs);
 		if (res) {
 			printk("SLAB: cache with size %d has lost its name\n",
-			       pc->objsize);
+			       pc->buffer_size);
 			continue;
 		}
 
@@ -1693,20 +1826,20 @@
 	align = ralign;
 
 	/* Get cache's description obj. */
-	cachep = (kmem_cache_t *) kmem_cache_alloc(&cache_cache, SLAB_KERNEL);
+	cachep = kmem_cache_alloc(&cache_cache, SLAB_KERNEL);
 	if (!cachep)
 		goto oops;
-	memset(cachep, 0, sizeof(kmem_cache_t));
+	memset(cachep, 0, sizeof(struct kmem_cache));
 
 #if DEBUG
-	cachep->reallen = size;
+	cachep->obj_size = size;
 
 	if (flags & SLAB_RED_ZONE) {
 		/* redzoning only works with word aligned caches */
 		align = BYTES_PER_WORD;
 
 		/* add space for red zone words */
-		cachep->dbghead += BYTES_PER_WORD;
+		cachep->obj_offset += BYTES_PER_WORD;
 		size += 2 * BYTES_PER_WORD;
 	}
 	if (flags & SLAB_STORE_USER) {
@@ -1719,8 +1852,8 @@
 	}
 #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
 	if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
-	    && cachep->reallen > cache_line_size() && size < PAGE_SIZE) {
-		cachep->dbghead += PAGE_SIZE - size;
+	    && cachep->obj_size > cache_line_size() && size < PAGE_SIZE) {
+		cachep->obj_offset += PAGE_SIZE - size;
 		size = PAGE_SIZE;
 	}
 #endif
@@ -1783,7 +1916,7 @@
 	if (flags & SLAB_CACHE_DMA)
 		cachep->gfpflags |= GFP_DMA;
 	spin_lock_init(&cachep->spinlock);
-	cachep->objsize = size;
+	cachep->buffer_size = size;
 
 	if (flags & CFLGS_OFF_SLAB)
 		cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
@@ -1791,8 +1924,6 @@
 	cachep->dtor = dtor;
 	cachep->name = name;
 
-	/* Don't let CPUs to come and go */
-	lock_cpu_hotplug();
 
 	if (g_cpucache_up == FULL) {
 		enable_cpucache(cachep);
@@ -1840,23 +1971,23 @@
 		    jiffies + REAPTIMEOUT_LIST3 +
 		    ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
 
-		BUG_ON(!ac_data(cachep));
-		ac_data(cachep)->avail = 0;
-		ac_data(cachep)->limit = BOOT_CPUCACHE_ENTRIES;
-		ac_data(cachep)->batchcount = 1;
-		ac_data(cachep)->touched = 0;
+		BUG_ON(!cpu_cache_get(cachep));
+		cpu_cache_get(cachep)->avail = 0;
+		cpu_cache_get(cachep)->limit = BOOT_CPUCACHE_ENTRIES;
+		cpu_cache_get(cachep)->batchcount = 1;
+		cpu_cache_get(cachep)->touched = 0;
 		cachep->batchcount = 1;
 		cachep->limit = BOOT_CPUCACHE_ENTRIES;
 	}
 
 	/* cache setup completed, link it into the list */
 	list_add(&cachep->next, &cache_chain);
-	unlock_cpu_hotplug();
       oops:
 	if (!cachep && (flags & SLAB_PANIC))
 		panic("kmem_cache_create(): failed to create slab `%s'\n",
 		      name);
-	up(&cache_chain_sem);
+	mutex_unlock(&cache_chain_mutex);
+	unlock_cpu_hotplug();
 	return cachep;
 }
 EXPORT_SYMBOL(kmem_cache_create);
@@ -1872,7 +2003,7 @@
 	BUG_ON(irqs_disabled());
 }
 
-static void check_spinlock_acquired(kmem_cache_t *cachep)
+static void check_spinlock_acquired(struct kmem_cache *cachep)
 {
 #ifdef CONFIG_SMP
 	check_irq_off();
@@ -1880,7 +2011,7 @@
 #endif
 }
 
-static inline void check_spinlock_acquired_node(kmem_cache_t *cachep, int node)
+static void check_spinlock_acquired_node(struct kmem_cache *cachep, int node)
 {
 #ifdef CONFIG_SMP
 	check_irq_off();
@@ -1913,45 +2044,43 @@
 	preempt_enable();
 }
 
-static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac,
+static void drain_array_locked(struct kmem_cache *cachep, struct array_cache *ac,
 				int force, int node);
 
 static void do_drain(void *arg)
 {
-	kmem_cache_t *cachep = (kmem_cache_t *) arg;
+	struct kmem_cache *cachep = (struct kmem_cache *) arg;
 	struct array_cache *ac;
 	int node = numa_node_id();
 
 	check_irq_off();
-	ac = ac_data(cachep);
+	ac = cpu_cache_get(cachep);
 	spin_lock(&cachep->nodelists[node]->list_lock);
 	free_block(cachep, ac->entry, ac->avail, node);
 	spin_unlock(&cachep->nodelists[node]->list_lock);
 	ac->avail = 0;
 }
 
-static void drain_cpu_caches(kmem_cache_t *cachep)
+static void drain_cpu_caches(struct kmem_cache *cachep)
 {
 	struct kmem_list3 *l3;
 	int node;
 
 	smp_call_function_all_cpus(do_drain, cachep);
 	check_irq_on();
-	spin_lock_irq(&cachep->spinlock);
 	for_each_online_node(node) {
 		l3 = cachep->nodelists[node];
 		if (l3) {
-			spin_lock(&l3->list_lock);
+			spin_lock_irq(&l3->list_lock);
 			drain_array_locked(cachep, l3->shared, 1, node);
-			spin_unlock(&l3->list_lock);
+			spin_unlock_irq(&l3->list_lock);
 			if (l3->alien)
-				drain_alien_cache(cachep, l3);
+				drain_alien_cache(cachep, l3->alien);
 		}
 	}
-	spin_unlock_irq(&cachep->spinlock);
 }
 
-static int __node_shrink(kmem_cache_t *cachep, int node)
+static int __node_shrink(struct kmem_cache *cachep, int node)
 {
 	struct slab *slabp;
 	struct kmem_list3 *l3 = cachep->nodelists[node];
@@ -1980,7 +2109,7 @@
 	return ret;
 }
 
-static int __cache_shrink(kmem_cache_t *cachep)
+static int __cache_shrink(struct kmem_cache *cachep)
 {
 	int ret = 0, i = 0;
 	struct kmem_list3 *l3;
@@ -2006,7 +2135,7 @@
  * Releases as many slabs as possible for a cache.
  * To help debugging, a zero exit status indicates all slabs were released.
  */
-int kmem_cache_shrink(kmem_cache_t *cachep)
+int kmem_cache_shrink(struct kmem_cache *cachep)
 {
 	if (!cachep || in_interrupt())
 		BUG();
@@ -2019,7 +2148,7 @@
  * kmem_cache_destroy - delete a cache
  * @cachep: the cache to destroy
  *
- * Remove a kmem_cache_t object from the slab cache.
+ * Remove a struct kmem_cache object from the slab cache.
  * Returns 0 on success.
  *
  * It is expected this function will be called by a module when it is
@@ -2032,7 +2161,7 @@
  * The caller must guarantee that noone will allocate memory from the cache
  * during the kmem_cache_destroy().
  */
-int kmem_cache_destroy(kmem_cache_t *cachep)
+int kmem_cache_destroy(struct kmem_cache *cachep)
 {
 	int i;
 	struct kmem_list3 *l3;
@@ -2044,18 +2173,18 @@
 	lock_cpu_hotplug();
 
 	/* Find the cache in the chain of caches. */
-	down(&cache_chain_sem);
+	mutex_lock(&cache_chain_mutex);
 	/*
 	 * the chain is never empty, cache_cache is never destroyed
 	 */
 	list_del(&cachep->next);
-	up(&cache_chain_sem);
+	mutex_unlock(&cache_chain_mutex);
 
 	if (__cache_shrink(cachep)) {
 		slab_error(cachep, "Can't free all objects");
-		down(&cache_chain_sem);
+		mutex_lock(&cache_chain_mutex);
 		list_add(&cachep->next, &cache_chain);
-		up(&cache_chain_sem);
+		mutex_unlock(&cache_chain_mutex);
 		unlock_cpu_hotplug();
 		return 1;
 	}
@@ -2083,7 +2212,7 @@
 EXPORT_SYMBOL(kmem_cache_destroy);
 
 /* Get the memory for a slab management obj. */
-static struct slab *alloc_slabmgmt(kmem_cache_t *cachep, void *objp,
+static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
 				   int colour_off, gfp_t local_flags)
 {
 	struct slab *slabp;
@@ -2109,13 +2238,13 @@
 	return (kmem_bufctl_t *) (slabp + 1);
 }
 
-static void cache_init_objs(kmem_cache_t *cachep,
+static void cache_init_objs(struct kmem_cache *cachep,
 			    struct slab *slabp, unsigned long ctor_flags)
 {
 	int i;
 
 	for (i = 0; i < cachep->num; i++) {
-		void *objp = slabp->s_mem + cachep->objsize * i;
+		void *objp = slabp->s_mem + cachep->buffer_size * i;
 #if DEBUG
 		/* need to poison the objs? */
 		if (cachep->flags & SLAB_POISON)
@@ -2133,7 +2262,7 @@
 		 * Otherwise, deadlock. They must also be threaded.
 		 */
 		if (cachep->ctor && !(cachep->flags & SLAB_POISON))
-			cachep->ctor(objp + obj_dbghead(cachep), cachep,
+			cachep->ctor(objp + obj_offset(cachep), cachep,
 				     ctor_flags);
 
 		if (cachep->flags & SLAB_RED_ZONE) {
@@ -2144,10 +2273,10 @@
 				slab_error(cachep, "constructor overwrote the"
 					   " start of an object");
 		}
-		if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)
+		if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)
 		    && cachep->flags & SLAB_POISON)
 			kernel_map_pages(virt_to_page(objp),
-					 cachep->objsize / PAGE_SIZE, 0);
+					 cachep->buffer_size / PAGE_SIZE, 0);
 #else
 		if (cachep->ctor)
 			cachep->ctor(objp, cachep, ctor_flags);
@@ -2158,7 +2287,7 @@
 	slabp->free = 0;
 }
 
-static void kmem_flagcheck(kmem_cache_t *cachep, gfp_t flags)
+static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags)
 {
 	if (flags & SLAB_DMA) {
 		if (!(cachep->gfpflags & GFP_DMA))
@@ -2169,7 +2298,43 @@
 	}
 }
 
-static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp)
+static void *slab_get_obj(struct kmem_cache *cachep, struct slab *slabp, int nodeid)
+{
+	void *objp = slabp->s_mem + (slabp->free * cachep->buffer_size);
+	kmem_bufctl_t next;
+
+	slabp->inuse++;
+	next = slab_bufctl(slabp)[slabp->free];
+#if DEBUG
+	slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
+	WARN_ON(slabp->nodeid != nodeid);
+#endif
+	slabp->free = next;
+
+	return objp;
+}
+
+static void slab_put_obj(struct kmem_cache *cachep, struct slab *slabp, void *objp,
+			  int nodeid)
+{
+	unsigned int objnr = (unsigned)(objp-slabp->s_mem) / cachep->buffer_size;
+
+#if DEBUG
+	/* Verify that the slab belongs to the intended node */
+	WARN_ON(slabp->nodeid != nodeid);
+
+	if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
+		printk(KERN_ERR "slab: double free detected in cache "
+		       "'%s', objp %p\n", cachep->name, objp);
+		BUG();
+	}
+#endif
+	slab_bufctl(slabp)[objnr] = slabp->free;
+	slabp->free = objnr;
+	slabp->inuse--;
+}
+
+static void set_slab_attr(struct kmem_cache *cachep, struct slab *slabp, void *objp)
 {
 	int i;
 	struct page *page;
@@ -2188,7 +2353,7 @@
  * Grow (by 1) the number of slabs within a cache.  This is called by
  * kmem_cache_alloc() when there are no active objs left in a cache.
  */
-static int cache_grow(kmem_cache_t *cachep, gfp_t flags, int nodeid)
+static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
 	struct slab *slabp;
 	void *objp;
@@ -2214,20 +2379,20 @@
 		 */
 		ctor_flags |= SLAB_CTOR_ATOMIC;
 
-	/* About to mess with non-constant members - lock. */
+	/* Take the l3 list lock to change the colour_next on this node */
 	check_irq_off();
-	spin_lock(&cachep->spinlock);
+	l3 = cachep->nodelists[nodeid];
+	spin_lock(&l3->list_lock);
 
 	/* Get colour for the slab, and cal the next value. */
-	offset = cachep->colour_next;
-	cachep->colour_next++;
-	if (cachep->colour_next >= cachep->colour)
-		cachep->colour_next = 0;
+	offset = l3->colour_next;
+	l3->colour_next++;
+	if (l3->colour_next >= cachep->colour)
+		l3->colour_next = 0;
+	spin_unlock(&l3->list_lock);
+
 	offset *= cachep->colour_off;
 
-	spin_unlock(&cachep->spinlock);
-
-	check_irq_off();
 	if (local_flags & __GFP_WAIT)
 		local_irq_enable();
 
@@ -2257,7 +2422,6 @@
 	if (local_flags & __GFP_WAIT)
 		local_irq_disable();
 	check_irq_off();
-	l3 = cachep->nodelists[nodeid];
 	spin_lock(&l3->list_lock);
 
 	/* Make slab active. */
@@ -2299,14 +2463,14 @@
 	}
 }
 
-static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp,
+static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
 				   void *caller)
 {
 	struct page *page;
 	unsigned int objnr;
 	struct slab *slabp;
 
-	objp -= obj_dbghead(cachep);
+	objp -= obj_offset(cachep);
 	kfree_debugcheck(objp);
 	page = virt_to_page(objp);
 
@@ -2338,31 +2502,31 @@
 	if (cachep->flags & SLAB_STORE_USER)
 		*dbg_userword(cachep, objp) = caller;
 
-	objnr = (objp - slabp->s_mem) / cachep->objsize;
+	objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size;
 
 	BUG_ON(objnr >= cachep->num);
-	BUG_ON(objp != slabp->s_mem + objnr * cachep->objsize);
+	BUG_ON(objp != slabp->s_mem + objnr * cachep->buffer_size);
 
 	if (cachep->flags & SLAB_DEBUG_INITIAL) {
 		/* Need to call the slab's constructor so the
 		 * caller can perform a verify of its state (debugging).
 		 * Called without the cache-lock held.
 		 */
-		cachep->ctor(objp + obj_dbghead(cachep),
+		cachep->ctor(objp + obj_offset(cachep),
 			     cachep, SLAB_CTOR_CONSTRUCTOR | SLAB_CTOR_VERIFY);
 	}
 	if (cachep->flags & SLAB_POISON && cachep->dtor) {
 		/* we want to cache poison the object,
 		 * call the destruction callback
 		 */
-		cachep->dtor(objp + obj_dbghead(cachep), cachep, 0);
+		cachep->dtor(objp + obj_offset(cachep), cachep, 0);
 	}
 	if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
-		if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) {
+		if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) {
 			store_stackinfo(cachep, objp, (unsigned long)caller);
 			kernel_map_pages(virt_to_page(objp),
-					 cachep->objsize / PAGE_SIZE, 0);
+					 cachep->buffer_size / PAGE_SIZE, 0);
 		} else {
 			poison_obj(cachep, objp, POISON_FREE);
 		}
@@ -2373,7 +2537,7 @@
 	return objp;
 }
 
-static void check_slabp(kmem_cache_t *cachep, struct slab *slabp)
+static void check_slabp(struct kmem_cache *cachep, struct slab *slabp)
 {
 	kmem_bufctl_t i;
 	int entries = 0;
@@ -2406,14 +2570,14 @@
 #define check_slabp(x,y) do { } while(0)
 #endif
 
-static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags)
+static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
 {
 	int batchcount;
 	struct kmem_list3 *l3;
 	struct array_cache *ac;
 
 	check_irq_off();
-	ac = ac_data(cachep);
+	ac = cpu_cache_get(cachep);
       retry:
 	batchcount = ac->batchcount;
 	if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
@@ -2458,22 +2622,12 @@
 		check_slabp(cachep, slabp);
 		check_spinlock_acquired(cachep);
 		while (slabp->inuse < cachep->num && batchcount--) {
-			kmem_bufctl_t next;
 			STATS_INC_ALLOCED(cachep);
 			STATS_INC_ACTIVE(cachep);
 			STATS_SET_HIGH(cachep);
 
-			/* get obj pointer */
-			ac->entry[ac->avail++] = slabp->s_mem +
-			    slabp->free * cachep->objsize;
-
-			slabp->inuse++;
-			next = slab_bufctl(slabp)[slabp->free];
-#if DEBUG
-			slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
-			WARN_ON(numa_node_id() != slabp->nodeid);
-#endif
-			slabp->free = next;
+			ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,
+							    numa_node_id());
 		}
 		check_slabp(cachep, slabp);
 
@@ -2495,7 +2649,7 @@
 		x = cache_grow(cachep, flags, numa_node_id());
 
 		// cache_grow can reenable interrupts, then ac could change.
-		ac = ac_data(cachep);
+		ac = cpu_cache_get(cachep);
 		if (!x && ac->avail == 0)	// no objects in sight? abort
 			return NULL;
 
@@ -2507,7 +2661,7 @@
 }
 
 static inline void
-cache_alloc_debugcheck_before(kmem_cache_t *cachep, gfp_t flags)
+cache_alloc_debugcheck_before(struct kmem_cache *cachep, gfp_t flags)
 {
 	might_sleep_if(flags & __GFP_WAIT);
 #if DEBUG
@@ -2516,16 +2670,16 @@
 }
 
 #if DEBUG
-static void *cache_alloc_debugcheck_after(kmem_cache_t *cachep, gfp_t flags,
+static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, gfp_t flags,
 					void *objp, void *caller)
 {
 	if (!objp)
 		return objp;
 	if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
-		if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
+		if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
 			kernel_map_pages(virt_to_page(objp),
-					 cachep->objsize / PAGE_SIZE, 1);
+					 cachep->buffer_size / PAGE_SIZE, 1);
 		else
 			check_poison_obj(cachep, objp);
 #else
@@ -2550,7 +2704,7 @@
 		*dbg_redzone1(cachep, objp) = RED_ACTIVE;
 		*dbg_redzone2(cachep, objp) = RED_ACTIVE;
 	}
-	objp += obj_dbghead(cachep);
+	objp += obj_offset(cachep);
 	if (cachep->ctor && cachep->flags & SLAB_POISON) {
 		unsigned long ctor_flags = SLAB_CTOR_CONSTRUCTOR;
 
@@ -2565,13 +2719,22 @@
 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
 #endif
 
-static inline void *____cache_alloc(kmem_cache_t *cachep, gfp_t flags)
+static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
 	void *objp;
 	struct array_cache *ac;
 
+#ifdef CONFIG_NUMA
+	if (unlikely(current->mempolicy && !in_interrupt())) {
+		int nid = slab_node(current->mempolicy);
+
+		if (nid != numa_node_id())
+			return __cache_alloc_node(cachep, flags, nid);
+	}
+#endif
+
 	check_irq_off();
-	ac = ac_data(cachep);
+	ac = cpu_cache_get(cachep);
 	if (likely(ac->avail)) {
 		STATS_INC_ALLOCHIT(cachep);
 		ac->touched = 1;
@@ -2583,7 +2746,8 @@
 	return objp;
 }
 
-static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags)
+static __always_inline void *
+__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
 {
 	unsigned long save_flags;
 	void *objp;
@@ -2594,7 +2758,7 @@
 	objp = ____cache_alloc(cachep, flags);
 	local_irq_restore(save_flags);
 	objp = cache_alloc_debugcheck_after(cachep, flags, objp,
-					    __builtin_return_address(0));
+					    caller);
 	prefetchw(objp);
 	return objp;
 }
@@ -2603,19 +2767,19 @@
 /*
  * A interface to enable slab creation on nodeid
  */
-static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
+static void *__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
 	struct list_head *entry;
 	struct slab *slabp;
 	struct kmem_list3 *l3;
 	void *obj;
-	kmem_bufctl_t next;
 	int x;
 
 	l3 = cachep->nodelists[nodeid];
 	BUG_ON(!l3);
 
       retry:
+	check_irq_off();
 	spin_lock(&l3->list_lock);
 	entry = l3->slabs_partial.next;
 	if (entry == &l3->slabs_partial) {
@@ -2635,14 +2799,7 @@
 
 	BUG_ON(slabp->inuse == cachep->num);
 
-	/* get obj pointer */
-	obj = slabp->s_mem + slabp->free * cachep->objsize;
-	slabp->inuse++;
-	next = slab_bufctl(slabp)[slabp->free];
-#if DEBUG
-	slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
-#endif
-	slabp->free = next;
+	obj = slab_get_obj(cachep, slabp, nodeid);
 	check_slabp(cachep, slabp);
 	l3->free_objects--;
 	/* move slabp to correct slabp list: */
@@ -2673,7 +2830,7 @@
 /*
  * Caller needs to acquire correct kmem_list's list_lock
  */
-static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects,
+static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
 		       int node)
 {
 	int i;
@@ -2682,29 +2839,14 @@
 	for (i = 0; i < nr_objects; i++) {
 		void *objp = objpp[i];
 		struct slab *slabp;
-		unsigned int objnr;
 
-		slabp = page_get_slab(virt_to_page(objp));
+		slabp = virt_to_slab(objp);
 		l3 = cachep->nodelists[node];
 		list_del(&slabp->list);
-		objnr = (objp - slabp->s_mem) / cachep->objsize;
 		check_spinlock_acquired_node(cachep, node);
 		check_slabp(cachep, slabp);
-
-#if DEBUG
-		/* Verify that the slab belongs to the intended node */
-		WARN_ON(slabp->nodeid != node);
-
-		if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
-			printk(KERN_ERR "slab: double free detected in cache "
-			       "'%s', objp %p\n", cachep->name, objp);
-			BUG();
-		}
-#endif
-		slab_bufctl(slabp)[objnr] = slabp->free;
-		slabp->free = objnr;
+		slab_put_obj(cachep, slabp, objp, node);
 		STATS_DEC_ACTIVE(cachep);
-		slabp->inuse--;
 		l3->free_objects++;
 		check_slabp(cachep, slabp);
 
@@ -2726,7 +2868,7 @@
 	}
 }
 
-static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
+static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
 {
 	int batchcount;
 	struct kmem_list3 *l3;
@@ -2785,9 +2927,9 @@
  *
  * Called with disabled ints.
  */
-static inline void __cache_free(kmem_cache_t *cachep, void *objp)
+static inline void __cache_free(struct kmem_cache *cachep, void *objp)
 {
-	struct array_cache *ac = ac_data(cachep);
+	struct array_cache *ac = cpu_cache_get(cachep);
 
 	check_irq_off();
 	objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
@@ -2798,7 +2940,7 @@
 #ifdef CONFIG_NUMA
 	{
 		struct slab *slabp;
-		slabp = page_get_slab(virt_to_page(objp));
+		slabp = virt_to_slab(objp);
 		if (unlikely(slabp->nodeid != numa_node_id())) {
 			struct array_cache *alien = NULL;
 			int nodeid = slabp->nodeid;
@@ -2844,9 +2986,9 @@
  * Allocate an object from this cache.  The flags are only relevant
  * if the cache has no available objects.
  */
-void *kmem_cache_alloc(kmem_cache_t *cachep, gfp_t flags)
+void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
-	return __cache_alloc(cachep, flags);
+	return __cache_alloc(cachep, flags, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(kmem_cache_alloc);
 
@@ -2864,12 +3006,12 @@
  *
  * Currently only used for dentry validation.
  */
-int fastcall kmem_ptr_validate(kmem_cache_t *cachep, void *ptr)
+int fastcall kmem_ptr_validate(struct kmem_cache *cachep, void *ptr)
 {
 	unsigned long addr = (unsigned long)ptr;
 	unsigned long min_addr = PAGE_OFFSET;
 	unsigned long align_mask = BYTES_PER_WORD - 1;
-	unsigned long size = cachep->objsize;
+	unsigned long size = cachep->buffer_size;
 	struct page *page;
 
 	if (unlikely(addr < min_addr))
@@ -2905,32 +3047,23 @@
  * New and improved: it will now make sure that the object gets
  * put on the correct node list so that there is no false sharing.
  */
-void *kmem_cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
+void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
 	unsigned long save_flags;
 	void *ptr;
 
-	if (nodeid == -1)
-		return __cache_alloc(cachep, flags);
-
-	if (unlikely(!cachep->nodelists[nodeid])) {
-		/* Fall back to __cache_alloc if we run into trouble */
-		printk(KERN_WARNING
-		       "slab: not allocating in inactive node %d for cache %s\n",
-		       nodeid, cachep->name);
-		return __cache_alloc(cachep, flags);
-	}
-
 	cache_alloc_debugcheck_before(cachep, flags);
 	local_irq_save(save_flags);
-	if (nodeid == numa_node_id())
+
+	if (nodeid == -1 || nodeid == numa_node_id() ||
+	    !cachep->nodelists[nodeid])
 		ptr = ____cache_alloc(cachep, flags);
 	else
 		ptr = __cache_alloc_node(cachep, flags, nodeid);
 	local_irq_restore(save_flags);
-	ptr =
-	    cache_alloc_debugcheck_after(cachep, flags, ptr,
-					 __builtin_return_address(0));
+
+	ptr = cache_alloc_debugcheck_after(cachep, flags, ptr,
+					   __builtin_return_address(0));
 
 	return ptr;
 }
@@ -2938,7 +3071,7 @@
 
 void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
-	kmem_cache_t *cachep;
+	struct kmem_cache *cachep;
 
 	cachep = kmem_find_general_cachep(size, flags);
 	if (unlikely(cachep == NULL))
@@ -2969,9 +3102,10 @@
  * platforms.  For example, on i386, it means that the memory must come
  * from the first 16MB.
  */
-void *__kmalloc(size_t size, gfp_t flags)
+static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
+					  void *caller)
 {
-	kmem_cache_t *cachep;
+	struct kmem_cache *cachep;
 
 	/* If you want to save a few bytes .text space: replace
 	 * __ with kmem_.
@@ -2981,10 +3115,27 @@
 	cachep = __find_general_cachep(size, flags);
 	if (unlikely(cachep == NULL))
 		return NULL;
-	return __cache_alloc(cachep, flags);
+	return __cache_alloc(cachep, flags, caller);
+}
+
+#ifndef CONFIG_DEBUG_SLAB
+
+void *__kmalloc(size_t size, gfp_t flags)
+{
+	return __do_kmalloc(size, flags, NULL);
 }
 EXPORT_SYMBOL(__kmalloc);
 
+#else
+
+void *__kmalloc_track_caller(size_t size, gfp_t flags, void *caller)
+{
+	return __do_kmalloc(size, flags, caller);
+}
+EXPORT_SYMBOL(__kmalloc_track_caller);
+
+#endif
+
 #ifdef CONFIG_SMP
 /**
  * __alloc_percpu - allocate one copy of the object for every present
@@ -3042,7 +3193,7 @@
  * Free an object which was previously allocated from this
  * cache.
  */
-void kmem_cache_free(kmem_cache_t *cachep, void *objp)
+void kmem_cache_free(struct kmem_cache *cachep, void *objp)
 {
 	unsigned long flags;
 
@@ -3063,15 +3214,15 @@
  */
 void kfree(const void *objp)
 {
-	kmem_cache_t *c;
+	struct kmem_cache *c;
 	unsigned long flags;
 
 	if (unlikely(!objp))
 		return;
 	local_irq_save(flags);
 	kfree_debugcheck(objp);
-	c = page_get_cache(virt_to_page(objp));
-	mutex_debug_check_no_locks_freed(objp, obj_reallen(c));
+	c = virt_to_cache(objp);
+	mutex_debug_check_no_locks_freed(objp, obj_size(c));
 	__cache_free(c, (void *)objp);
 	local_irq_restore(flags);
 }
@@ -3100,13 +3251,13 @@
 EXPORT_SYMBOL(free_percpu);
 #endif
 
-unsigned int kmem_cache_size(kmem_cache_t *cachep)
+unsigned int kmem_cache_size(struct kmem_cache *cachep)
 {
-	return obj_reallen(cachep);
+	return obj_size(cachep);
 }
 EXPORT_SYMBOL(kmem_cache_size);
 
-const char *kmem_cache_name(kmem_cache_t *cachep)
+const char *kmem_cache_name(struct kmem_cache *cachep)
 {
 	return cachep->name;
 }
@@ -3115,7 +3266,7 @@
 /*
  * This initializes kmem_list3 for all nodes.
  */
-static int alloc_kmemlist(kmem_cache_t *cachep)
+static int alloc_kmemlist(struct kmem_cache *cachep)
 {
 	int node;
 	struct kmem_list3 *l3;
@@ -3171,7 +3322,7 @@
 }
 
 struct ccupdate_struct {
-	kmem_cache_t *cachep;
+	struct kmem_cache *cachep;
 	struct array_cache *new[NR_CPUS];
 };
 
@@ -3181,13 +3332,13 @@
 	struct array_cache *old;
 
 	check_irq_off();
-	old = ac_data(new->cachep);
+	old = cpu_cache_get(new->cachep);
 
 	new->cachep->array[smp_processor_id()] = new->new[smp_processor_id()];
 	new->new[smp_processor_id()] = old;
 }
 
-static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
+static int do_tune_cpucache(struct kmem_cache *cachep, int limit, int batchcount,
 			    int shared)
 {
 	struct ccupdate_struct new;
@@ -3208,11 +3359,11 @@
 	smp_call_function_all_cpus(do_ccupdate_local, (void *)&new);
 
 	check_irq_on();
-	spin_lock_irq(&cachep->spinlock);
+	spin_lock(&cachep->spinlock);
 	cachep->batchcount = batchcount;
 	cachep->limit = limit;
 	cachep->shared = shared;
-	spin_unlock_irq(&cachep->spinlock);
+	spin_unlock(&cachep->spinlock);
 
 	for_each_online_cpu(i) {
 		struct array_cache *ccold = new.new[i];
@@ -3233,7 +3384,7 @@
 	return 0;
 }
 
-static void enable_cpucache(kmem_cache_t *cachep)
+static void enable_cpucache(struct kmem_cache *cachep)
 {
 	int err;
 	int limit, shared;
@@ -3246,13 +3397,13 @@
 	 * The numbers are guessed, we should auto-tune as described by
 	 * Bonwick.
 	 */
-	if (cachep->objsize > 131072)
+	if (cachep->buffer_size > 131072)
 		limit = 1;
-	else if (cachep->objsize > PAGE_SIZE)
+	else if (cachep->buffer_size > PAGE_SIZE)
 		limit = 8;
-	else if (cachep->objsize > 1024)
+	else if (cachep->buffer_size > 1024)
 		limit = 24;
-	else if (cachep->objsize > 256)
+	else if (cachep->buffer_size > 256)
 		limit = 54;
 	else
 		limit = 120;
@@ -3267,7 +3418,7 @@
 	 */
 	shared = 0;
 #ifdef CONFIG_SMP
-	if (cachep->objsize <= PAGE_SIZE)
+	if (cachep->buffer_size <= PAGE_SIZE)
 		shared = 8;
 #endif
 
@@ -3285,7 +3436,7 @@
 		       cachep->name, -err);
 }
 
-static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac,
+static void drain_array_locked(struct kmem_cache *cachep, struct array_cache *ac,
 				int force, int node)
 {
 	int tofree;
@@ -3314,7 +3465,7 @@
  * - clear the per-cpu caches for this CPU.
  * - return freeable pages to the main free memory pool.
  *
- * If we cannot acquire the cache chain semaphore then just give up - we'll
+ * If we cannot acquire the cache chain mutex then just give up - we'll
  * try again on the next iteration.
  */
 static void cache_reap(void *unused)
@@ -3322,7 +3473,7 @@
 	struct list_head *walk;
 	struct kmem_list3 *l3;
 
-	if (down_trylock(&cache_chain_sem)) {
+	if (!mutex_trylock(&cache_chain_mutex)) {
 		/* Give up. Setup the next iteration. */
 		schedule_delayed_work(&__get_cpu_var(reap_work),
 				      REAPTIMEOUT_CPUC);
@@ -3330,12 +3481,12 @@
 	}
 
 	list_for_each(walk, &cache_chain) {
-		kmem_cache_t *searchp;
+		struct kmem_cache *searchp;
 		struct list_head *p;
 		int tofree;
 		struct slab *slabp;
 
-		searchp = list_entry(walk, kmem_cache_t, next);
+		searchp = list_entry(walk, struct kmem_cache, next);
 
 		if (searchp->flags & SLAB_NO_REAP)
 			goto next;
@@ -3344,10 +3495,10 @@
 
 		l3 = searchp->nodelists[numa_node_id()];
 		if (l3->alien)
-			drain_alien_cache(searchp, l3);
+			drain_alien_cache(searchp, l3->alien);
 		spin_lock_irq(&l3->list_lock);
 
-		drain_array_locked(searchp, ac_data(searchp), 0,
+		drain_array_locked(searchp, cpu_cache_get(searchp), 0,
 				   numa_node_id());
 
 		if (time_after(l3->next_reap, jiffies))
@@ -3393,7 +3544,7 @@
 		cond_resched();
 	}
 	check_irq_on();
-	up(&cache_chain_sem);
+	mutex_unlock(&cache_chain_mutex);
 	drain_remote_pages();
 	/* Setup the next iteration */
 	schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC);
@@ -3429,7 +3580,7 @@
 	loff_t n = *pos;
 	struct list_head *p;
 
-	down(&cache_chain_sem);
+	mutex_lock(&cache_chain_mutex);
 	if (!n)
 		print_slabinfo_header(m);
 	p = cache_chain.next;
@@ -3438,25 +3589,25 @@
 		if (p == &cache_chain)
 			return NULL;
 	}
-	return list_entry(p, kmem_cache_t, next);
+	return list_entry(p, struct kmem_cache, next);
 }
 
 static void *s_next(struct seq_file *m, void *p, loff_t *pos)
 {
-	kmem_cache_t *cachep = p;
+	struct kmem_cache *cachep = p;
 	++*pos;
 	return cachep->next.next == &cache_chain ? NULL
-	    : list_entry(cachep->next.next, kmem_cache_t, next);
+	    : list_entry(cachep->next.next, struct kmem_cache, next);
 }
 
 static void s_stop(struct seq_file *m, void *p)
 {
-	up(&cache_chain_sem);
+	mutex_unlock(&cache_chain_mutex);
 }
 
 static int s_show(struct seq_file *m, void *p)
 {
-	kmem_cache_t *cachep = p;
+	struct kmem_cache *cachep = p;
 	struct list_head *q;
 	struct slab *slabp;
 	unsigned long active_objs;
@@ -3468,8 +3619,7 @@
 	int node;
 	struct kmem_list3 *l3;
 
-	check_irq_on();
-	spin_lock_irq(&cachep->spinlock);
+	spin_lock(&cachep->spinlock);
 	active_objs = 0;
 	num_slabs = 0;
 	for_each_online_node(node) {
@@ -3477,7 +3627,8 @@
 		if (!l3)
 			continue;
 
-		spin_lock(&l3->list_lock);
+		check_irq_on();
+		spin_lock_irq(&l3->list_lock);
 
 		list_for_each(q, &l3->slabs_full) {
 			slabp = list_entry(q, struct slab, list);
@@ -3502,9 +3653,10 @@
 			num_slabs++;
 		}
 		free_objects += l3->free_objects;
-		shared_avail += l3->shared->avail;
+		if (l3->shared)
+			shared_avail += l3->shared->avail;
 
-		spin_unlock(&l3->list_lock);
+		spin_unlock_irq(&l3->list_lock);
 	}
 	num_slabs += active_slabs;
 	num_objs = num_slabs * cachep->num;
@@ -3516,7 +3668,7 @@
 		printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
 
 	seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d",
-		   name, active_objs, num_objs, cachep->objsize,
+		   name, active_objs, num_objs, cachep->buffer_size,
 		   cachep->num, (1 << cachep->gfporder));
 	seq_printf(m, " : tunables %4u %4u %4u",
 		   cachep->limit, cachep->batchcount, cachep->shared);
@@ -3548,7 +3700,7 @@
 	}
 #endif
 	seq_putc(m, '\n');
-	spin_unlock_irq(&cachep->spinlock);
+	spin_unlock(&cachep->spinlock);
 	return 0;
 }
 
@@ -3603,10 +3755,11 @@
 		return -EINVAL;
 
 	/* Find the cache in the chain of caches. */
-	down(&cache_chain_sem);
+	mutex_lock(&cache_chain_mutex);
 	res = -EINVAL;
 	list_for_each(p, &cache_chain) {
-		kmem_cache_t *cachep = list_entry(p, kmem_cache_t, next);
+		struct kmem_cache *cachep = list_entry(p, struct kmem_cache,
+						       next);
 
 		if (!strcmp(cachep->name, kbuf)) {
 			if (limit < 1 ||
@@ -3620,7 +3773,7 @@
 			break;
 		}
 	}
-	up(&cache_chain_sem);
+	mutex_unlock(&cache_chain_mutex);
 	if (res >= 0)
 		res = count;
 	return res;
@@ -3644,5 +3797,5 @@
 	if (unlikely(objp == NULL))
 		return 0;
 
-	return obj_reallen(page_get_cache(virt_to_page(objp)));
+	return obj_size(virt_to_cache(objp));
 }
diff --git a/mm/slob.c b/mm/slob.c
index 1c240c4..a1f42bd 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -336,7 +336,7 @@
 
 #ifdef CONFIG_SMP
 
-void *__alloc_percpu(size_t size, size_t align)
+void *__alloc_percpu(size_t size)
 {
 	int i;
 	struct percpu_data *pdata = kmalloc(sizeof (*pdata), GFP_KERNEL);
diff --git a/mm/swap.c b/mm/swap.c
index cbb48e7..7624742 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -34,19 +34,22 @@
 /* How many pages do we try to swap or page in/out together? */
 int page_cluster;
 
+static void put_compound_page(struct page *page)
+{
+	page = (struct page *)page_private(page);
+	if (put_page_testzero(page)) {
+		void (*dtor)(struct page *page);
+
+		dtor = (void (*)(struct page *))page[1].mapping;
+		(*dtor)(page);
+	}
+}
+
 void put_page(struct page *page)
 {
-	if (unlikely(PageCompound(page))) {
-		page = (struct page *)page_private(page);
-		if (put_page_testzero(page)) {
-			void (*dtor)(struct page *page);
-
-			dtor = (void (*)(struct page *))page[1].mapping;
-			(*dtor)(page);
-		}
-		return;
-	}
-	if (put_page_testzero(page))
+	if (unlikely(PageCompound(page)))
+		put_compound_page(page);
+	else if (put_page_testzero(page))
 		__page_cache_release(page);
 }
 EXPORT_SYMBOL(put_page);
@@ -174,6 +177,32 @@
 	put_cpu();
 }
 
+#ifdef CONFIG_NUMA
+static void lru_add_drain_per_cpu(void *dummy)
+{
+	lru_add_drain();
+}
+
+/*
+ * Returns 0 for success
+ */
+int lru_add_drain_all(void)
+{
+	return schedule_on_each_cpu(lru_add_drain_per_cpu, NULL);
+}
+
+#else
+
+/*
+ * Returns 0 for success
+ */
+int lru_add_drain_all(void)
+{
+	lru_add_drain();
+	return 0;
+}
+#endif
+
 /*
  * This path almost never happens for VM activity - pages are normally
  * freed via pagevecs.  But it gets used by networking.
@@ -218,6 +247,15 @@
 		struct page *page = pages[i];
 		struct zone *pagezone;
 
+		if (unlikely(PageCompound(page))) {
+			if (zone) {
+				spin_unlock_irq(&zone->lru_lock);
+				zone = NULL;
+			}
+			put_compound_page(page);
+			continue;
+		}
+
 		if (!put_page_testzero(page))
 			continue;
 
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 7b09ac5..db8a3d3 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -27,6 +27,7 @@
 	.writepage	= swap_writepage,
 	.sync_page	= block_sync_page,
 	.set_page_dirty	= __set_page_dirty_nobuffers,
+	.migratepage	= migrate_page,
 };
 
 static struct backing_dev_info swap_backing_dev_info = {
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 957fef4..1f9cf0d 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -25,6 +25,7 @@
 #include <linux/rmap.h>
 #include <linux/security.h>
 #include <linux/backing-dev.h>
+#include <linux/mutex.h>
 #include <linux/capability.h>
 #include <linux/syscalls.h>
 
@@ -46,12 +47,12 @@
 
 struct swap_info_struct swap_info[MAX_SWAPFILES];
 
-static DECLARE_MUTEX(swapon_sem);
+static DEFINE_MUTEX(swapon_mutex);
 
 /*
  * We need this because the bdev->unplug_fn can sleep and we cannot
  * hold swap_lock while calling the unplug_fn. And swap_lock
- * cannot be turned into a semaphore.
+ * cannot be turned into a mutex.
  */
 static DECLARE_RWSEM(swap_unplug_sem);
 
@@ -553,6 +554,15 @@
 	return 0;
 }
 
+#ifdef CONFIG_MIGRATION
+int remove_vma_swap(struct vm_area_struct *vma, struct page *page)
+{
+	swp_entry_t entry = { .val = page_private(page) };
+
+	return unuse_vma(vma, entry, page);
+}
+#endif
+
 /*
  * Scan swap_map from current position to next entry still in use.
  * Recycle to start on reaching the end, returning 0 when empty.
@@ -645,6 +655,7 @@
 		 */
 		swap_map = &si->swap_map[i];
 		entry = swp_entry(type, i);
+again:
 		page = read_swap_cache_async(entry, NULL, 0);
 		if (!page) {
 			/*
@@ -679,6 +690,12 @@
 		wait_on_page_locked(page);
 		wait_on_page_writeback(page);
 		lock_page(page);
+		if (!PageSwapCache(page)) {
+			/* Page migration has occured */
+			unlock_page(page);
+			page_cache_release(page);
+			goto again;
+		}
 		wait_on_page_writeback(page);
 
 		/*
@@ -1161,7 +1178,7 @@
 	up_write(&swap_unplug_sem);
 
 	destroy_swap_extents(p);
-	down(&swapon_sem);
+	mutex_lock(&swapon_mutex);
 	spin_lock(&swap_lock);
 	drain_mmlist();
 
@@ -1180,7 +1197,7 @@
 	p->swap_map = NULL;
 	p->flags = 0;
 	spin_unlock(&swap_lock);
-	up(&swapon_sem);
+	mutex_unlock(&swapon_mutex);
 	vfree(swap_map);
 	inode = mapping->host;
 	if (S_ISBLK(inode->i_mode)) {
@@ -1209,7 +1226,7 @@
 	int i;
 	loff_t l = *pos;
 
-	down(&swapon_sem);
+	mutex_lock(&swapon_mutex);
 
 	for (i = 0; i < nr_swapfiles; i++, ptr++) {
 		if (!(ptr->flags & SWP_USED) || !ptr->swap_map)
@@ -1238,7 +1255,7 @@
 
 static void swap_stop(struct seq_file *swap, void *v)
 {
-	up(&swapon_sem);
+	mutex_unlock(&swapon_mutex);
 }
 
 static int swap_show(struct seq_file *swap, void *v)
@@ -1540,7 +1557,7 @@
 		goto bad_swap;
 	}
 
-	down(&swapon_sem);
+	mutex_lock(&swapon_mutex);
 	spin_lock(&swap_lock);
 	p->flags = SWP_ACTIVE;
 	nr_swap_pages += nr_good_pages;
@@ -1566,7 +1583,7 @@
 		swap_info[prev].next = p - swap_info;
 	}
 	spin_unlock(&swap_lock);
-	up(&swapon_sem);
+	mutex_unlock(&swapon_mutex);
 	error = 0;
 	goto out;
 bad_swap:
diff --git a/mm/vmscan.c b/mm/vmscan.c
index bf903b2..1838c15 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -71,6 +71,9 @@
 
 	int may_writepage;
 
+	/* Can pages be swapped as part of reclaim? */
+	int may_swap;
+
 	/* This context's SWAP_CLUSTER_MAX. If freeing memory for
 	 * suspend, we effectively ignore SWAP_CLUSTER_MAX.
 	 * In this context, it doesn't matter that we scan the
@@ -440,6 +443,10 @@
 		BUG_ON(PageActive(page));
 
 		sc->nr_scanned++;
+
+		if (!sc->may_swap && page_mapped(page))
+			goto keep_locked;
+
 		/* Double the slab pressure for mapped and swapcache pages */
 		if (page_mapped(page) || PageSwapCache(page))
 			sc->nr_scanned++;
@@ -458,6 +465,8 @@
 		 * Try to allocate it some swap space here.
 		 */
 		if (PageAnon(page) && !PageSwapCache(page)) {
+			if (!sc->may_swap)
+				goto keep_locked;
 			if (!add_to_swap(page, GFP_ATOMIC))
 				goto activate_locked;
 		}
@@ -472,7 +481,13 @@
 		 * processes. Try to unmap it here.
 		 */
 		if (page_mapped(page) && mapping) {
-			switch (try_to_unmap(page)) {
+			/*
+			 * No unmapping if we do not swap
+			 */
+			if (!sc->may_swap)
+				goto keep_locked;
+
+			switch (try_to_unmap(page, 0)) {
 			case SWAP_FAIL:
 				goto activate_locked;
 			case SWAP_AGAIN:
@@ -487,7 +502,7 @@
 				goto keep_locked;
 			if (!may_enter_fs)
 				goto keep_locked;
-			if (laptop_mode && !sc->may_writepage)
+			if (!sc->may_writepage)
 				goto keep_locked;
 
 			/* Page is dirty, try to write it out here */
@@ -586,7 +601,7 @@
 }
 
 /*
- * Add isolated pages on the list back to the LRU
+ * Add isolated pages on the list back to the LRU.
  *
  * returns the number of pages put back.
  */
@@ -604,6 +619,15 @@
 }
 
 /*
+ * Non migratable page
+ */
+int fail_migrate_page(struct page *newpage, struct page *page)
+{
+	return -EIO;
+}
+EXPORT_SYMBOL(fail_migrate_page);
+
+/*
  * swapout a single page
  * page is locked upon entry, unlocked on exit
  */
@@ -612,7 +636,7 @@
 	struct address_space *mapping = page_mapping(page);
 
 	if (page_mapped(page) && mapping)
-		if (try_to_unmap(page) != SWAP_SUCCESS)
+		if (try_to_unmap(page, 1) != SWAP_SUCCESS)
 			goto unlock_retry;
 
 	if (PageDirty(page)) {
@@ -648,6 +672,167 @@
 retry:
 	return -EAGAIN;
 }
+EXPORT_SYMBOL(swap_page);
+
+/*
+ * Page migration was first developed in the context of the memory hotplug
+ * project. The main authors of the migration code are:
+ *
+ * IWAMOTO Toshihiro <iwamoto@valinux.co.jp>
+ * Hirokazu Takahashi <taka@valinux.co.jp>
+ * Dave Hansen <haveblue@us.ibm.com>
+ * Christoph Lameter <clameter@sgi.com>
+ */
+
+/*
+ * Remove references for a page and establish the new page with the correct
+ * basic settings to be able to stop accesses to the page.
+ */
+int migrate_page_remove_references(struct page *newpage,
+				struct page *page, int nr_refs)
+{
+	struct address_space *mapping = page_mapping(page);
+	struct page **radix_pointer;
+
+	/*
+	 * Avoid doing any of the following work if the page count
+	 * indicates that the page is in use or truncate has removed
+	 * the page.
+	 */
+	if (!mapping || page_mapcount(page) + nr_refs != page_count(page))
+		return 1;
+
+	/*
+	 * Establish swap ptes for anonymous pages or destroy pte
+	 * maps for files.
+	 *
+	 * In order to reestablish file backed mappings the fault handlers
+	 * will take the radix tree_lock which may then be used to stop
+  	 * processses from accessing this page until the new page is ready.
+	 *
+	 * A process accessing via a swap pte (an anonymous page) will take a
+	 * page_lock on the old page which will block the process until the
+	 * migration attempt is complete. At that time the PageSwapCache bit
+	 * will be examined. If the page was migrated then the PageSwapCache
+	 * bit will be clear and the operation to retrieve the page will be
+	 * retried which will find the new page in the radix tree. Then a new
+	 * direct mapping may be generated based on the radix tree contents.
+	 *
+	 * If the page was not migrated then the PageSwapCache bit
+	 * is still set and the operation may continue.
+	 */
+	try_to_unmap(page, 1);
+
+	/*
+	 * Give up if we were unable to remove all mappings.
+	 */
+	if (page_mapcount(page))
+		return 1;
+
+	write_lock_irq(&mapping->tree_lock);
+
+	radix_pointer = (struct page **)radix_tree_lookup_slot(
+						&mapping->page_tree,
+						page_index(page));
+
+	if (!page_mapping(page) || page_count(page) != nr_refs ||
+			*radix_pointer != page) {
+		write_unlock_irq(&mapping->tree_lock);
+		return 1;
+	}
+
+	/*
+	 * Now we know that no one else is looking at the page.
+	 *
+	 * Certain minimal information about a page must be available
+	 * in order for other subsystems to properly handle the page if they
+	 * find it through the radix tree update before we are finished
+	 * copying the page.
+	 */
+	get_page(newpage);
+	newpage->index = page->index;
+	newpage->mapping = page->mapping;
+	if (PageSwapCache(page)) {
+		SetPageSwapCache(newpage);
+		set_page_private(newpage, page_private(page));
+	}
+
+	*radix_pointer = newpage;
+	__put_page(page);
+	write_unlock_irq(&mapping->tree_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(migrate_page_remove_references);
+
+/*
+ * Copy the page to its new location
+ */
+void migrate_page_copy(struct page *newpage, struct page *page)
+{
+	copy_highpage(newpage, page);
+
+	if (PageError(page))
+		SetPageError(newpage);
+	if (PageReferenced(page))
+		SetPageReferenced(newpage);
+	if (PageUptodate(page))
+		SetPageUptodate(newpage);
+	if (PageActive(page))
+		SetPageActive(newpage);
+	if (PageChecked(page))
+		SetPageChecked(newpage);
+	if (PageMappedToDisk(page))
+		SetPageMappedToDisk(newpage);
+
+	if (PageDirty(page)) {
+		clear_page_dirty_for_io(page);
+		set_page_dirty(newpage);
+ 	}
+
+	ClearPageSwapCache(page);
+	ClearPageActive(page);
+	ClearPagePrivate(page);
+	set_page_private(page, 0);
+	page->mapping = NULL;
+
+	/*
+	 * If any waiters have accumulated on the new page then
+	 * wake them up.
+	 */
+	if (PageWriteback(newpage))
+		end_page_writeback(newpage);
+}
+EXPORT_SYMBOL(migrate_page_copy);
+
+/*
+ * Common logic to directly migrate a single page suitable for
+ * pages that do not use PagePrivate.
+ *
+ * Pages are locked upon entry and exit.
+ */
+int migrate_page(struct page *newpage, struct page *page)
+{
+	BUG_ON(PageWriteback(page));	/* Writeback must be complete */
+
+	if (migrate_page_remove_references(newpage, page, 2))
+		return -EAGAIN;
+
+	migrate_page_copy(newpage, page);
+
+	/*
+	 * Remove auxiliary swap entries and replace
+	 * them with real ptes.
+	 *
+	 * Note that a real pte entry will allow processes that are not
+	 * waiting on the page lock to use the new page via the page tables
+	 * before the new page is unlocked.
+	 */
+	remove_from_swap(newpage);
+	return 0;
+}
+EXPORT_SYMBOL(migrate_page);
+
 /*
  * migrate_pages
  *
@@ -658,14 +843,9 @@
  * pages are swapped out.
  *
  * The function returns after 10 attempts or if no pages
- * are movable anymore because t has become empty
+ * are movable anymore because to has become empty
  * or no retryable pages exist anymore.
  *
- * SIMPLIFIED VERSION: This implementation of migrate_pages
- * is only swapping out pages and never touches the second
- * list. The direct migration patchset
- * extends this function to avoid the use of swap.
- *
  * Return: Number of pages not migrated when "to" ran empty.
  */
 int migrate_pages(struct list_head *from, struct list_head *to,
@@ -686,6 +866,9 @@
 	retry = 0;
 
 	list_for_each_entry_safe(page, page2, from, lru) {
+		struct page *newpage = NULL;
+		struct address_space *mapping;
+
 		cond_resched();
 
 		rc = 0;
@@ -693,6 +876,9 @@
 			/* page was freed from under us. So we are done. */
 			goto next;
 
+		if (to && list_empty(to))
+			break;
+
 		/*
 		 * Skip locked pages during the first two passes to give the
 		 * functions holding the lock time to release the page. Later we
@@ -729,12 +915,84 @@
 			}
 		}
 
+		if (!to) {
+			rc = swap_page(page);
+			goto next;
+		}
+
+		newpage = lru_to_page(to);
+		lock_page(newpage);
+
 		/*
-		 * Page is properly locked and writeback is complete.
+		 * Pages are properly locked and writeback is complete.
 		 * Try to migrate the page.
 		 */
-		rc = swap_page(page);
-		goto next;
+		mapping = page_mapping(page);
+		if (!mapping)
+			goto unlock_both;
+
+		if (mapping->a_ops->migratepage) {
+			/*
+			 * Most pages have a mapping and most filesystems
+			 * should provide a migration function. Anonymous
+			 * pages are part of swap space which also has its
+			 * own migration function. This is the most common
+			 * path for page migration.
+			 */
+			rc = mapping->a_ops->migratepage(newpage, page);
+			goto unlock_both;
+                }
+
+		/*
+		 * Default handling if a filesystem does not provide
+		 * a migration function. We can only migrate clean
+		 * pages so try to write out any dirty pages first.
+		 */
+		if (PageDirty(page)) {
+			switch (pageout(page, mapping)) {
+			case PAGE_KEEP:
+			case PAGE_ACTIVATE:
+				goto unlock_both;
+
+			case PAGE_SUCCESS:
+				unlock_page(newpage);
+				goto next;
+
+			case PAGE_CLEAN:
+				; /* try to migrate the page below */
+			}
+                }
+
+		/*
+		 * Buffers are managed in a filesystem specific way.
+		 * We must have no buffers or drop them.
+		 */
+		if (!page_has_buffers(page) ||
+		    try_to_release_page(page, GFP_KERNEL)) {
+			rc = migrate_page(newpage, page);
+			goto unlock_both;
+		}
+
+		/*
+		 * On early passes with mapped pages simply
+		 * retry. There may be a lock held for some
+		 * buffers that may go away. Later
+		 * swap them out.
+		 */
+		if (pass > 4) {
+			/*
+			 * Persistently unable to drop buffers..... As a
+			 * measure of last resort we fall back to
+			 * swap_page().
+			 */
+			unlock_page(newpage);
+			newpage = NULL;
+			rc = swap_page(page);
+			goto next;
+		}
+
+unlock_both:
+		unlock_page(newpage);
 
 unlock_page:
 		unlock_page(page);
@@ -747,7 +1005,10 @@
 			list_move(&page->lru, failed);
 			nr_failed++;
 		} else {
-			/* Success */
+			if (newpage) {
+				/* Successful migration. Return page to LRU */
+				move_to_lru(newpage);
+			}
 			list_move(&page->lru, moved);
 		}
 	}
@@ -760,46 +1021,33 @@
 	return nr_failed + retry;
 }
 
-static void lru_add_drain_per_cpu(void *dummy)
-{
-	lru_add_drain();
-}
-
 /*
  * Isolate one page from the LRU lists and put it on the
- * indicated list. Do necessary cache draining if the
- * page is not on the LRU lists yet.
+ * indicated list with elevated refcount.
  *
  * Result:
  *  0 = page not on LRU list
  *  1 = page removed from LRU list and added to the specified list.
- * -ENOENT = page is being freed elsewhere.
  */
 int isolate_lru_page(struct page *page)
 {
-	int rc = 0;
-	struct zone *zone = page_zone(page);
+	int ret = 0;
 
-redo:
-	spin_lock_irq(&zone->lru_lock);
-	rc = __isolate_lru_page(page);
-	if (rc == 1) {
-		if (PageActive(page))
-			del_page_from_active_list(zone, page);
-		else
-			del_page_from_inactive_list(zone, page);
+	if (PageLRU(page)) {
+		struct zone *zone = page_zone(page);
+		spin_lock_irq(&zone->lru_lock);
+		if (TestClearPageLRU(page)) {
+			ret = 1;
+			get_page(page);
+			if (PageActive(page))
+				del_page_from_active_list(zone, page);
+			else
+				del_page_from_inactive_list(zone, page);
+		}
+		spin_unlock_irq(&zone->lru_lock);
 	}
-	spin_unlock_irq(&zone->lru_lock);
-	if (rc == 0) {
-		/*
-		 * Maybe this page is still waiting for a cpu to drain it
-		 * from one of the lru lists?
-		 */
-		rc = schedule_on_each_cpu(lru_add_drain_per_cpu, NULL);
-		if (rc == 0 && PageLRU(page))
-			goto redo;
-	}
-	return rc;
+
+	return ret;
 }
 #endif
 
@@ -831,18 +1079,20 @@
 		page = lru_to_page(src);
 		prefetchw_prev_lru_page(page, src, flags);
 
-		switch (__isolate_lru_page(page)) {
-		case 1:
-			/* Succeeded to isolate page */
-			list_move(&page->lru, dst);
-			nr_taken++;
-			break;
-		case -ENOENT:
-			/* Not possible to isolate */
-			list_move(&page->lru, src);
-			break;
-		default:
+		if (!TestClearPageLRU(page))
 			BUG();
+		list_del(&page->lru);
+		if (get_page_testone(page)) {
+			/*
+			 * It is being freed elsewhere
+			 */
+			__put_page(page);
+			SetPageLRU(page);
+			list_add(&page->lru, src);
+			continue;
+		} else {
+			list_add(&page->lru, dst);
+			nr_taken++;
 		}
 	}
 
@@ -945,9 +1195,47 @@
 	struct page *page;
 	struct pagevec pvec;
 	int reclaim_mapped = 0;
-	long mapped_ratio;
-	long distress;
-	long swap_tendency;
+
+	if (unlikely(sc->may_swap)) {
+		long mapped_ratio;
+		long distress;
+		long swap_tendency;
+
+		/*
+		 * `distress' is a measure of how much trouble we're having
+		 * reclaiming pages.  0 -> no problems.  100 -> great trouble.
+		 */
+		distress = 100 >> zone->prev_priority;
+
+		/*
+		 * The point of this algorithm is to decide when to start
+		 * reclaiming mapped memory instead of just pagecache.  Work out
+		 * how much memory
+		 * is mapped.
+		 */
+		mapped_ratio = (sc->nr_mapped * 100) / total_memory;
+
+		/*
+		 * Now decide how much we really want to unmap some pages.  The
+		 * mapped ratio is downgraded - just because there's a lot of
+		 * mapped memory doesn't necessarily mean that page reclaim
+		 * isn't succeeding.
+		 *
+		 * The distress ratio is important - we don't want to start
+		 * going oom.
+		 *
+		 * A 100% value of vm_swappiness overrides this algorithm
+		 * altogether.
+		 */
+		swap_tendency = mapped_ratio / 2 + distress + vm_swappiness;
+
+		/*
+		 * Now use this metric to decide whether to start moving mapped
+		 * memory onto the inactive list.
+		 */
+		if (swap_tendency >= 100)
+			reclaim_mapped = 1;
+	}
 
 	lru_add_drain();
 	spin_lock_irq(&zone->lru_lock);
@@ -957,37 +1245,6 @@
 	zone->nr_active -= pgmoved;
 	spin_unlock_irq(&zone->lru_lock);
 
-	/*
-	 * `distress' is a measure of how much trouble we're having reclaiming
-	 * pages.  0 -> no problems.  100 -> great trouble.
-	 */
-	distress = 100 >> zone->prev_priority;
-
-	/*
-	 * The point of this algorithm is to decide when to start reclaiming
-	 * mapped memory instead of just pagecache.  Work out how much memory
-	 * is mapped.
-	 */
-	mapped_ratio = (sc->nr_mapped * 100) / total_memory;
-
-	/*
-	 * Now decide how much we really want to unmap some pages.  The mapped
-	 * ratio is downgraded - just because there's a lot of mapped memory
-	 * doesn't necessarily mean that page reclaim isn't succeeding.
-	 *
-	 * The distress ratio is important - we don't want to start going oom.
-	 *
-	 * A 100% value of vm_swappiness overrides this algorithm altogether.
-	 */
-	swap_tendency = mapped_ratio / 2 + distress + vm_swappiness;
-
-	/*
-	 * Now use this metric to decide whether to start moving mapped memory
-	 * onto the inactive list.
-	 */
-	if (swap_tendency >= 100)
-		reclaim_mapped = 1;
-
 	while (!list_empty(&l_hold)) {
 		cond_resched();
 		page = lru_to_page(&l_hold);
@@ -1176,7 +1433,8 @@
 	int i;
 
 	sc.gfp_mask = gfp_mask;
-	sc.may_writepage = 0;
+	sc.may_writepage = !laptop_mode;
+	sc.may_swap = 1;
 
 	inc_page_state(allocstall);
 
@@ -1278,7 +1536,8 @@
 	total_scanned = 0;
 	total_reclaimed = 0;
 	sc.gfp_mask = GFP_KERNEL;
-	sc.may_writepage = 0;
+	sc.may_writepage = !laptop_mode;
+	sc.may_swap = 1;
 	sc.nr_mapped = read_page_state(nr_mapped);
 
 	inc_page_state(pageoutrun);
@@ -1362,9 +1621,7 @@
 			sc.nr_reclaimed = 0;
 			sc.priority = priority;
 			sc.swap_cluster_max = nr_pages? nr_pages : SWAP_CLUSTER_MAX;
-			atomic_inc(&zone->reclaim_in_progress);
 			shrink_zone(zone, &sc);
-			atomic_dec(&zone->reclaim_in_progress);
 			reclaim_state->reclaimed_slab = 0;
 			nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
 						lru_pages);
@@ -1576,3 +1833,115 @@
 }
 
 module_init(kswapd_init)
+
+#ifdef CONFIG_NUMA
+/*
+ * Zone reclaim mode
+ *
+ * If non-zero call zone_reclaim when the number of free pages falls below
+ * the watermarks.
+ *
+ * In the future we may add flags to the mode. However, the page allocator
+ * should only have to check that zone_reclaim_mode != 0 before calling
+ * zone_reclaim().
+ */
+int zone_reclaim_mode __read_mostly;
+
+#define RECLAIM_OFF 0
+#define RECLAIM_ZONE (1<<0)	/* Run shrink_cache on the zone */
+#define RECLAIM_WRITE (1<<1)	/* Writeout pages during reclaim */
+#define RECLAIM_SWAP (1<<2)	/* Swap pages out during reclaim */
+#define RECLAIM_SLAB (1<<3)	/* Do a global slab shrink if the zone is out of memory */
+
+/*
+ * Mininum time between zone reclaim scans
+ */
+int zone_reclaim_interval __read_mostly = 30*HZ;
+
+/*
+ * Priority for ZONE_RECLAIM. This determines the fraction of pages
+ * of a node considered for each zone_reclaim. 4 scans 1/16th of
+ * a zone.
+ */
+#define ZONE_RECLAIM_PRIORITY 4
+
+/*
+ * Try to free up some pages from this zone through reclaim.
+ */
+int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
+{
+	int nr_pages;
+	struct task_struct *p = current;
+	struct reclaim_state reclaim_state;
+	struct scan_control sc;
+	cpumask_t mask;
+	int node_id;
+
+	if (time_before(jiffies,
+		zone->last_unsuccessful_zone_reclaim + zone_reclaim_interval))
+			return 0;
+
+	if (!(gfp_mask & __GFP_WAIT) ||
+		zone->all_unreclaimable ||
+		atomic_read(&zone->reclaim_in_progress) > 0)
+			return 0;
+
+	node_id = zone->zone_pgdat->node_id;
+	mask = node_to_cpumask(node_id);
+	if (!cpus_empty(mask) && node_id != numa_node_id())
+		return 0;
+
+	sc.may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE);
+	sc.may_swap = !!(zone_reclaim_mode & RECLAIM_SWAP);
+	sc.nr_scanned = 0;
+	sc.nr_reclaimed = 0;
+	sc.priority = ZONE_RECLAIM_PRIORITY + 1;
+	sc.nr_mapped = read_page_state(nr_mapped);
+	sc.gfp_mask = gfp_mask;
+
+	disable_swap_token();
+
+	nr_pages = 1 << order;
+	if (nr_pages > SWAP_CLUSTER_MAX)
+		sc.swap_cluster_max = nr_pages;
+	else
+		sc.swap_cluster_max = SWAP_CLUSTER_MAX;
+
+	cond_resched();
+	p->flags |= PF_MEMALLOC;
+	reclaim_state.reclaimed_slab = 0;
+	p->reclaim_state = &reclaim_state;
+
+	/*
+	 * Free memory by calling shrink zone with increasing priorities
+	 * until we have enough memory freed.
+	 */
+	do {
+		sc.priority--;
+		shrink_zone(zone, &sc);
+
+	} while (sc.nr_reclaimed < nr_pages && sc.priority > 0);
+
+	if (sc.nr_reclaimed < nr_pages && (zone_reclaim_mode & RECLAIM_SLAB)) {
+		/*
+		 * shrink_slab does not currently allow us to determine
+		 * how many pages were freed in the zone. So we just
+		 * shake the slab and then go offnode for a single allocation.
+		 *
+		 * shrink_slab will free memory on all zones and may take
+		 * a long time.
+		 */
+		shrink_slab(sc.nr_scanned, gfp_mask, order);
+		sc.nr_reclaimed = 1;    /* Avoid getting the off node timeout */
+	}
+
+	p->reclaim_state = NULL;
+	current->flags &= ~PF_MEMALLOC;
+
+	if (sc.nr_reclaimed == 0)
+		zone->last_unsuccessful_zone_reclaim = jiffies;
+
+	return sc.nr_reclaimed >= nr_pages;
+}
+#endif
+
diff --git a/net/802/p8023.c b/net/802/p8023.c
index d23e906..53cf057 100644
--- a/net/802/p8023.c
+++ b/net/802/p8023.c
@@ -59,3 +59,5 @@
 
 EXPORT_SYMBOL(destroy_8023_client);
 EXPORT_SYMBOL(make_8023_client);
+
+MODULE_LICENSE("GPL");
diff --git a/net/802/psnap.c b/net/802/psnap.c
index 4d63894..34e4296 100644
--- a/net/802/psnap.c
+++ b/net/802/psnap.c
@@ -59,8 +59,10 @@
 	proto = find_snap_client(skb->h.raw);
 	if (proto) {
 		/* Pass the frame on. */
+		u8 *hdr = skb->data;
 		skb->h.raw  += 5;
 		skb_pull(skb, 5);
+		skb_postpull_rcsum(skb, hdr, 5);
 		rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev);
 	} else {
 		skb->sk = NULL;
diff --git a/net/Kconfig b/net/Kconfig
index 9296b269..5126f58 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -27,6 +27,13 @@
 
 menu "Networking options"
 
+config NETDEBUG
+	bool "Network packet debugging"
+	help
+	  You can say Y here if you want to get additional messages useful in
+	  debugging bad packets, but can overwhelm logs under denial of service
+	  attacks.
+
 source "net/packet/Kconfig"
 source "net/unix/Kconfig"
 source "net/xfrm/Kconfig"
@@ -150,6 +157,7 @@
 
 source "net/dccp/Kconfig"
 source "net/sctp/Kconfig"
+source "net/tipc/Kconfig"
 source "net/atm/Kconfig"
 source "net/bridge/Kconfig"
 source "net/8021q/Kconfig"
@@ -159,7 +167,6 @@
 source "drivers/net/appletalk/Kconfig"
 source "net/x25/Kconfig"
 source "net/lapb/Kconfig"
-source "net/tipc/Kconfig"
 
 config NET_DIVERT
 	bool "Frame Diverter (EXPERIMENTAL)"
diff --git a/net/atm/signaling.c b/net/atm/signaling.c
index e7211a7..93ad59a 100644
--- a/net/atm/signaling.c
+++ b/net/atm/signaling.c
@@ -56,7 +56,8 @@
 	remove_wait_queue(&sigd_sleep,&wait);
 #else
 	if (!sigd) {
-		printk(KERN_WARNING "atmsvc: no signaling demon\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "atmsvc: no signaling demon\n");
 		kfree_skb(skb);
 		return;
 	}
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index bdb6458..97bdec7 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -143,13 +143,15 @@
 static int hci_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct hci_dev *hdev = hci_pi(sk)->hdev;
+	struct hci_dev *hdev;
 
 	BT_DBG("sock %p sk %p", sock, sk);
 
 	if (!sk)
 		return 0;
 
+	hdev = hci_pi(sk)->hdev;
+
 	bt_sock_unlink(&hci_sk_list, sk);
 
 	if (hdev) {
@@ -311,14 +313,18 @@
 {
 	struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
 	struct sock *sk = sock->sk;
+	struct hci_dev *hdev = hci_pi(sk)->hdev;
 
 	BT_DBG("sock %p sk %p", sock, sk);
 
+	if (!hdev)
+		return -EBADFD;
+
 	lock_sock(sk);
 
 	*addr_len = sizeof(*haddr);
 	haddr->hci_family = AF_BLUETOOTH;
-	haddr->hci_dev    = hci_pi(sk)->hdev->id;
+	haddr->hci_dev    = hdev->id;
 
 	release_sock(sk);
 	return 0;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 0d89d64..5b4253c 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -46,13 +46,15 @@
 #include <net/bluetooth/l2cap.h>
 #include <net/bluetooth/rfcomm.h>
 
-#define VERSION "1.6"
-
 #ifndef CONFIG_BT_RFCOMM_DEBUG
 #undef  BT_DBG
 #define BT_DBG(D...)
 #endif
 
+#define VERSION "1.7"
+
+static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
+
 static struct task_struct *rfcomm_thread;
 
 static DECLARE_MUTEX(rfcomm_sem);
@@ -623,7 +625,7 @@
 	/* Set L2CAP options */
 	sk = sock->sk;
 	lock_sock(sk);
-	l2cap_pi(sk)->imtu = RFCOMM_MAX_L2CAP_MTU;
+	l2cap_pi(sk)->imtu = l2cap_mtu;
 	release_sock(sk);
 
 	s = rfcomm_session_add(sock, BT_BOUND);
@@ -1868,7 +1870,7 @@
 	/* Set L2CAP options */
 	sk = sock->sk;
 	lock_sock(sk);
-	l2cap_pi(sk)->imtu = RFCOMM_MAX_L2CAP_MTU;
+	l2cap_pi(sk)->imtu = l2cap_mtu;
 	release_sock(sk);
 
 	/* Start listening on the socket */
@@ -2070,6 +2072,9 @@
 module_init(rfcomm_init);
 module_exit(rfcomm_exit);
 
+module_param(l2cap_mtu, uint, 0644);
+MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection");
+
 MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
 MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION);
 MODULE_VERSION(VERSION);
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index ba44288..7fa3a5a 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -79,9 +79,14 @@
  */
 static void port_carrier_check(void *arg)
 {
-	struct net_bridge_port *p = arg;
+	struct net_device *dev = arg;
+	struct net_bridge_port *p;
 
 	rtnl_lock();
+	p = dev->br_port;
+	if (!p)
+		goto done;
+
 	if (netif_carrier_ok(p->dev)) {
 		u32 cost = port_cost(p->dev);
 
@@ -97,9 +102,24 @@
 			br_stp_disable_port(p);
 		spin_unlock_bh(&p->br->lock);
 	}
+done:
 	rtnl_unlock();
 }
 
+static void release_nbp(struct kobject *kobj)
+{
+	struct net_bridge_port *p
+		= container_of(kobj, struct net_bridge_port, kobj);
+	kfree(p);
+}
+
+static struct kobj_type brport_ktype = {
+#ifdef CONFIG_SYSFS
+	.sysfs_ops = &brport_sysfs_ops,
+#endif
+	.release = release_nbp,
+};
+
 static void destroy_nbp(struct net_bridge_port *p)
 {
 	struct net_device *dev = p->dev;
@@ -108,7 +128,7 @@
 	p->dev = NULL;
 	dev_put(dev);
 
-	br_sysfs_freeif(p);
+	kobject_put(&p->kobj);
 }
 
 static void destroy_nbp_rcu(struct rcu_head *head)
@@ -118,17 +138,25 @@
 	destroy_nbp(p);
 }
 
-/* called with RTNL */
+/* Delete port(interface) from bridge is done in two steps.
+ * via RCU. First step, marks device as down. That deletes
+ * all the timers and stops new packets from flowing through.
+ *
+ * Final cleanup doesn't occur until after all CPU's finished
+ * processing packets.
+ *
+ * Protected from multiple admin operations by RTNL mutex
+ */
 static void del_nbp(struct net_bridge_port *p)
 {
 	struct net_bridge *br = p->br;
 	struct net_device *dev = p->dev;
 
-	dev->br_port = NULL;
+	sysfs_remove_link(&br->ifobj, dev->name);
+
 	dev_set_promiscuity(dev, -1);
 
 	cancel_delayed_work(&p->carrier_check);
-	flush_scheduled_work();
 
 	spin_lock_bh(&br->lock);
 	br_stp_disable_port(p);
@@ -138,10 +166,10 @@
 
 	list_del_rcu(&p->list);
 
-	del_timer_sync(&p->message_age_timer);
-	del_timer_sync(&p->forward_delay_timer);
-	del_timer_sync(&p->hold_timer);
-	
+	rcu_assign_pointer(dev->br_port, NULL);
+
+	kobject_del(&p->kobj);
+
 	call_rcu(&p->rcu, destroy_nbp_rcu);
 }
 
@@ -151,7 +179,6 @@
 	struct net_bridge_port *p, *n;
 
 	list_for_each_entry_safe(p, n, &br->port_list, list) {
-		br_sysfs_removeif(p);
 		del_nbp(p);
 	}
 
@@ -245,13 +272,17 @@
 	p->dev = dev;
 	p->path_cost = port_cost(dev);
  	p->priority = 0x8000 >> BR_PORT_BITS;
-	dev->br_port = p;
 	p->port_no = index;
 	br_init_port(p);
 	p->state = BR_STATE_DISABLED;
-	INIT_WORK(&p->carrier_check, port_carrier_check, p);
+	INIT_WORK(&p->carrier_check, port_carrier_check, dev);
 	kobject_init(&p->kobj);
 
+	kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
+	p->kobj.ktype = &brport_ktype;
+	p->kobj.parent = &(dev->class_dev.kobj);
+	p->kobj.kset = NULL;
+
 	return p;
 }
 
@@ -379,30 +410,43 @@
 	if (dev->br_port != NULL)
 		return -EBUSY;
 
-	if (IS_ERR(p = new_nbp(br, dev)))
+	p = new_nbp(br, dev);
+	if (IS_ERR(p))
 		return PTR_ERR(p);
 
- 	if ((err = br_fdb_insert(br, p, dev->dev_addr)))
-		destroy_nbp(p);
- 
-	else if ((err = br_sysfs_addif(p)))
-		del_nbp(p);
-	else {
-		dev_set_promiscuity(dev, 1);
+	err = kobject_add(&p->kobj);
+	if (err)
+		goto err0;
 
-		list_add_rcu(&p->list, &br->port_list);
+ 	err = br_fdb_insert(br, p, dev->dev_addr);
+	if (err)
+		goto err1;
 
-		spin_lock_bh(&br->lock);
-		br_stp_recalculate_bridge_id(br);
-		br_features_recompute(br);
-		if ((br->dev->flags & IFF_UP) 
-		    && (dev->flags & IFF_UP) && netif_carrier_ok(dev))
-			br_stp_enable_port(p);
-		spin_unlock_bh(&br->lock);
+	err = br_sysfs_addif(p);
+	if (err)
+		goto err2;
 
-		dev_set_mtu(br->dev, br_min_mtu(br));
-	}
+	rcu_assign_pointer(dev->br_port, p);
+	dev_set_promiscuity(dev, 1);
 
+	list_add_rcu(&p->list, &br->port_list);
+
+	spin_lock_bh(&br->lock);
+	br_stp_recalculate_bridge_id(br);
+	br_features_recompute(br);
+	schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
+	spin_unlock_bh(&br->lock);
+
+	dev_set_mtu(br->dev, br_min_mtu(br));
+	kobject_uevent(&p->kobj, KOBJ_ADD);
+
+	return 0;
+err2:
+	br_fdb_delete_by_port(br, p);
+err1:
+	kobject_del(&p->kobj);
+err0:
+	kobject_put(&p->kobj);
 	return err;
 }
 
@@ -414,7 +458,6 @@
 	if (!p || p->br != br) 
 		return -EINVAL;
 
-	br_sysfs_removeif(p);
 	del_nbp(p);
 
 	spin_lock_bh(&br->lock);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index e3a73ce..4eef837 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -45,18 +45,20 @@
 int br_handle_frame_finish(struct sk_buff *skb)
 {
 	const unsigned char *dest = eth_hdr(skb)->h_dest;
-	struct net_bridge_port *p = skb->dev->br_port;
-	struct net_bridge *br = p->br;
+	struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
+	struct net_bridge *br;
 	struct net_bridge_fdb_entry *dst;
 	int passedup = 0;
 
-	/* insert into forwarding database after filtering to avoid spoofing */
-	br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
+	if (!p || p->state == BR_STATE_DISABLED)
+		goto drop;
 
-	if (p->state == BR_STATE_LEARNING) {
-		kfree_skb(skb);
-		goto out;
-	}
+	/* insert into forwarding database after filtering to avoid spoofing */
+	br = p->br;
+	br_fdb_update(br, p, eth_hdr(skb)->h_source);
+
+	if (p->state == BR_STATE_LEARNING)
+		goto drop;
 
 	if (br->dev->flags & IFF_PROMISC) {
 		struct sk_buff *skb2;
@@ -93,6 +95,9 @@
 
 out:
 	return 0;
+drop:
+	kfree_skb(skb);
+	goto out;
 }
 
 /*
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 7cac3fb..6bb0c7e 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -51,9 +51,6 @@
 #define store_orig_dstaddr(skb)	 (skb_origaddr(skb) = (skb)->nh.iph->daddr)
 #define dnat_took_place(skb)	 (skb_origaddr(skb) != (skb)->nh.iph->daddr)
 
-#define has_bridge_parent(device)	((device)->br_port != NULL)
-#define bridge_parent(device)		((device)->br_port->br->dev)
-
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
 static int brnf_call_iptables = 1;
@@ -98,6 +95,12 @@
 	.rt_flags	= 0,
 };
 
+static inline struct net_device *bridge_parent(const struct net_device *dev)
+{
+	struct net_bridge_port *port = rcu_dereference(dev->br_port);
+
+	return port ? port->br->dev : NULL;
+}
 
 /* PF_BRIDGE/PRE_ROUTING *********************************************/
 /* Undo the changes made for ip6tables PREROUTING and continue the
@@ -189,11 +192,15 @@
 	skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
 
 	skb->dev = bridge_parent(skb->dev);
-	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
-		skb_pull(skb, VLAN_HLEN);
-		skb->nh.raw += VLAN_HLEN;
+	if (!skb->dev)
+		kfree_skb(skb);
+	else {
+		if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+			skb_pull(skb, VLAN_HLEN);
+			skb->nh.raw += VLAN_HLEN;
+		}
+		skb->dst->output(skb);
 	}
-	skb->dst->output(skb);
 	return 0;
 }
 
@@ -270,7 +277,7 @@
 }
 
 /* Some common code for IPv4/IPv6 */
-static void setup_pre_routing(struct sk_buff *skb)
+static struct net_device *setup_pre_routing(struct sk_buff *skb)
 {
 	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
 
@@ -282,6 +289,8 @@
 	nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
 	nf_bridge->physindev = skb->dev;
 	skb->dev = bridge_parent(skb->dev);
+
+	return skb->dev;
 }
 
 /* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */
@@ -376,7 +385,8 @@
  	nf_bridge_put(skb->nf_bridge);
 	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
 		return NF_DROP;
-	setup_pre_routing(skb);
+	if (!setup_pre_routing(skb))
+		return NF_DROP;
 
 	NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
 		br_nf_pre_routing_finish_ipv6);
@@ -465,7 +475,8 @@
  	nf_bridge_put(skb->nf_bridge);
 	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
 		return NF_DROP;
-	setup_pre_routing(skb);
+	if (!setup_pre_routing(skb))
+		return NF_DROP;
 	store_orig_dstaddr(skb);
 
 	NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
@@ -539,11 +550,16 @@
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge;
 	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+	struct net_device *parent;
 	int pf;
 
 	if (!skb->nf_bridge)
 		return NF_ACCEPT;
 
+	parent = bridge_parent(out);
+	if (!parent)
+		return NF_DROP;
+
 	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
 		pf = PF_INET;
 	else
@@ -564,8 +580,8 @@
 	nf_bridge->mask |= BRNF_BRIDGED;
 	nf_bridge->physoutdev = skb->dev;
 
-	NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in),
-		bridge_parent(out), br_nf_forward_finish);
+	NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), parent,
+		br_nf_forward_finish);
 
 	return NF_STOLEN;
 }
@@ -688,6 +704,8 @@
 		goto out;
 	}
 	realoutdev = bridge_parent(skb->dev);
+	if (!realoutdev)
+		return NF_DROP;
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 	/* iptables should match -o br0.x */
@@ -701,9 +719,11 @@
 	/* IP forwarded traffic has a physindev, locally
 	 * generated traffic hasn't. */
 	if (realindev != NULL) {
-		if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) &&
-		    has_bridge_parent(realindev))
-			realindev = bridge_parent(realindev);
+		if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) ) {
+			struct net_device *parent = bridge_parent(realindev);
+			if (parent)
+				realindev = parent;
+		}
 
 		NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
 			       realoutdev, br_nf_local_out_finish,
@@ -743,6 +763,9 @@
 	if (!nf_bridge)
 		return NF_ACCEPT;
 
+	if (!realoutdev)
+		return NF_DROP;
+
 	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
 		pf = PF_INET;
 	else
@@ -782,8 +805,8 @@
 print_error:
 	if (skb->dev != NULL) {
 		printk("[%s]", skb->dev->name);
-		if (has_bridge_parent(skb->dev))
-			printk("[%s]", bridge_parent(skb->dev)->name);
+		if (realoutdev)
+			printk("[%s]", realoutdev->name);
 	}
 	printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw,
 					      skb->data);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index c5bd631..8f10e09 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -232,9 +232,8 @@
 
 #ifdef CONFIG_SYSFS
 /* br_sysfs_if.c */
+extern struct sysfs_ops brport_sysfs_ops;
 extern int br_sysfs_addif(struct net_bridge_port *p);
-extern void br_sysfs_removeif(struct net_bridge_port *p);
-extern void br_sysfs_freeif(struct net_bridge_port *p);
 
 /* br_sysfs_br.c */
 extern int br_sysfs_addbr(struct net_device *dev);
@@ -243,8 +242,6 @@
 #else
 
 #define br_sysfs_addif(p)	(0)
-#define br_sysfs_removeif(p)	do { } while(0)
-#define br_sysfs_freeif(p)	kfree(p)
 #define br_sysfs_addbr(dev)	(0)
 #define br_sysfs_delbr(dev)	do { } while(0)
 #endif /* CONFIG_SYSFS */
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index d071f1c..296f6a4 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -133,29 +133,35 @@
 
 static const unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
 
-/* NO locks */
+/* NO locks, but rcu_read_lock (preempt_disabled)  */
 int br_stp_handle_bpdu(struct sk_buff *skb)
 {
-	struct net_bridge_port *p = skb->dev->br_port;
-	struct net_bridge *br = p->br;
+	struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
+	struct net_bridge *br;
 	unsigned char *buf;
 
+	if (!p)
+		goto err;
+
+	br = p->br;
+	spin_lock(&br->lock);
+
+	if (p->state == BR_STATE_DISABLED || !(br->dev->flags & IFF_UP))
+		goto out;
+
 	/* insert into forwarding database after filtering to avoid spoofing */
-	br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
+	br_fdb_update(br, p, eth_hdr(skb)->h_source);
+
+	if (!br->stp_enabled)
+		goto out;
 
 	/* need at least the 802 and STP headers */
 	if (!pskb_may_pull(skb, sizeof(header)+1) ||
 	    memcmp(skb->data, header, sizeof(header)))
-		goto err;
+		goto out;
 
 	buf = skb_pull(skb, sizeof(header));
 
-	spin_lock_bh(&br->lock);
-	if (p->state == BR_STATE_DISABLED 
-	    || !(br->dev->flags & IFF_UP)
-	    || !br->stp_enabled)
-		goto out;
-
 	if (buf[0] == BPDU_TYPE_CONFIG) {
 		struct br_config_bpdu bpdu;
 
@@ -201,7 +207,7 @@
 		br_received_tcn_bpdu(p);
 	}
  out:
-	spin_unlock_bh(&br->lock);
+	spin_unlock(&br->lock);
  err:
 	kfree_skb(skb);
 	return 0;
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 0ac0355..c51c9e4 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -195,23 +195,11 @@
 	return ret;
 }
 
-/* called from kobject_put when port ref count goes to zero. */
-static void brport_release(struct kobject *kobj)
-{
-	kfree(container_of(kobj, struct net_bridge_port, kobj));
-}
-
-static struct sysfs_ops brport_sysfs_ops = {
+struct sysfs_ops brport_sysfs_ops = {
 	.show = brport_show,
 	.store = brport_store,
 };
 
-static struct kobj_type brport_ktype = {
-	.sysfs_ops = &brport_sysfs_ops,
-	.release = brport_release,
-};
-
-
 /*
  * Add sysfs entries to ethernet device added to a bridge.
  * Creates a brport subdirectory with bridge attributes.
@@ -223,17 +211,6 @@
 	struct brport_attribute **a;
 	int err;
 
-	ASSERT_RTNL();
-
-	kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
-	p->kobj.ktype = &brport_ktype;
-	p->kobj.parent = &(p->dev->class_dev.kobj);
-	p->kobj.kset = NULL;
-
-	err = kobject_add(&p->kobj);
-	if(err)
-		goto out1;
-
 	err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, 
 				SYSFS_BRIDGE_PORT_LINK);
 	if (err)
@@ -245,28 +222,7 @@
 			goto out2;
 	}
 
-	err = sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name);
-	if (err)
-		goto out2;
-
-	kobject_uevent(&p->kobj, KOBJ_ADD);
-	return 0;
- out2:
-	kobject_del(&p->kobj);
- out1:
+	err= sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name);
+out2:
 	return err;
 }
-
-void br_sysfs_removeif(struct net_bridge_port *p)
-{
-	pr_debug("br_sysfs_removeif\n");
-	sysfs_remove_link(&p->br->ifobj, p->dev->name);
-	kobject_uevent(&p->kobj, KOBJ_REMOVE);
-	kobject_del(&p->kobj);
-}
-
-void br_sysfs_freeif(struct net_bridge_port *p)
-{
-	pr_debug("br_sysfs_freeif\n");
-	kobject_put(&p->kobj);
-}
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index ce617b3..802baf7 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -46,7 +46,7 @@
 #define PRINTR(format, args...) do { if (net_ratelimit()) \
                                 printk(format , ## args); } while (0)
 
-static unsigned int nlbufsiz = 4096;
+static unsigned int nlbufsiz = NLMSG_GOODSIZE;
 module_param(nlbufsiz, uint, 0600);
 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) "
                            "(defaults to 4096)");
@@ -98,12 +98,14 @@
 static struct sk_buff *ulog_alloc_skb(unsigned int size)
 {
 	struct sk_buff *skb;
+	unsigned int n;
 
-	skb = alloc_skb(nlbufsiz, GFP_ATOMIC);
+	n = max(size, nlbufsiz);
+	skb = alloc_skb(n, GFP_ATOMIC);
 	if (!skb) {
 		PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer "
-		       "of size %ub!\n", nlbufsiz);
-		if (size < nlbufsiz) {
+		       "of size %ub!\n", n);
+		if (n > size) {
 			/* try to allocate only as much as we need for
 			 * current packet */
 			skb = alloc_skb(size, GFP_ATOMIC);
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 00729b3..cbd4020 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -934,6 +934,13 @@
 		BUGPRINT("Entries_size never zero\n");
 		return -EINVAL;
 	}
+	/* overflow check */
+	if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
+			SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
+		return -ENOMEM;
+	if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
+		return -ENOMEM;
+
 	countersize = COUNTER_OFFSET(tmp.nentries) * 
 					(highest_possible_processor_id()+1);
 	newinfo = (struct ebt_table_info *)
diff --git a/net/core/datagram.c b/net/core/datagram.c
index f8d322e..b8ce6bf 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -247,49 +247,74 @@
 int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
 			    struct iovec *to, int len)
 {
-	int i, err, fraglen, end = 0;
-	struct sk_buff *next = skb_shinfo(skb)->frag_list;
+	int start = skb_headlen(skb);
+	int i, copy = start - offset;
 
-	if (!len)
-		return 0;
+	/* Copy header. */
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		if (memcpy_toiovec(to, skb->data + offset, copy))
+			goto fault;
+		if ((len -= copy) == 0)
+			return 0;
+		offset += copy;
+	}
 
-next_skb:
-	fraglen = skb_headlen(skb);
-	i = -1;
+	/* Copy paged appendix. Hmm... why does this look so complicated? */
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
 
-	while (1) {
-		int start = end;
+		BUG_TRAP(start <= offset + len);
 
-		if ((end += fraglen) > offset) {
-			int copy = end - offset, o = offset - start;
+		end = start + skb_shinfo(skb)->frags[i].size;
+		if ((copy = end - offset) > 0) {
+			int err;
+			u8  *vaddr;
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			struct page *page = frag->page;
 
 			if (copy > len)
 				copy = len;
-			if (i == -1)
-				err = memcpy_toiovec(to, skb->data + o, copy);
-			else {
-				skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-				struct page *page = frag->page;
-				void *p = kmap(page) + frag->page_offset + o;
-				err = memcpy_toiovec(to, p, copy);
-				kunmap(page);
-			}
+			vaddr = kmap(page);
+			err = memcpy_toiovec(to, vaddr + frag->page_offset +
+					     offset - start, copy);
+			kunmap(page);
 			if (err)
 				goto fault;
 			if (!(len -= copy))
 				return 0;
 			offset += copy;
 		}
-		if (++i >= skb_shinfo(skb)->nr_frags)
-			break;
-		fraglen = skb_shinfo(skb)->frags[i].size;
+		start = end;
 	}
-	if (next) {
-		skb = next;
-		BUG_ON(skb_shinfo(skb)->frag_list);
-		next = skb->next;
-		goto next_skb;
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			if ((copy = end - offset) > 0) {
+				if (copy > len)
+					copy = len;
+				if (skb_copy_datagram_iovec(list,
+							    offset - start,
+							    to, copy))
+					goto fault;
+				if ((len -= copy) == 0)
+					return 0;
+				offset += copy;
+			}
+			start = end;
+		}
 	}
+	if (!len)
+		return 0;
+
 fault:
 	return -EFAULT;
 }
diff --git a/net/core/dev.c b/net/core/dev.c
index fd070a0..2afb0de 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2543,13 +2543,14 @@
 		case SIOCBONDENSLAVE:
 		case SIOCBONDRELEASE:
 		case SIOCBONDSETHWADDR:
-		case SIOCBONDSLAVEINFOQUERY:
-		case SIOCBONDINFOQUERY:
 		case SIOCBONDCHANGEACTIVE:
 		case SIOCBRADDIF:
 		case SIOCBRDELIF:
 			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
+			/* fall through */
+		case SIOCBONDSLAVEINFOQUERY:
+		case SIOCBONDINFOQUERY:
 			dev_load(ifr.ifr_name);
 			rtnl_lock();
 			ret = dev_ifsioc(&ifr, cmd);
@@ -3236,7 +3237,7 @@
 	 *	Initialise the packet receive queues.
 	 */
 
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_cpu(i) {
 		struct softnet_data *queue;
 
 		queue = &per_cpu(softnet_data, i);
diff --git a/net/core/filter.c b/net/core/filter.c
index 9540946..93fbd01 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -64,7 +64,7 @@
 }
 
 /**
- *	sk_run_filter	- 	run a filter on a socket
+ *	sk_run_filter - run a filter on a socket
  *	@skb: buffer to run the filter on
  *	@filter: filter to apply
  *	@flen: length of filter
@@ -78,8 +78,8 @@
 {
 	struct sock_filter *fentry;	/* We walk down these */
 	void *ptr;
-	u32 A = 0;	   		/* Accumulator */
-	u32 X = 0;   			/* Index Register */
+	u32 A = 0;			/* Accumulator */
+	u32 X = 0;			/* Index Register */
 	u32 mem[BPF_MEMWORDS];		/* Scratch Memory Store */
 	u32 tmp;
 	int k;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 3827f88..da16f8f 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1860,13 +1860,14 @@
 	 */
 	mod_cur_headers(pkt_dev);
 
-	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
+	datalen = (odev->hard_header_len + 16) & ~0xf;
+	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen, GFP_ATOMIC);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
 	}
 
-	skb_reserve(skb, 16);
+	skb_reserve(skb, datalen);
 
 	/*  Reserve for ethernet and IP header  */
 	eth = (__u8 *) skb_push(skb, 14);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 8700379..eca2976 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -455,7 +455,7 @@
 	if (!skb)
 		return;
 
-	if (rtnetlink_fill_ifinfo(skb, dev, type, current->pid, 0, change, 0) < 0) {
+	if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change, 0) < 0) {
 		kfree_skb(skb);
 		return;
 	}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index d0732e9..6766f11 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -135,13 +135,15 @@
 struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
 			    int fclone)
 {
+	kmem_cache_t *cache;
 	struct skb_shared_info *shinfo;
 	struct sk_buff *skb;
 	u8 *data;
 
+	cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
+
 	/* Get the HEAD */
-	skb = kmem_cache_alloc(fclone ? skbuff_fclone_cache : skbuff_head_cache,
-				gfp_mask & ~__GFP_DMA);
+	skb = kmem_cache_alloc(cache, gfp_mask & ~__GFP_DMA);
 	if (!skb)
 		goto out;
 
@@ -180,7 +182,7 @@
 out:
 	return skb;
 nodata:
-	kmem_cache_free(skbuff_head_cache, skb);
+	kmem_cache_free(cache, skb);
 	skb = NULL;
 	goto out;
 }
diff --git a/net/core/utils.c b/net/core/utils.c
index ac1d1fc..fdc4f38 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -121,7 +121,7 @@
 {
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_cpu(i) {
 		struct nrnd_state *state = &per_cpu(net_rand_state,i);
 		__net_srandom(state, i+jiffies);
 	}
@@ -133,7 +133,7 @@
 	unsigned long seed[NR_CPUS];
 
 	get_random_bytes(seed, sizeof(seed));
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_cpu(i) {
 		struct nrnd_state *state = &per_cpu(net_rand_state,i);
 		__net_srandom(state, seed[i]);
 	}
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index d2b5933..add3cae 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -15,7 +15,6 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
-#include <asm/bug.h>
 #include <asm/div64.h>
 
 #include "tfrc.h"
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 00f9832..dc0487b 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -119,7 +119,8 @@
 	if (err != 0)
 		goto failure;
 
-	err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
+	err = ip_route_newports(&rt, IPPROTO_DCCP, inet->sport, inet->dport,
+	                        sk);
 	if (err != 0)
 		goto failure;
 
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index df07425..80c4d04 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -468,6 +468,7 @@
 done:
         if (opt && opt != np->opt)
 		sock_kfree_s(sk, opt, opt->tot_len);
+	dst_release(dst);
 	return err;
 }
 
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 7a12180..960aa78 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -350,6 +350,7 @@
 	u8 src[ETH_ALEN];
 	struct ieee80211_crypt_data *crypt = NULL;
 	int keyidx = 0;
+	int can_be_decrypted = 0;
 
 	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	stats = &ieee->stats;
@@ -410,12 +411,23 @@
 		return 1;
 	}
 
-	if (is_multicast_ether_addr(hdr->addr1)
-	    ? ieee->host_mc_decrypt : ieee->host_decrypt) {
+	can_be_decrypted = (is_multicast_ether_addr(hdr->addr1) ||
+			    is_broadcast_ether_addr(hdr->addr2)) ?
+	    ieee->host_mc_decrypt : ieee->host_decrypt;
+
+	if (can_be_decrypted) {
 		int idx = 0;
-		if (skb->len >= hdrlen + 3)
+		if (skb->len >= hdrlen + 3) {
+			/* Top two-bits of byte 3 are the key index */
 			idx = skb->data[hdrlen + 3] >> 6;
+		}
+
+		/* ieee->crypt[] is WEP_KEY (4) in length.  Given that idx
+		 * is only allowed 2-bits of storage, no value of idx can
+		 * be provided via above code that would result in idx
+		 * being out of range */
 		crypt = ieee->crypt[idx];
+
 #ifdef NOT_YET
 		sta = NULL;
 
@@ -553,7 +565,7 @@
 
 	/* skb: hdr + (possibly fragmented, possibly encrypted) payload */
 
-	if (ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+	if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted &&
 	    (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
 		goto rx_dropped;
 
@@ -617,7 +629,7 @@
 
 	/* skb: hdr + (possible reassembled) full MSDU payload; possibly still
 	 * encrypted/authenticated */
-	if (ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+	if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted &&
 	    ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
 		goto rx_dropped;
 
@@ -1439,7 +1451,7 @@
 		break;
 
 	case IEEE80211_STYPE_PROBE_REQ:
-		IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+		IEEE80211_DEBUG_MGMT("received auth (%d)\n",
 				     WLAN_FC_GET_STYPE(le16_to_cpu
 						       (header->frame_ctl)));
 
@@ -1473,7 +1485,7 @@
 		break;
 	case IEEE80211_STYPE_AUTH:
 
-		IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+		IEEE80211_DEBUG_MGMT("received auth (%d)\n",
 				     WLAN_FC_GET_STYPE(le16_to_cpu
 						       (header->frame_ctl)));
 
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 23e1630..f87c6b8 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -232,15 +232,18 @@
 	return start;
 }
 
+#define SCAN_ITEM_SIZE 128
+
 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
 			  struct iw_request_info *info,
 			  union iwreq_data *wrqu, char *extra)
 {
 	struct ieee80211_network *network;
 	unsigned long flags;
+	int err = 0;
 
 	char *ev = extra;
-	char *stop = ev + IW_SCAN_MAX_DATA;
+	char *stop = ev + wrqu->data.length;
 	int i = 0;
 
 	IEEE80211_DEBUG_WX("Getting scan\n");
@@ -249,6 +252,11 @@
 
 	list_for_each_entry(network, &ieee->network_list, list) {
 		i++;
+		if (stop - ev < SCAN_ITEM_SIZE) {
+			err = -E2BIG;
+			break;
+		}
+
 		if (ieee->scan_age == 0 ||
 		    time_after(network->last_scanned + ieee->scan_age, jiffies))
 			ev = ipw2100_translate_scan(ieee, ev, stop, network);
@@ -270,7 +278,7 @@
 
 	IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
 
-	return 0;
+	return err;
 }
 
 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 95b9d81..3ffa60d 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1135,7 +1135,7 @@
 
 	if (!skb)
 		netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS);
-	else if (inet_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) {
+	else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
 		kfree_skb(skb);
 		netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL);
 	} else {
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index ef4724d..0f4145b 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1045,7 +1045,7 @@
 	}
 
 	nl->nlmsg_flags = NLM_F_REQUEST;
-	nl->nlmsg_pid = current->pid;
+	nl->nlmsg_pid = 0;
 	nl->nlmsg_seq = 0;
 	nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm));
 	if (cmd == SIOCDELRT) {
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 105039e..e7bbff4 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -192,7 +192,7 @@
 int sysctl_icmp_echo_ignore_broadcasts = 1;
 
 /* Control parameter - ignore bogus broadcast responses? */
-int sysctl_icmp_ignore_bogus_error_responses;
+int sysctl_icmp_ignore_bogus_error_responses = 1;
 
 /*
  * 	Configurable global rate limit.
@@ -385,7 +385,7 @@
 	u32 daddr;
 
 	if (ip_options_echo(&icmp_param->replyopts, skb))
-		goto out;
+		return;
 
 	if (icmp_xmit_lock())
 		return;
@@ -416,7 +416,6 @@
 	ip_rt_put(rt);
 out_unlock:
 	icmp_xmit_unlock();
-out:;
 }
 
 
@@ -525,7 +524,7 @@
 					  iph->tos;
 
 	if (ip_options_echo(&icmp_param.replyopts, skb_in))
-		goto ende;
+		goto out_unlock;
 
 
 	/*
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 192092b..64ce52b 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -233,7 +233,18 @@
 	case IGMPV3_MODE_IS_EXCLUDE:
 		if (gdeleted || sdeleted)
 			return 0;
-		return !(pmc->gsquery && !psf->sf_gsresp);
+		if (!(pmc->gsquery && !psf->sf_gsresp)) {
+			if (pmc->sfmode == MCAST_INCLUDE)
+				return 1;
+			/* don't include if this source is excluded
+			 * in all filters
+			 */
+			if (psf->sf_count[MCAST_INCLUDE])
+				return type == IGMPV3_MODE_IS_INCLUDE;
+			return pmc->sfcount[MCAST_EXCLUDE] ==
+				psf->sf_count[MCAST_EXCLUDE];
+		}
+		return 0;
 	case IGMPV3_CHANGE_TO_INCLUDE:
 		if (gdeleted || sdeleted)
 			return 0;
@@ -385,7 +396,7 @@
 	struct igmpv3_report *pih;
 	struct igmpv3_grec *pgr = NULL;
 	struct ip_sf_list *psf, *psf_next, *psf_prev, **psf_list;
-	int scount, first, isquery, truncate;
+	int scount, stotal, first, isquery, truncate;
 
 	if (pmc->multiaddr == IGMP_ALL_HOSTS)
 		return skb;
@@ -395,25 +406,13 @@
 	truncate = type == IGMPV3_MODE_IS_EXCLUDE ||
 		    type == IGMPV3_CHANGE_TO_EXCLUDE;
 
+	stotal = scount = 0;
+
 	psf_list = sdeleted ? &pmc->tomb : &pmc->sources;
 
-	if (!*psf_list) {
-		if (type == IGMPV3_ALLOW_NEW_SOURCES ||
-		    type == IGMPV3_BLOCK_OLD_SOURCES)
-			return skb;
-		if (pmc->crcount || isquery) {
-			/* make sure we have room for group header and at
-			 * least one source.
-			 */
-			if (skb && AVAILABLE(skb) < sizeof(struct igmpv3_grec)+
-			    sizeof(__u32)) {
-				igmpv3_sendpack(skb);
-				skb = NULL; /* add_grhead will get a new one */
-			}
-			skb = add_grhead(skb, pmc, type, &pgr);
-		}
-		return skb;
-	}
+	if (!*psf_list)
+		goto empty_source;
+
 	pih = skb ? (struct igmpv3_report *)skb->h.igmph : NULL;
 
 	/* EX and TO_EX get a fresh packet, if needed */
@@ -426,7 +425,6 @@
 		}
 	}
 	first = 1;
-	scount = 0;
 	psf_prev = NULL;
 	for (psf=*psf_list; psf; psf=psf_next) {
 		u32 *psrc;
@@ -460,7 +458,7 @@
 		}
 		psrc = (u32 *)skb_put(skb, sizeof(u32));
 		*psrc = psf->sf_inaddr;
-		scount++;
+		scount++; stotal++;
 		if ((type == IGMPV3_ALLOW_NEW_SOURCES ||
 		     type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) {
 			psf->sf_crcount--;
@@ -475,6 +473,21 @@
 		}
 		psf_prev = psf;
 	}
+
+empty_source:
+	if (!stotal) {
+		if (type == IGMPV3_ALLOW_NEW_SOURCES ||
+		    type == IGMPV3_BLOCK_OLD_SOURCES)
+			return skb;
+		if (pmc->crcount || isquery) {
+			/* make sure we have room for group header */
+			if (skb && AVAILABLE(skb)<sizeof(struct igmpv3_grec)) {
+				igmpv3_sendpack(skb);
+				skb = NULL; /* add_grhead will get a new one */
+			}
+			skb = add_grhead(skb, pmc, type, &pgr);
+		}
+	}
 	if (pgr)
 		pgr->grec_nsrcs = htons(scount);
 
@@ -557,11 +570,11 @@
 			skb = add_grec(skb, pmc, dtype, 1, 1);
 		}
 		if (pmc->crcount) {
-			pmc->crcount--;
 			if (pmc->sfmode == MCAST_EXCLUDE) {
 				type = IGMPV3_CHANGE_TO_INCLUDE;
 				skb = add_grec(skb, pmc, type, 1, 0);
 			}
+			pmc->crcount--;
 			if (pmc->crcount == 0) {
 				igmpv3_clear_zeros(&pmc->tomb);
 				igmpv3_clear_zeros(&pmc->sources);
@@ -594,12 +607,12 @@
 
 		/* filter mode changes */
 		if (pmc->crcount) {
-			pmc->crcount--;
 			if (pmc->sfmode == MCAST_EXCLUDE)
 				type = IGMPV3_CHANGE_TO_EXCLUDE;
 			else
 				type = IGMPV3_CHANGE_TO_INCLUDE;
 			skb = add_grec(skb, pmc, type, 0, 0);
+			pmc->crcount--;
 		}
 		spin_unlock_bh(&pmc->lock);
 	}
@@ -735,7 +748,8 @@
 	ip_ma_put(im);
 }
 
-static void igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+/* mark EXCLUDE-mode sources */
+static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
 {
 	struct ip_sf_list *psf;
 	int i, scount;
@@ -744,6 +758,37 @@
 	for (psf=pmc->sources; psf; psf=psf->sf_next) {
 		if (scount == nsrcs)
 			break;
+		for (i=0; i<nsrcs; i++) {
+			/* skip inactive filters */
+			if (pmc->sfcount[MCAST_INCLUDE] ||
+			    pmc->sfcount[MCAST_EXCLUDE] !=
+			    psf->sf_count[MCAST_EXCLUDE])
+				continue;
+			if (srcs[i] == psf->sf_inaddr) {
+				scount++;
+				break;
+			}
+		}
+	}
+	pmc->gsquery = 0;
+	if (scount == nsrcs)	/* all sources excluded */
+		return 0;
+	return 1;
+}
+
+static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+{
+	struct ip_sf_list *psf;
+	int i, scount;
+
+	if (pmc->sfmode == MCAST_EXCLUDE)
+		return igmp_xmarksources(pmc, nsrcs, srcs);
+
+	/* mark INCLUDE-mode sources */
+	scount = 0;
+	for (psf=pmc->sources; psf; psf=psf->sf_next) {
+		if (scount == nsrcs)
+			break;
 		for (i=0; i<nsrcs; i++)
 			if (srcs[i] == psf->sf_inaddr) {
 				psf->sf_gsresp = 1;
@@ -751,6 +796,12 @@
 				break;
 			}
 	}
+	if (!scount) {
+		pmc->gsquery = 0;
+		return 0;
+	}
+	pmc->gsquery = 1;
+	return 1;
 }
 
 static void igmp_heard_report(struct in_device *in_dev, u32 group)
@@ -845,6 +896,8 @@
 	 */
 	read_lock(&in_dev->mc_list_lock);
 	for (im=in_dev->mc_list; im!=NULL; im=im->next) {
+		int changed;
+
 		if (group && group != im->multiaddr)
 			continue;
 		if (im->multiaddr == IGMP_ALL_HOSTS)
@@ -854,10 +907,11 @@
 			im->gsquery = im->gsquery && mark;
 		else
 			im->gsquery = mark;
-		if (im->gsquery)
-			igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
+		changed = !im->gsquery ||
+		    	igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
 		spin_unlock_bh(&im->lock);
-		igmp_mod_timer(im, max_delay);
+		if (changed)
+			igmp_mod_timer(im, max_delay);
 	}
 	read_unlock(&in_dev->mc_list_lock);
 }
@@ -916,7 +970,7 @@
 	case IGMP_MTRACE_RESP:
 		break;
 	default:
-		NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type);
+		break;
 	}
 
 drop:
@@ -1510,7 +1564,7 @@
 
 static int sf_setstate(struct ip_mc_list *pmc)
 {
-	struct ip_sf_list *psf;
+	struct ip_sf_list *psf, *dpsf;
 	int mca_xcount = pmc->sfcount[MCAST_EXCLUDE];
 	int qrv = pmc->interface->mr_qrv;
 	int new_in, rv;
@@ -1522,8 +1576,46 @@
 				!psf->sf_count[MCAST_INCLUDE];
 		} else
 			new_in = psf->sf_count[MCAST_INCLUDE] != 0;
-		if (new_in != psf->sf_oldin) {
-			psf->sf_crcount = qrv;
+		if (new_in) {
+			if (!psf->sf_oldin) {
+				struct ip_sf_list *prev = NULL;
+
+				for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next) {
+					if (dpsf->sf_inaddr == psf->sf_inaddr)
+						break;
+					prev = dpsf;
+				}
+				if (dpsf) {
+					if (prev)
+						prev->sf_next = dpsf->sf_next;
+					else
+						pmc->tomb = dpsf->sf_next;
+					kfree(dpsf);
+				}
+				psf->sf_crcount = qrv;
+				rv++;
+			}
+		} else if (psf->sf_oldin) {
+
+			psf->sf_crcount = 0;
+			/*
+			 * add or update "delete" records if an active filter
+			 * is now inactive
+			 */
+			for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next)
+				if (dpsf->sf_inaddr == psf->sf_inaddr)
+					break;
+			if (!dpsf) {
+				dpsf = (struct ip_sf_list *)
+					kmalloc(sizeof(*dpsf), GFP_ATOMIC);
+				if (!dpsf)
+					continue;
+				*dpsf = *psf;
+				/* pmc->lock held by callers */
+				dpsf->sf_next = pmc->tomb;
+				pmc->tomb = dpsf;
+			}
+			dpsf->sf_crcount = qrv;
 			rv++;
 		}
 	}
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
index d34a9fa..342d0b9 100644
--- a/net/ipv4/multipath_wrandom.c
+++ b/net/ipv4/multipath_wrandom.c
@@ -228,7 +228,7 @@
 	struct multipath_dest *d, *target_dest = NULL;
 
 	/* store the weight information for a certain route */
-	spin_lock(&state[state_idx].lock);
+	spin_lock_bh(&state[state_idx].lock);
 
 	/* find state entry for gateway or add one if necessary */
 	list_for_each_entry_rcu(r, &state[state_idx].head, list) {
@@ -276,7 +276,7 @@
 	 * we are finished
 	 */
 
-	spin_unlock(&state[state_idx].lock);
+	spin_unlock_bh(&state[state_idx].lock);
 }
 
 static void __multipath_free(struct rcu_head *head)
@@ -302,7 +302,7 @@
 	for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
 		struct multipath_route *r;
 
-		spin_lock(&state[i].lock);
+		spin_lock_bh(&state[i].lock);
 		list_for_each_entry_rcu(r, &state[i].head, list) {
 			struct multipath_dest *d;
 			list_for_each_entry_rcu(d, &r->dests, list) {
@@ -315,7 +315,7 @@
 				 __multipath_free);
 		}
 
-		spin_unlock(&state[i].lock);
+		spin_unlock_bh(&state[i].lock);
 	}
 }
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index afe3d8f..dd1048b 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -807,6 +807,13 @@
 	if (len != sizeof(tmp) + tmp.size)
 		return -ENOPROTOOPT;
 
+	/* overflow check */
+	if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+			SMP_CACHE_BYTES)
+		return -ENOMEM;
+	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+		return -ENOMEM;
+
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
 		return -ENOMEM;
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index c9ebbe0..e0b5926 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1216,7 +1216,7 @@
 
 	b = skb->tail;
 
-	type |= NFNL_SUBSYS_CTNETLINK << 8;
+	type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
 	nlh   = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
 	nfmsg = NLMSG_DATA(nlh);
 
@@ -1567,6 +1567,7 @@
 };
 
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
 
 static int __init ctnetlink_init(void)
 {
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index d3c5a37..4ba4463 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -71,6 +71,7 @@
 
 		exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
 		exp->mask.src.ip = 0xffffffff;
+		exp->mask.src.u.udp.port = 0;
 		exp->mask.dst.ip = 0xffffffff;
 		exp->mask.dst.u.udp.port = 0xffff;
 		exp->mask.dst.protonum = 0xff;
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index ad438fb..92c5499 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -209,8 +209,8 @@
 	    && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
 		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 
-		if (ct->tuplehash[dir].tuple.src.ip !=
-		    ct->tuplehash[!dir].tuple.dst.ip) {
+		if (ct->tuplehash[dir].tuple.dst.ip !=
+		    ct->tuplehash[!dir].tuple.src.ip) {
 			dst_release((*pskb)->dst);
 			(*pskb)->dst = NULL;
 		}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 2371b20..16f47c6 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -921,6 +921,13 @@
 	if (len != sizeof(tmp) + tmp.size)
 		return -ENOPROTOOPT;
 
+	/* overflow check */
+	if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+			SMP_CACHE_BYTES)
+		return -ENOMEM;
+	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+		return -ENOMEM;
+
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
 		return -ENOMEM;
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 641dbc4..180a9ea 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -35,6 +35,10 @@
  * each nlgroup you are using, so the total kernel memory usage increases
  * by that factor.
  *
+ * Actually you should use nlbufsiz a bit smaller than PAGE_SIZE, since
+ * nlbufsiz is used with alloc_skb, which adds another
+ * sizeof(struct skb_shared_info).  Use NLMSG_GOODSIZE instead.
+ *
  * flushtimeout:
  *   Specify, after how many hundredths of a second the queue should be
  *   flushed even if it is not full yet.
@@ -76,7 +80,7 @@
 
 #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
 
-static unsigned int nlbufsiz = 4096;
+static unsigned int nlbufsiz = NLMSG_GOODSIZE;
 module_param(nlbufsiz, uint, 0400);
 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
 
@@ -143,22 +147,26 @@
 static struct sk_buff *ulog_alloc_skb(unsigned int size)
 {
 	struct sk_buff *skb;
+	unsigned int n;
 
 	/* alloc skb which should be big enough for a whole
 	 * multipart message. WARNING: has to be <= 131000
 	 * due to slab allocator restrictions */
 
-	skb = alloc_skb(nlbufsiz, GFP_ATOMIC);
+	n = max(size, nlbufsiz);
+	skb = alloc_skb(n, GFP_ATOMIC);
 	if (!skb) {
-		PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n",
-			nlbufsiz);
+		PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", n);
 
-		/* try to allocate only as much as we need for 
-		 * current packet */
+		if (n > size) {
+			/* try to allocate only as much as we need for 
+			 * current packet */
 
-		skb = alloc_skb(size, GFP_ATOMIC);
-		if (!skb)
-			PRINTR("ipt_ULOG: can't even allocate %ub\n", size);
+			skb = alloc_skb(size, GFP_ATOMIC);
+			if (!skb)
+				PRINTR("ipt_ULOG: can't even allocate %ub\n",
+				       size);
+		}
 	}
 
 	return skb;
diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c
index 18ca825..5a7a265 100644
--- a/net/ipv4/netfilter/ipt_policy.c
+++ b/net/ipv4/netfilter/ipt_policy.c
@@ -26,10 +26,13 @@
 static inline int
 match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
 {
-#define MATCH(x,y)	(!e->match.x || ((e->x == (y)) ^ e->invert.x))
+#define MATCH_ADDR(x,y,z)	(!e->match.x ||				     \
+		                 ((e->x.a4.s_addr == (e->y.a4.s_addr & (z))) \
+				  ^ e->invert.x))
+#define MATCH(x,y)		(!e->match.x || ((e->x == (y)) ^ e->invert.x))
 
-	return MATCH(saddr, x->props.saddr.a4 & e->smask) &&
-	       MATCH(daddr, x->id.daddr.a4 & e->dmask) &&
+	return MATCH_ADDR(saddr, smask, x->props.saddr.a4) &&
+	       MATCH_ADDR(daddr, dmask, x->id.daddr.a4) &&
 	       MATCH(proto, x->id.proto) &&
 	       MATCH(mode, x->props.mode) &&
 	       MATCH(spi, x->id.spi) &&
@@ -89,7 +92,7 @@
 			return 0;
 	}
 
-	return strict ? 1 : 0;
+	return strict ? i == info->len : 0;
 }
 
 static int match(const struct sk_buff *skb,
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 39d49dc..1b167c4b 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -49,7 +49,7 @@
 	int res = 0;
 	int cpu;
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++)
+	for_each_cpu(cpu)
 		res += proto->stats[cpu].inuse;
 
 	return res;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 165a4d8..f29a12d 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -40,12 +40,12 @@
  */
  
 #include <linux/config.h> 
+#include <linux/types.h>
 #include <asm/atomic.h>
 #include <asm/byteorder.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
-#include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f2e82af..d82c242 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -241,7 +241,8 @@
 static unsigned int		rt_hash_rnd;
 
 static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
-#define RT_CACHE_STAT_INC(field) (__get_cpu_var(rt_cache_stat).field++)
+#define RT_CACHE_STAT_INC(field) \
+	(per_cpu(rt_cache_stat, raw_smp_processor_id()).field++)
 
 static int rt_intern_hash(unsigned hash, struct rtable *rth,
 				struct rtable **res);
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 3284cfb..128de4d 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -230,7 +230,6 @@
 			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
 				tp->snd_cwnd++;
 			tp->snd_cwnd_cnt = 0;
-			ca->ccount++;
 		}
 	}
 }
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index a97ed54..e9a54ae 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -456,7 +456,8 @@
 
 		tp->rcvq_space.space = space;
 
-		if (sysctl_tcp_moderate_rcvbuf) {
+		if (sysctl_tcp_moderate_rcvbuf &&
+		    !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) {
 			int new_clamp = space;
 
 			/* Receive space grows, normalize in order to
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 6ea3539..233bdf2 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -236,7 +236,7 @@
 	if (err)
 		goto failure;
 
-	err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
+	err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk);
 	if (err)
 		goto failure;
 
@@ -1845,7 +1845,6 @@
 }
 
 EXPORT_SYMBOL(ipv4_specific);
-EXPORT_SYMBOL(inet_bind_bucket_create);
 EXPORT_SYMBOL(tcp_hashinfo);
 EXPORT_SYMBOL(tcp_prot);
 EXPORT_SYMBOL(tcp_unhash);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 42196ba..45f7ae5 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -8,7 +8,6 @@
  * 	
  */
 
-#include <asm/bug.h>
 #include <linux/compiler.h>
 #include <linux/config.h>
 #include <linux/inetdevice.h>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d328d59..b7d8822 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2165,6 +2165,9 @@
 					dev->name);
 				break;
 			}
+
+			if (idev)
+				idev->if_flags |= IF_READY;
 		} else {
 			if (!netif_carrier_ok(dev)) {
 				/* device is still not ready. */
@@ -3321,9 +3324,7 @@
 
 	switch (event) {
 	case RTM_NEWADDR:
-		dst_hold(&ifp->rt->u.dst);
-		if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL))
-			dst_release(&ifp->rt->u.dst);
+		ip6_ins_rt(ifp->rt, NULL, NULL, NULL);
 		if (ifp->idev->cnf.forwarding)
 			addrconf_join_anycast(ifp);
 		break;
@@ -3334,8 +3335,6 @@
 		dst_hold(&ifp->rt->u.dst);
 		if (ip6_del_rt(ifp->rt, NULL, NULL, NULL))
 			dst_free(&ifp->rt->u.dst);
-		else
-			dst_release(&ifp->rt->u.dst);
 		break;
 	}
 }
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 064ffab..6c9711a 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -369,12 +369,6 @@
 	struct sk_buff *skb;
 	struct ipv6_txoptions *opt;
 
-	/*
-	 *	Release destination entry
-	 */
-
-	sk_dst_reset(sk);
-
 	/* Release rx options */
 
 	if ((skb = xchg(&np->pktoptions, NULL)) != NULL)
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 6c05c79..807c021 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1252,8 +1252,7 @@
 		}
 	} else {
 		for (ma = idev->mc_list; ma; ma=ma->next) {
-			if (group_type != IPV6_ADDR_ANY &&
-			    !ipv6_addr_equal(group, &ma->mca_addr))
+			if (!ipv6_addr_equal(group, &ma->mca_addr))
 				continue;
 			spin_lock_bh(&ma->mca_lock);
 			if (ma->mca_flags & MAF_TIMER_RUNNING) {
@@ -1268,11 +1267,10 @@
 					ma->mca_flags &= ~MAF_GSQUERY;
 			}
 			if (!(ma->mca_flags & MAF_GSQUERY) ||
-			   mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs))
+			    mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs))
 				igmp6_group_queried(ma, max_delay);
 			spin_unlock_bh(&ma->mca_lock);
-			if (group_type != IPV6_ADDR_ANY)
-				break;
+			break;
 		}
 	}
 	read_unlock_bh(&idev->lock);
@@ -1351,7 +1349,7 @@
 			 * in all filters
 			 */
 			if (psf->sf_count[MCAST_INCLUDE])
-				return 0;
+				return type == MLD2_MODE_IS_INCLUDE;
 			return pmc->mca_sfcount[MCAST_EXCLUDE] ==
 				psf->sf_count[MCAST_EXCLUDE];
 		}
@@ -1966,7 +1964,7 @@
 
 static int sf_setstate(struct ifmcaddr6 *pmc)
 {
-	struct ip6_sf_list *psf;
+	struct ip6_sf_list *psf, *dpsf;
 	int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE];
 	int qrv = pmc->idev->mc_qrv;
 	int new_in, rv;
@@ -1978,8 +1976,48 @@
 				!psf->sf_count[MCAST_INCLUDE];
 		} else
 			new_in = psf->sf_count[MCAST_INCLUDE] != 0;
-		if (new_in != psf->sf_oldin) {
-			psf->sf_crcount = qrv;
+		if (new_in) {
+			if (!psf->sf_oldin) {
+				struct ip6_sf_list *prev = NULL;
+
+				for (dpsf=pmc->mca_tomb; dpsf;
+				     dpsf=dpsf->sf_next) {
+					if (ipv6_addr_equal(&dpsf->sf_addr,
+					    &psf->sf_addr))
+						break;
+					prev = dpsf;
+				}
+				if (dpsf) {
+					if (prev)
+						prev->sf_next = dpsf->sf_next;
+					else
+						pmc->mca_tomb = dpsf->sf_next;
+					kfree(dpsf);
+				}
+				psf->sf_crcount = qrv;
+				rv++;
+			}
+		} else if (psf->sf_oldin) {
+			psf->sf_crcount = 0;
+			/*
+			 * add or update "delete" records if an active filter
+			 * is now inactive
+			 */
+			for (dpsf=pmc->mca_tomb; dpsf; dpsf=dpsf->sf_next)
+				if (ipv6_addr_equal(&dpsf->sf_addr,
+				    &psf->sf_addr))
+					break;
+			if (!dpsf) {
+				dpsf = (struct ip6_sf_list *)
+					kmalloc(sizeof(*dpsf), GFP_ATOMIC);
+				if (!dpsf)
+					continue;
+				*dpsf = *psf;
+				/* pmc->mca_lock held by callers */
+				dpsf->sf_next = pmc->mca_tomb;
+				pmc->mca_tomb = dpsf;
+			}
+			dpsf->sf_crcount = qrv;
 			rv++;
 		}
 	}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 847068f..74ff56c 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -978,6 +978,13 @@
 	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
 		return -EFAULT;
 
+	/* overflow check */
+	if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+			SMP_CACHE_BYTES)
+		return -ENOMEM;
+	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+		return -ENOMEM;
+
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
 		return -ENOMEM;
diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c
index afe1cc4..3d39ec9 100644
--- a/net/ipv6/netfilter/ip6t_policy.c
+++ b/net/ipv6/netfilter/ip6t_policy.c
@@ -26,8 +26,9 @@
 static inline int
 match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
 {
-#define MATCH_ADDR(x,y,z)	(!e->match.x || \
-				 ((ip6_masked_addrcmp((z), &e->x, &e->y)) == 0) ^ e->invert.x)
+#define MATCH_ADDR(x,y,z)	(!e->match.x ||				       \
+				 ((!ip6_masked_addrcmp(&e->x.a6, &e->y.a6, z)) \
+				  ^ e->invert.x))
 #define MATCH(x,y)		(!e->match.x || ((e->x == (y)) ^ e->invert.x))
 	
 	return MATCH_ADDR(saddr, smask, (struct in6_addr *)&x->props.saddr.a6) &&
@@ -91,7 +92,7 @@
 			return 0;
 	}
 
-	return strict ? 1 : 0;
+	return strict ? i == info->len : 0;
 }
 
 static int match(const struct sk_buff *skb,
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 50a13e7..4238b1e 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -38,7 +38,7 @@
 	int res = 0;
 	int cpu;
 
-	for (cpu=0; cpu<NR_CPUS; cpu++)
+	for_each_cpu(cpu)
 		res += proto->stats[cpu].inuse;
 
 	return res;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 66f1d12..ae20a0e 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -35,7 +35,6 @@
 #include <linux/skbuff.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
-#include <asm/bug.h>
 
 #include <net/ip.h>
 #include <net/sock.h>
@@ -804,10 +803,7 @@
 			err = rawv6_push_pending_frames(sk, &fl, rp);
 	}
 done:
-	ip6_dst_store(sk, dst,
-		      ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ?
-		      &np->daddr : NULL);
-
+	dst_release(dst);
 	release_sock(sk);
 out:	
 	fl6_sock_release(flowlabel);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 66d0400..ca9cf68 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -515,6 +515,7 @@
 done:
         if (opt && opt != np->opt)
 		sock_kfree_s(sk, opt, opt->tot_len);
+	dst_release(dst);
 	return err;
 }
 
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 69bd957..91cce8b 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -11,7 +11,6 @@
  * 
  */
 
-#include <asm/bug.h>
 #include <linux/compiler.h>
 #include <linux/config.h>
 #include <linux/netdevice.h>
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index 890bac0..e3debbd 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -343,12 +343,12 @@
 static void irda_device_setup(struct net_device *dev)
 {
         dev->hard_header_len = 0;
-        dev->addr_len        = 0;
+        dev->addr_len        = LAP_ALEN;
 
         dev->type            = ARPHRD_IRDA;
         dev->tx_queue_len    = 8; /* Window size + 1 s-frame */
 
-	memset(dev->broadcast, 0xff, 4);
+	memset(dev->broadcast, 0xff, LAP_ALEN);
 
 	dev->mtu = 2048;
 	dev->flags = IFF_NOARP;
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
index 07ec326..f65c7a8 100644
--- a/net/irda/irnet/irnet_irda.c
+++ b/net/irda/irnet/irnet_irda.c
@@ -696,7 +696,7 @@
 	{
 	  /* Yes !!! Get it.. */
 	  strlcpy(self->rname, discoveries[i].info, sizeof(self->rname));
-	  self->rname[NICKNAME_MAX_LEN + 1] = '\0';
+	  self->rname[sizeof(self->rname) - 1] = '\0';
 	  DEBUG(IRDA_SERV_INFO, "Device 0x%08x is in fact ``%s''.\n",
 		self->daddr, self->rname);
 	  kfree(discoveries);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 43f1ce7..ae86d23 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1620,6 +1620,7 @@
 		return -ENOBUFS;
 	hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
 	hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto);
+	hdr->sadb_msg_type = SADB_FLUSH;
 	hdr->sadb_msg_seq = c->seq;
 	hdr->sadb_msg_pid = c->pid;
 	hdr->sadb_msg_version = PF_KEY_V2;
@@ -2385,6 +2386,7 @@
 	if (!skb_out)
 		return -ENOBUFS;
 	hdr = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
+	hdr->sadb_msg_type = SADB_X_SPDFLUSH;
 	hdr->sadb_msg_seq = c->seq;
 	hdr->sadb_msg_pid = c->pid;
 	hdr->sadb_msg_version = PF_KEY_V2;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 99c0a0f..0e55012 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -102,8 +102,6 @@
 	help
 	  This option enables support for a netlink-based userspace interface
 
-endmenu
-
 config NETFILTER_XTABLES
 	tristate "Netfilter Xtables support (required for ip_tables)"
 	help
@@ -361,3 +359,5 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+endmenu
+
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 62bb509..0ce337a 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -188,7 +188,7 @@
 struct nf_conntrack_protocol *
 __nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol)
 {
-	if (unlikely(nf_ct_protos[l3proto] == NULL))
+	if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL))
 		return &nf_conntrack_generic_protocol;
 
 	return nf_ct_protos[l3proto][protocol];
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index ab0c920..6f210f3 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -657,8 +657,6 @@
 	/* FIXME should be configurable whether IPv4 and IPv6 FTP connections
 		 are tracked or not - YK */
 	for (i = 0; i < ports_c; i++) {
-		memset(&ftp[i], 0, sizeof(struct nf_conntrack_helper));
-
 		ftp[i][0].tuple.src.l3num = PF_INET;
 		ftp[i][1].tuple.src.l3num = PF_INET6;
 		for (j = 0; j < 2; j++) {
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 73ab16b..9ff3463 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1232,7 +1232,7 @@
 
 	b = skb->tail;
 
-	type |= NFNL_SUBSYS_CTNETLINK << 8;
+	type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
 	nlh   = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
 	nfmsg = NLMSG_DATA(nlh);
 
@@ -1589,6 +1589,7 @@
 };
 
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
 
 static int __init ctnetlink_init(void)
 {
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index e10512e..3b3c781 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -37,7 +37,7 @@
 #include "../bridge/br_private.h"
 #endif
 
-#define NFULNL_NLBUFSIZ_DEFAULT	4096
+#define NFULNL_NLBUFSIZ_DEFAULT	NLMSG_GOODSIZE
 #define NFULNL_TIMEOUT_DEFAULT 	100	/* every second */
 #define NFULNL_QTHRESH_DEFAULT 	100	/* 100 packets */
 
@@ -314,24 +314,28 @@
 					unsigned int pkt_size)
 {
 	struct sk_buff *skb;
+	unsigned int n;
 
 	UDEBUG("entered (%u, %u)\n", inst_size, pkt_size);
 
 	/* alloc skb which should be big enough for a whole multipart
 	 * message.  WARNING: has to be <= 128k due to slab restrictions */
 
-	skb = alloc_skb(inst_size, GFP_ATOMIC);
+	n = max(inst_size, pkt_size);
+	skb = alloc_skb(n, GFP_ATOMIC);
 	if (!skb) {
 		PRINTR("nfnetlink_log: can't alloc whole buffer (%u bytes)\n",
 			inst_size);
 
-		/* try to allocate only as much as we need for current
-		 * packet */
+		if (n > pkt_size) {
+			/* try to allocate only as much as we need for current
+			 * packet */
 
-		skb = alloc_skb(pkt_size, GFP_ATOMIC);
-		if (!skb)
-			PRINTR("nfnetlink_log: can't even alloc %u bytes\n",
-				pkt_size);
+			skb = alloc_skb(pkt_size, GFP_ATOMIC);
+			if (!skb)
+				PRINTR("nfnetlink_log: can't even alloc %u "
+				       "bytes\n", pkt_size);
+		}
 	}
 
 	return skb;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 18ed9c5..cac38b2 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -825,7 +825,8 @@
 	}
 
 	if (nfqa[NFQA_MARK-1])
-		skb->nfmark = ntohl(*(u_int32_t *)NFA_DATA(nfqa[NFQA_MARK-1]));
+		entry->skb->nfmark = ntohl(*(u_int32_t *)
+		                           NFA_DATA(nfqa[NFQA_MARK-1]));
 		
 	issue_verdict(entry, verdict);
 	instance_put(queue);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2101b45..6b9772d 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -702,7 +702,8 @@
  * 0: continue
  * 1: repeat lookup - reference dropped while waiting for socket memory.
  */
-int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo)
+int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
+		long timeo, struct sock *ssk)
 {
 	struct netlink_sock *nlk;
 
@@ -712,7 +713,7 @@
 	    test_bit(0, &nlk->state)) {
 		DECLARE_WAITQUEUE(wait, current);
 		if (!timeo) {
-			if (!nlk->pid)
+			if (!ssk || nlk_sk(ssk)->pid == 0)
 				netlink_overrun(sk);
 			sock_put(sk);
 			kfree_skb(skb);
@@ -797,7 +798,7 @@
 		kfree_skb(skb);
 		return PTR_ERR(sk);
 	}
-	err = netlink_attachskb(sk, skb, nonblock, timeo);
+	err = netlink_attachskb(sk, skb, nonblock, timeo, ssk);
 	if (err == 1)
 		goto retry;
 	if (err)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 4ae1538..43e7241 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -238,7 +238,7 @@
 					sizeof(struct nlattr *), GFP_KERNEL);
 		if (family->attrbuf == NULL) {
 			err = -ENOMEM;
-			goto errout;
+			goto errout_locked;
 		}
 	} else
 		family->attrbuf = NULL;
@@ -288,7 +288,7 @@
 	return -ENOENT;
 }
 
-static inline int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
+static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
 			       int *errp)
 {
 	struct genl_ops *ops;
@@ -375,7 +375,7 @@
 	do {
 		if (genl_trylock())
 			return;
-		netlink_run_queue(sk, &qlen, &genl_rcv_msg);
+		netlink_run_queue(sk, &qlen, genl_rcv_msg);
 		genl_unlock();
 	} while (qlen && genl_sock && genl_sock->sk_receive_queue.qlen);
 }
@@ -549,10 +549,8 @@
 	netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
 	genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID,
 					  genl_rcv, THIS_MODULE);
-	if (genl_sock == NULL) {
+	if (genl_sock == NULL)
 		panic("GENL: Cannot initialize generic netlink\n");
-		return -ENOMEM;
-	}
 
 	return 0;
 
@@ -560,7 +558,6 @@
 	genl_unregister_family(&genl_ctrl);
 errout:
 	panic("GENL: Cannot register controller: %d\n", err);
-	return err;
 }
 
 subsys_initcall(genl_init);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index ee93abc..9db7dbd 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -365,7 +365,7 @@
 	 */
 	 
 	err = -EMSGSIZE;
- 	if(len>dev->mtu+dev->hard_header_len)
+	if (len > dev->mtu + dev->hard_header_len)
 		goto out_unlock;
 
 	err = -ENOBUFS;
@@ -935,7 +935,7 @@
 	 *	Check legality
 	 */
 	 
-	if(addr_len!=sizeof(struct sockaddr))
+	if (addr_len != sizeof(struct sockaddr))
 		return -EINVAL;
 	strlcpy(name,uaddr->sa_data,sizeof(name));
 
@@ -1092,7 +1092,7 @@
 	 *	retries.
 	 */
 
-	if(skb==NULL)
+	if (skb == NULL)
 		goto out;
 
 	/*
@@ -1392,8 +1392,8 @@
 	if (level != SOL_PACKET)
 		return -ENOPROTOOPT;
 
-  	if (get_user(len,optlen))
-  		return -EFAULT;
+	if (get_user(len, optlen))
+		return -EFAULT;
 
 	if (len < 0)
 		return -EINVAL;
@@ -1419,9 +1419,9 @@
 		return -ENOPROTOOPT;
 	}
 
-  	if (put_user(len, optlen))
-  		return -EFAULT;
-  	return 0;
+	if (put_user(len, optlen))
+		return -EFAULT;
+	return 0;
 }
 
 
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 4aa6fc6..cb78b50 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -257,20 +257,26 @@
 	 */
 	sctp_bh_lock_sock(sk);
 
+	/* It is possible that the association could have moved to a different
+	 * socket if it is peeled off. If so, update the sk.
+	 */ 
+	if (sk != rcvr->sk) {
+		sctp_bh_lock_sock(rcvr->sk);
+		sctp_bh_unlock_sock(sk);
+		sk = rcvr->sk;
+	}
+
 	if (sock_owned_by_user(sk))
 		sk_add_backlog(sk, skb);
 	else
 		sctp_backlog_rcv(sk, skb);
 
-	/* Release the sock and any reference counts we took in the
-	 * lookup calls.
+	/* Release the sock and the sock ref we took in the lookup calls.
+	 * The asoc/ep ref will be released in sctp_backlog_rcv.
 	 */
 	sctp_bh_unlock_sock(sk);
-	if (asoc)
-		sctp_association_put(asoc);
-	else
-		sctp_endpoint_put(ep);
 	sock_put(sk);
+
 	return ret;
 
 discard_it:
@@ -296,12 +302,50 @@
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
-	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
+ 	struct sctp_inq *inqueue = NULL;
+ 	struct sctp_ep_common *rcvr = NULL;
 
-	sctp_inq_push(inqueue, chunk);
+ 	rcvr = chunk->rcvr;
+
+	BUG_TRAP(rcvr->sk == sk);
+
+ 	if (rcvr->dead) {
+ 		sctp_chunk_free(chunk);
+ 	} else {
+ 		inqueue = &chunk->rcvr->inqueue;
+ 		sctp_inq_push(inqueue, chunk);
+ 	}
+
+	/* Release the asoc/ep ref we took in the lookup calls in sctp_rcv. */ 
+ 	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
+ 		sctp_association_put(sctp_assoc(rcvr));
+ 	else
+ 		sctp_endpoint_put(sctp_ep(rcvr));
+  
         return 0;
 }
 
+void sctp_backlog_migrate(struct sctp_association *assoc, 
+			  struct sock *oldsk, struct sock *newsk)
+{
+	struct sk_buff *skb;
+	struct sctp_chunk *chunk;
+
+	skb = oldsk->sk_backlog.head;
+	oldsk->sk_backlog.head = oldsk->sk_backlog.tail = NULL;
+	while (skb != NULL) {
+		struct sk_buff *next = skb->next;
+
+		chunk = SCTP_INPUT_CB(skb)->chunk;
+		skb->next = NULL;
+		if (&assoc->base == chunk->rcvr)
+			sk_add_backlog(newsk, skb);
+		else
+			sk_add_backlog(oldsk, skb);
+		skb = next;
+	}
+}
+
 /* Handle icmp frag needed error. */
 void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
 			   struct sctp_transport *t, __u32 pmtu)
@@ -544,10 +588,16 @@
 	sctp_errhdr_t *err;
 
 	ch = (sctp_chunkhdr_t *) skb->data;
-	ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
 
 	/* Scan through all the chunks in the packet.  */
-	while (ch_end > (__u8 *)ch && ch_end < skb->tail) {
+	do {
+		/* Break out if chunk length is less then minimal. */
+		if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t))
+			break;
+
+		ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+		if (ch_end > skb->tail)
+			break;
 
 		/* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
 		 * receiver MUST silently discard the OOTB packet and take no
@@ -578,8 +628,7 @@
 		}
 
 		ch = (sctp_chunkhdr_t *) ch_end;
-	        ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
-	}
+	} while (ch_end < skb->tail);
 
 	return 0;
 
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 2d33922..297b895 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -73,8 +73,10 @@
 	/* If there is a packet which is currently being worked on,
 	 * free it as well.
 	 */
-	if (queue->in_progress)
+	if (queue->in_progress) {
 		sctp_chunk_free(queue->in_progress);
+		queue->in_progress = NULL;
+	}
 
 	if (queue->malloced) {
 		/* Dump the master memory segment.  */
diff --git a/net/sctp/output.c b/net/sctp/output.c
index a40991e..437cba7 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -608,7 +608,7 @@
 	 *    When a Fast Retransmit is being performed the sender SHOULD
 	 *    ignore the value of cwnd and SHOULD NOT delay retransmission.
 	 */
-	if (!chunk->fast_retransmit)
+	if (chunk->fast_retransmit <= 0)
 		if (transport->flight_size >= transport->cwnd) {
 			retval = SCTP_XMIT_RWND_FULL;
 			goto finish;
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index efb72fa..f148f95 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -406,7 +406,7 @@
 		 * chunks that are not yet acked should be added to the
 		 * retransmit queue.
 		 */
-		if ((fast_retransmit && chunk->fast_retransmit) ||
+		if ((fast_retransmit && (chunk->fast_retransmit > 0)) ||
 		   (!fast_retransmit && !chunk->tsn_gap_acked)) {
 			/* RFC 2960 6.2.1 Processing a Received SACK
 			 *
@@ -603,7 +603,8 @@
 			/* Mark the chunk as ineligible for fast retransmit 
 			 * after it is retransmitted.
 			 */
-			chunk->fast_retransmit = 0;
+			if (chunk->fast_retransmit > 0)
+				chunk->fast_retransmit = -1;
 
 			*start_timer = 1;
 			q->empty = 0;
@@ -621,7 +622,8 @@
 			list_for_each(lchunk1, lqueue) {
 				chunk1 = list_entry(lchunk1, struct sctp_chunk,
 						    transmitted_list);
-				chunk1->fast_retransmit = 0;
+				if (chunk1->fast_retransmit > 0)
+					chunk1->fast_retransmit = -1;
 			}
 		}
 	}
@@ -1562,11 +1564,11 @@
 		/*
 		 * M4) If any DATA chunk is found to have a
 		 * 'TSN.Missing.Report'
-		 * value larger than or equal to 4, mark that chunk for
+		 * value larger than or equal to 3, mark that chunk for
 		 * retransmission and start the fast retransmit procedure.
 		 */
 
-		if (chunk->tsn_missing_report >= 4) {
+		if (chunk->tsn_missing_report >= 3) {
 			chunk->fast_retransmit = 1;
 			do_fast_retransmit = 1;
 		}
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 6e4dc28..d47a52c 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -176,7 +176,7 @@
 
 static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	if (*pos > sctp_ep_hashsize)
+	if (*pos >= sctp_ep_hashsize)
 		return NULL;
 
 	if (*pos < 0)
@@ -185,8 +185,6 @@
 	if (*pos == 0)
 		seq_printf(seq, " ENDPT     SOCK   STY SST HBKT LPORT   UID INODE LADDRS\n");
 
-	++*pos;
-
 	return (void *)pos;
 }
 
@@ -198,11 +196,9 @@
 
 static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	if (*pos > sctp_ep_hashsize)
+	if (++*pos >= sctp_ep_hashsize)
 		return NULL;
 
-	++*pos;
-
 	return pos;
 }
 
@@ -214,19 +210,19 @@
 	struct sctp_ep_common *epb;
 	struct sctp_endpoint *ep;
 	struct sock *sk;
-	int    hash = *(int *)v;
+	int    hash = *(loff_t *)v;
 
-	if (hash > sctp_ep_hashsize)
+	if (hash >= sctp_ep_hashsize)
 		return -ENOMEM;
 
-	head = &sctp_ep_hashtable[hash-1];
+	head = &sctp_ep_hashtable[hash];
 	sctp_local_bh_disable();
 	read_lock(&head->lock);
 	for (epb = head->chain; epb; epb = epb->next) {
 		ep = sctp_ep(epb);
 		sk = epb->sk;
 		seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
-			   sctp_sk(sk)->type, sk->sk_state, hash-1,
+			   sctp_sk(sk)->type, sk->sk_state, hash,
 			   epb->bind_addr.port,
 			   sock_i_uid(sk), sock_i_ino(sk));
 
@@ -283,7 +279,7 @@
 
 static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	if (*pos > sctp_assoc_hashsize)
+	if (*pos >= sctp_assoc_hashsize)
 		return NULL;
 
 	if (*pos < 0)
@@ -293,8 +289,6 @@
 		seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
 				"RPORT LADDRS <-> RADDRS\n");
 
-	++*pos;
-
 	return (void *)pos;
 }
 
@@ -306,11 +300,9 @@
 
 static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	if (*pos > sctp_assoc_hashsize)
+	if (++*pos >= sctp_assoc_hashsize)
 		return NULL;
 
-	++*pos;
-
 	return pos;
 }
 
@@ -321,12 +313,12 @@
 	struct sctp_ep_common *epb;
 	struct sctp_association *assoc;
 	struct sock *sk;
-	int    hash = *(int *)v;
+	int    hash = *(loff_t *)v;
 
-	if (hash > sctp_assoc_hashsize)
+	if (hash >= sctp_assoc_hashsize)
 		return -ENOMEM;
 
-	head = &sctp_assoc_hashtable[hash-1];
+	head = &sctp_assoc_hashtable[hash];
 	sctp_local_bh_disable();
 	read_lock(&head->lock);
 	for (epb = head->chain; epb; epb = epb->next) {
@@ -335,7 +327,7 @@
 		seq_printf(seq,
 			   "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
 			   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
-			   assoc->state, hash-1, assoc->assoc_id,
+			   assoc->state, hash, assoc->assoc_id,
 			   (sk->sk_rcvbuf - assoc->rwnd),
 			   assoc->sndbuf_used,
 			   sock_i_uid(sk), sock_i_ino(sk),
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 556c495..5e0de3c 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1275,7 +1275,12 @@
 	unsigned int keylen;
 	char *key;
 
-	headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE;
+	/* Header size is static data prior to the actual cookie, including
+	 * any padding.
+	 */
+	headersize = sizeof(sctp_paramhdr_t) + 
+		     (sizeof(struct sctp_signed_cookie) - 
+		      sizeof(struct sctp_cookie));
 	bodysize = sizeof(struct sctp_cookie)
 		+ ntohs(init_chunk->chunk_hdr->length) + addrs_len;
 
@@ -1354,7 +1359,7 @@
 	struct sctp_signed_cookie *cookie;
 	struct sctp_cookie *bear_cookie;
 	int headersize, bodysize, fixed_size;
-	__u8 digest[SCTP_SIGNATURE_SIZE];
+	__u8 *digest = ep->digest;
 	struct scatterlist sg;
 	unsigned int keylen, len;
 	char *key;
@@ -1362,7 +1367,12 @@
 	struct sk_buff *skb = chunk->skb;
 	struct timeval tv;
 
-	headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE;
+	/* Header size is static data prior to the actual cookie, including
+	 * any padding.
+	 */
+	headersize = sizeof(sctp_chunkhdr_t) +
+		     (sizeof(struct sctp_signed_cookie) - 
+		      sizeof(struct sctp_cookie));
 	bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
 	fixed_size = headersize + sizeof(struct sctp_cookie);
 
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index b8b38ab..8d1dc24 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1300,7 +1300,7 @@
 					"T1 INIT Timeout adjustment"
 					" init_err_counter: %d"
 					" cycle: %d"
-					" timeout: %d\n",
+					" timeout: %ld\n",
 					asoc->init_err_counter,
 					asoc->init_cycle,
 					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
@@ -1328,7 +1328,7 @@
 			SCTP_DEBUG_PRINTK(
 				"T1 COOKIE Timeout adjustment"
 				" init_err_counter: %d"
-				" timeout: %d\n",
+				" timeout: %ld\n",
 				asoc->init_err_counter,
 				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 477d7f8..2b9a832 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -884,7 +884,7 @@
 {
 	struct sctp_transport *transport = (struct sctp_transport *) arg;
 
-	if (asoc->overall_error_count > asoc->max_retrans) {
+	if (asoc->overall_error_count >= asoc->max_retrans) {
 		/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -2122,7 +2122,7 @@
 	struct sctp_bind_addr *bp;
 	int attempts = asoc->init_err_counter + 1;
 
-	if (attempts >= asoc->max_init_attempts) {
+	if (attempts > asoc->max_init_attempts) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
 				SCTP_U32(SCTP_ERROR_STALE_COOKIE));
 		return SCTP_DISPOSITION_DELETE_TCB;
@@ -3090,6 +3090,8 @@
 			break;
 
 		ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+		if (ch_end > skb->tail)
+			break;
 
 		if (SCTP_CID_SHUTDOWN_ACK == ch->type)
 			ootb_shut_ack = 1;
@@ -4638,7 +4640,7 @@
 
 	SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
 
-	if (attempts < asoc->max_init_attempts) {
+	if (attempts <= asoc->max_init_attempts) {
 		bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
 		repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
 		if (!repl)
@@ -4695,7 +4697,7 @@
 
 	SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
 
-	if (attempts < asoc->max_init_attempts) {
+	if (attempts <= asoc->max_init_attempts) {
 		repl = sctp_make_cookie_echo(asoc, NULL);
 		if (!repl)
 			return SCTP_DISPOSITION_NOMEM;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c98ee37..0ea947e 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2995,7 +2995,7 @@
 	sp->hbinterval  = jiffies_to_msecs(sctp_hb_interval);
 	sp->pathmaxrxt  = sctp_max_retrans_path;
 	sp->pathmtu     = 0; // allow default discovery
-	sp->sackdelay   = sctp_sack_timeout;
+	sp->sackdelay   = jiffies_to_msecs(sctp_sack_timeout);
 	sp->param_flags = SPP_HB_ENABLE |
 	                  SPP_PMTUD_ENABLE |
 	                  SPP_SACKDELAY_ENABLE;
@@ -5426,7 +5426,7 @@
 	return err;
 
 do_error:
-	if (asoc->init_err_counter + 1 >= asoc->max_init_attempts)
+	if (asoc->init_err_counter + 1 > asoc->max_init_attempts)
 		err = -ETIMEDOUT;
 	else
 		err = -ECONNREFUSED;
@@ -5602,8 +5602,12 @@
 	 */
 	newsp->type = type;
 
+	spin_lock_bh(&oldsk->sk_lock.slock);
+	/* Migrate the backlog from oldsk to newsk. */
+	sctp_backlog_migrate(assoc, oldsk, newsk);
 	/* Migrate the association to the new socket. */
 	sctp_assoc_migrate(assoc, newsk);
+	spin_unlock_bh(&oldsk->sk_lock.slock);
 
 	/* If the association on the newsk is already closed before accept()
 	 * is called, set RCV_SHUTDOWN flag.
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index fcd7096..dc6f3ff 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -159,12 +159,9 @@
 		.ctl_name	= NET_SCTP_PRESERVE_ENABLE,
 		.procname	= "cookie_preserve_enable",
 		.data		= &sctp_cookie_preserve_enable,
-		.maxlen		= sizeof(long),
+		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
-		.strategy	= &sctp_sysctl_jiffies_ms,
-		.extra1         = &rto_timer_min,
-		.extra2         = &rto_timer_max
+		.proc_handler	= &proc_dointvec
 	},
 	{
 		.ctl_name	= NET_SCTP_RTO_ALPHA,
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 68d73e2..160f62a 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -350,7 +350,7 @@
 	tp->rto_pending = 0;
 
 	SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d "
-			  "rttvar: %d, rto: %d\n", __FUNCTION__,
+			  "rttvar: %d, rto: %ld\n", __FUNCTION__,
 			  tp, rtt, tp->srtt, tp->rttvar, tp->rto);
 }
 
diff --git a/net/socket.c b/net/socket.c
index b38a263..a00851f 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2078,7 +2078,7 @@
 	int cpu;
 	int counter = 0;
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++)
+	for_each_cpu(cpu)
 		counter += per_cpu(sockets_in_use, cpu);
 
 	/* It can be negative, by the way. 8) */
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 9ac1b8c..8d6f1a1 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -184,7 +184,7 @@
  */
 struct rpc_cred *
 rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
-		int taskflags)
+		int flags)
 {
 	struct rpc_cred_cache *cache = auth->au_credcache;
 	HLIST_HEAD(free);
@@ -193,7 +193,7 @@
 			*cred = NULL;
 	int		nr = 0;
 
-	if (!(taskflags & RPC_TASK_ROOTCREDS))
+	if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
 		nr = acred->uid & RPC_CREDCACHE_MASK;
 retry:
 	spin_lock(&rpc_credcache_lock);
@@ -202,7 +202,7 @@
 	hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
 		struct rpc_cred *entry;
 	       	entry = hlist_entry(pos, struct rpc_cred, cr_hash);
-		if (entry->cr_ops->crmatch(acred, entry, taskflags)) {
+		if (entry->cr_ops->crmatch(acred, entry, flags)) {
 			hlist_del(&entry->cr_hash);
 			cred = entry;
 			break;
@@ -224,7 +224,7 @@
 	rpcauth_destroy_credlist(&free);
 
 	if (!cred) {
-		new = auth->au_ops->crcreate(auth, acred, taskflags);
+		new = auth->au_ops->crcreate(auth, acred, flags);
 		if (!IS_ERR(new)) {
 #ifdef RPC_DEBUG
 			new->cr_magic = RPCAUTH_CRED_MAGIC;
@@ -232,13 +232,21 @@
 			goto retry;
 		} else
 			cred = new;
+	} else if ((cred->cr_flags & RPCAUTH_CRED_NEW)
+			&& cred->cr_ops->cr_init != NULL
+			&& !(flags & RPCAUTH_LOOKUP_NEW)) {
+		int res = cred->cr_ops->cr_init(auth, cred);
+		if (res < 0) {
+			put_rpccred(cred);
+			cred = ERR_PTR(res);
+		}
 	}
 
 	return (struct rpc_cred *) cred;
 }
 
 struct rpc_cred *
-rpcauth_lookupcred(struct rpc_auth *auth, int taskflags)
+rpcauth_lookupcred(struct rpc_auth *auth, int flags)
 {
 	struct auth_cred acred = {
 		.uid = current->fsuid,
@@ -250,7 +258,7 @@
 	dprintk("RPC:     looking up %s cred\n",
 		auth->au_ops->au_name);
 	get_group_info(acred.group_info);
-	ret = auth->au_ops->lookup_cred(auth, &acred, taskflags);
+	ret = auth->au_ops->lookup_cred(auth, &acred, flags);
 	put_group_info(acred.group_info);
 	return ret;
 }
@@ -265,11 +273,14 @@
 		.group_info = current->group_info,
 	};
 	struct rpc_cred *ret;
+	int flags = 0;
 
 	dprintk("RPC: %4d looking up %s cred\n",
 		task->tk_pid, task->tk_auth->au_ops->au_name);
 	get_group_info(acred.group_info);
-	ret = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags);
+	if (task->tk_flags & RPC_TASK_ROOTCREDS)
+		flags |= RPCAUTH_LOOKUP_ROOTCREDS;
+	ret = auth->au_ops->lookup_cred(auth, &acred, flags);
 	if (!IS_ERR(ret))
 		task->tk_msg.rpc_cred = ret;
 	else
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 8d78228..bb46efd 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -158,6 +158,7 @@
 	old = gss_cred->gc_ctx;
 	gss_cred->gc_ctx = ctx;
 	cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
+	cred->cr_flags &= ~RPCAUTH_CRED_NEW;
 	write_unlock(&gss_ctx_lock);
 	if (old)
 		gss_put_ctx(old);
@@ -580,7 +581,7 @@
 	} else {
 		struct auth_cred acred = { .uid = uid };
 		spin_unlock(&gss_auth->lock);
-		cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0);
+		cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
 		if (IS_ERR(cred)) {
 			err = PTR_ERR(cred);
 			goto err_put_ctx;
@@ -758,13 +759,13 @@
  * Lookup RPCSEC_GSS cred for the current process
  */
 static struct rpc_cred *
-gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
+gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 {
-	return rpcauth_lookup_credcache(auth, acred, taskflags);
+	return rpcauth_lookup_credcache(auth, acred, flags);
 }
 
 static struct rpc_cred *
-gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
+gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 {
 	struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
 	struct gss_cred	*cred = NULL;
@@ -785,13 +786,8 @@
 	 */
 	cred->gc_flags = 0;
 	cred->gc_base.cr_ops = &gss_credops;
+	cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
 	cred->gc_service = gss_auth->service;
-	do {
-		err = gss_create_upcall(gss_auth, cred);
-	} while (err == -EAGAIN);
-	if (err < 0)
-		goto out_err;
-
 	return &cred->gc_base;
 
 out_err:
@@ -801,13 +797,34 @@
 }
 
 static int
-gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags)
+gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred)
+{
+	struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
+	struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base);
+	int err;
+
+	do {
+		err = gss_create_upcall(gss_auth, gss_cred);
+	} while (err == -EAGAIN);
+	return err;
+}
+
+static int
+gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
 {
 	struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
 
+	/*
+	 * If the searchflags have set RPCAUTH_LOOKUP_NEW, then
+	 * we don't really care if the credential has expired or not,
+	 * since the caller should be prepared to reinitialise it.
+	 */
+	if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW))
+		goto out;
 	/* Don't match with creds that have expired. */
 	if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
 		return 0;
+out:
 	return (rc->cr_uid == acred->uid);
 }
 
@@ -1241,6 +1258,7 @@
 static struct rpc_credops gss_credops = {
 	.cr_name	= "AUTH_GSS",
 	.crdestroy	= gss_destroy_cred,
+	.cr_init	= gss_cred_init,
 	.crmatch	= gss_match,
 	.crmarshal	= gss_marshal,
 	.crrefresh	= gss_refresh,
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index e4ada15..23632d8 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -420,7 +420,8 @@
 			gss_mech_put(gm);
 			goto out;
 		}
-		if (gss_import_sec_context(buf, len, gm, &rsci.mechctx)) {
+		status = gss_import_sec_context(buf, len, gm, &rsci.mechctx);
+		if (status) {
 			gss_mech_put(gm);
 			goto out;
 		}
@@ -586,6 +587,20 @@
 }
 
 static int
+gss_write_null_verf(struct svc_rqst *rqstp)
+{
+	u32     *p;
+
+	svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_NULL));
+	p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
+	/* don't really need to check if head->iov_len > PAGE_SIZE ... */
+	*p++ = 0;
+	if (!xdr_ressize_check(rqstp, p))
+		return -1;
+	return 0;
+}
+
+static int
 gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
 {
 	u32			xdr_seq;
@@ -741,6 +756,21 @@
 	return SVC_OK;
 }
 
+static inline int
+gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip)
+{
+	struct rsc *rsci;
+
+	if (rsip->major_status != GSS_S_COMPLETE)
+		return gss_write_null_verf(rqstp);
+	rsci = gss_svc_searchbyctx(&rsip->out_handle);
+	if (rsci == NULL) {
+		rsip->major_status = GSS_S_NO_CONTEXT;
+		return gss_write_null_verf(rqstp);
+	}
+	return gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
+}
+
 /*
  * Accept an rpcsec packet.
  * If context establishment, punt to user space
@@ -876,11 +906,7 @@
 		case -ENOENT:
 			goto drop;
 		case 0:
-			rsci = gss_svc_searchbyctx(&rsip->out_handle);
-			if (!rsci) {
-				goto drop;
-			}
-			if (gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN))
+			if (gss_write_init_verf(rqstp, rsip))
 				goto drop;
 			if (resv->iov_len + 4 > PAGE_SIZE)
 				goto drop;
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 1b3ed4f..df14b6b 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -75,7 +75,7 @@
 
 	atomic_set(&cred->uc_count, 1);
 	cred->uc_flags = RPCAUTH_CRED_UPTODATE;
-	if (flags & RPC_TASK_ROOTCREDS) {
+	if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
 		cred->uc_uid = 0;
 		cred->uc_gid = 0;
 		cred->uc_gids[0] = NOGROUP;
@@ -108,12 +108,12 @@
  * request root creds (e.g. for NFS swapping).
  */
 static int
-unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
+unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
 {
 	struct unx_cred	*cred = (struct unx_cred *) rcred;
 	int		i;
 
-	if (!(taskflags & RPC_TASK_ROOTCREDS)) {
+	if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) {
 		int groups;
 
 		if (cred->uc_uid != acred->uid
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 9764c80..a5c0c7b 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -38,44 +38,42 @@
 
 #define RPC_UPCALL_TIMEOUT (30*HZ)
 
-static void
-__rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, int err)
+static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head,
+		void (*destroy_msg)(struct rpc_pipe_msg *), int err)
 {
 	struct rpc_pipe_msg *msg;
-	void (*destroy_msg)(struct rpc_pipe_msg *);
 
-	destroy_msg = rpci->ops->destroy_msg;
-	while (!list_empty(head)) {
+	if (list_empty(head))
+		return;
+	do {
 		msg = list_entry(head->next, struct rpc_pipe_msg, list);
-		list_del_init(&msg->list);
+		list_del(&msg->list);
 		msg->errno = err;
 		destroy_msg(msg);
-	}
-}
-
-static void
-__rpc_purge_upcall(struct inode *inode, int err)
-{
-	struct rpc_inode *rpci = RPC_I(inode);
-
-	__rpc_purge_list(rpci, &rpci->pipe, err);
-	rpci->pipelen = 0;
+	} while (!list_empty(head));
 	wake_up(&rpci->waitq);
 }
 
 static void
 rpc_timeout_upcall_queue(void *data)
 {
+	LIST_HEAD(free_list);
 	struct rpc_inode *rpci = (struct rpc_inode *)data;
 	struct inode *inode = &rpci->vfs_inode;
+	void (*destroy_msg)(struct rpc_pipe_msg *);
 
-	mutex_lock(&inode->i_mutex);
-	if (rpci->ops == NULL)
-		goto out;
-	if (rpci->nreaders == 0 && !list_empty(&rpci->pipe))
-		__rpc_purge_upcall(inode, -ETIMEDOUT);
-out:
-	mutex_unlock(&inode->i_mutex);
+	spin_lock(&inode->i_lock);
+	if (rpci->ops == NULL) {
+		spin_unlock(&inode->i_lock);
+		return;
+	}
+	destroy_msg = rpci->ops->destroy_msg;
+	if (rpci->nreaders == 0) {
+		list_splice_init(&rpci->pipe, &free_list);
+		rpci->pipelen = 0;
+	}
+	spin_unlock(&inode->i_lock);
+	rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT);
 }
 
 int
@@ -84,7 +82,7 @@
 	struct rpc_inode *rpci = RPC_I(inode);
 	int res = -EPIPE;
 
-	mutex_lock(&inode->i_mutex);
+	spin_lock(&inode->i_lock);
 	if (rpci->ops == NULL)
 		goto out;
 	if (rpci->nreaders) {
@@ -100,7 +98,7 @@
 		res = 0;
 	}
 out:
-	mutex_unlock(&inode->i_mutex);
+	spin_unlock(&inode->i_lock);
 	wake_up(&rpci->waitq);
 	return res;
 }
@@ -115,21 +113,29 @@
 rpc_close_pipes(struct inode *inode)
 {
 	struct rpc_inode *rpci = RPC_I(inode);
+	struct rpc_pipe_ops *ops;
 
 	mutex_lock(&inode->i_mutex);
-	if (rpci->ops != NULL) {
+	ops = rpci->ops;
+	if (ops != NULL) {
+		LIST_HEAD(free_list);
+
+		spin_lock(&inode->i_lock);
 		rpci->nreaders = 0;
-		__rpc_purge_list(rpci, &rpci->in_upcall, -EPIPE);
-		__rpc_purge_upcall(inode, -EPIPE);
-		rpci->nwriters = 0;
-		if (rpci->ops->release_pipe)
-			rpci->ops->release_pipe(inode);
+		list_splice_init(&rpci->in_upcall, &free_list);
+		list_splice_init(&rpci->pipe, &free_list);
+		rpci->pipelen = 0;
 		rpci->ops = NULL;
+		spin_unlock(&inode->i_lock);
+		rpc_purge_list(rpci, &free_list, ops->destroy_msg, -EPIPE);
+		rpci->nwriters = 0;
+		if (ops->release_pipe)
+			ops->release_pipe(inode);
+		cancel_delayed_work(&rpci->queue_timeout);
+		flush_scheduled_work();
 	}
 	rpc_inode_setowner(inode, NULL);
 	mutex_unlock(&inode->i_mutex);
-	cancel_delayed_work(&rpci->queue_timeout);
-	flush_scheduled_work();
 }
 
 static struct inode *
@@ -177,16 +183,26 @@
 		goto out;
 	msg = (struct rpc_pipe_msg *)filp->private_data;
 	if (msg != NULL) {
+		spin_lock(&inode->i_lock);
 		msg->errno = -EAGAIN;
-		list_del_init(&msg->list);
+		list_del(&msg->list);
+		spin_unlock(&inode->i_lock);
 		rpci->ops->destroy_msg(msg);
 	}
 	if (filp->f_mode & FMODE_WRITE)
 		rpci->nwriters --;
-	if (filp->f_mode & FMODE_READ)
+	if (filp->f_mode & FMODE_READ) {
 		rpci->nreaders --;
-	if (!rpci->nreaders)
-		__rpc_purge_upcall(inode, -EAGAIN);
+		if (rpci->nreaders == 0) {
+			LIST_HEAD(free_list);
+			spin_lock(&inode->i_lock);
+			list_splice_init(&rpci->pipe, &free_list);
+			rpci->pipelen = 0;
+			spin_unlock(&inode->i_lock);
+			rpc_purge_list(rpci, &free_list,
+					rpci->ops->destroy_msg, -EAGAIN);
+		}
+	}
 	if (rpci->ops->release_pipe)
 		rpci->ops->release_pipe(inode);
 out:
@@ -209,6 +225,7 @@
 	}
 	msg = filp->private_data;
 	if (msg == NULL) {
+		spin_lock(&inode->i_lock);
 		if (!list_empty(&rpci->pipe)) {
 			msg = list_entry(rpci->pipe.next,
 					struct rpc_pipe_msg,
@@ -218,6 +235,7 @@
 			filp->private_data = msg;
 			msg->copied = 0;
 		}
+		spin_unlock(&inode->i_lock);
 		if (msg == NULL)
 			goto out_unlock;
 	}
@@ -225,7 +243,9 @@
 	res = rpci->ops->upcall(filp, msg, buf, len);
 	if (res < 0 || msg->len == msg->copied) {
 		filp->private_data = NULL;
-		list_del_init(&msg->list);
+		spin_lock(&inode->i_lock);
+		list_del(&msg->list);
+		spin_unlock(&inode->i_lock);
 		rpci->ops->destroy_msg(msg);
 	}
 out_unlock:
@@ -610,7 +630,7 @@
 		return ERR_PTR(error);
 	dir = nd->dentry->d_inode;
 	mutex_lock(&dir->i_mutex);
-	dentry = lookup_hash(nd);
+	dentry = lookup_one_len(nd->last.name, nd->dentry, nd->last.len);
 	if (IS_ERR(dentry))
 		goto out_err;
 	if (dentry->d_inode) {
@@ -672,7 +692,7 @@
 		return error;
 	dir = nd.dentry->d_inode;
 	mutex_lock(&dir->i_mutex);
-	dentry = lookup_hash(&nd);
+	dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len);
 	if (IS_ERR(dentry)) {
 		error = PTR_ERR(dentry);
 		goto out_release;
@@ -733,7 +753,7 @@
 		return error;
 	dir = nd.dentry->d_inode;
 	mutex_lock(&dir->i_mutex);
-	dentry = lookup_hash(&nd);
+	dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len);
 	if (IS_ERR(dentry)) {
 		error = PTR_ERR(dentry);
 		goto out_release;
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 7415406..802d4fe 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -908,10 +908,10 @@
 
 /**
  * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
- * @clnt - pointer to RPC client
- * @flags - RPC flags
- * @ops - RPC call ops
- * @data - user call data
+ * @clnt: pointer to RPC client
+ * @flags: RPC flags
+ * @ops: RPC call ops
+ * @data: user call data
  */
 struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
 					const struct rpc_call_ops *ops,
@@ -930,6 +930,7 @@
 /**
  * rpc_find_parent - find the parent of a child task.
  * @child: child task
+ * @parent: parent task
  *
  * Checks that the parent task is still sleeping on the
  * queue 'childq'. If so returns a pointer to the parent.
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index e67613e..5058062 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1527,6 +1527,7 @@
 		dr->handle.owner = rqstp->rq_server;
 		dr->prot = rqstp->rq_prot;
 		dr->addr = rqstp->rq_addr;
+		dr->daddr = rqstp->rq_daddr;
 		dr->argslen = rqstp->rq_arg.len >> 2;
 		memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
 	}
@@ -1552,6 +1553,7 @@
 	rqstp->rq_arg.len = dr->argslen<<2;
 	rqstp->rq_prot        = dr->prot;
 	rqstp->rq_addr        = dr->addr;
+	rqstp->rq_daddr       = dr->daddr;
 	return dr->argslen<<2;
 }
 
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig
index 05ab18e..3891cc0 100644
--- a/net/tipc/Kconfig
+++ b/net/tipc/Kconfig
@@ -8,7 +8,12 @@
 config TIPC
 	tristate "The TIPC Protocol (EXPERIMENTAL)"
 	---help---
-	  TBD.
+	  The Transparent Inter Process Communication (TIPC) protocol is
+	  specially designed for intra cluster communication. This protocol
+	  originates from Ericsson where it has been used in carrier grade
+	  cluster applications for many years.
+	
+	  For more information about TIPC, see http://tipc.sourceforge.net.
 
 	  This protocol support is also available as a module ( = code which
 	  can be inserted in and removed from the running kernel whenever you
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
index eca2226..0be25e1 100644
--- a/net/tipc/addr.c
+++ b/net/tipc/addr.c
@@ -47,7 +47,7 @@
 }
 
 /**
- * addr_domain_valid - validates a network domain address
+ * tipc_addr_domain_valid - validates a network domain address
  * 
  * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>, 
  * where Z, C, and N are non-zero and do not exceed the configured limits.
@@ -55,7 +55,7 @@
  * Returns 1 if domain address is valid, otherwise 0
  */
 
-int addr_domain_valid(u32 addr)
+int tipc_addr_domain_valid(u32 addr)
 {
 	u32 n = tipc_node(addr);
 	u32 c = tipc_cluster(addr);
@@ -79,7 +79,7 @@
 }
 
 /**
- * addr_node_valid - validates a proposed network address for this node
+ * tipc_addr_node_valid - validates a proposed network address for this node
  * 
  * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed 
  * the configured limits.
@@ -87,8 +87,8 @@
  * Returns 1 if address can be used, otherwise 0
  */
 
-int addr_node_valid(u32 addr)
+int tipc_addr_node_valid(u32 addr)
 {
-	return (addr_domain_valid(addr) && tipc_node(addr));
+	return (tipc_addr_domain_valid(addr) && tipc_node(addr));
 }
 
diff --git a/net/tipc/addr.h b/net/tipc/addr.h
index 02ca717..bcfebb3 100644
--- a/net/tipc/addr.h
+++ b/net/tipc/addr.h
@@ -122,7 +122,7 @@
 	return string;
 }
 
-int addr_domain_valid(u32);
-int addr_node_valid(u32 addr);
+int tipc_addr_domain_valid(u32);
+int tipc_addr_node_valid(u32 addr);
 
 #endif
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 9713d62..a7b04f3 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -82,7 +82,7 @@
 	struct bearer bearer;
 	struct media media;
 	struct bcbearer_pair bpairs[MAX_BEARERS];
-	struct bcbearer_pair bpairs_temp[TIPC_NUM_LINK_PRI];
+	struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1];
 };
 
 /**
@@ -104,7 +104,7 @@
 static struct link *bcl = NULL;
 static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED;
 
-char bc_link_name[] = "multicast-link";
+char tipc_bclink_name[] = "multicast-link";
 
 
 static inline u32 buf_seqno(struct sk_buff *buf)
@@ -178,19 +178,19 @@
 		buf = buf->next;                
 	}
 	if (buf != NULL)
-		link_retransmit(bcl, buf, mod(to - after));
+		tipc_link_retransmit(bcl, buf, mod(to - after));
 	spin_unlock_bh(&bc_lock);              
 }
 
 /** 
- * bclink_acknowledge - handle acknowledgement of broadcast packets
+ * tipc_bclink_acknowledge - handle acknowledgement of broadcast packets
  * @n_ptr: node that sent acknowledgement info
  * @acked: broadcast sequence # that has been acknowledged
  * 
  * Node is locked, bc_lock unlocked.
  */
 
-void bclink_acknowledge(struct node *n_ptr, u32 acked)
+void tipc_bclink_acknowledge(struct node *n_ptr, u32 acked)
 {
 	struct sk_buff *crs;
 	struct sk_buff *next;
@@ -226,16 +226,16 @@
 	/* Try resolving broadcast link congestion, if necessary */
 
 	if (unlikely(bcl->next_out))
-		link_push_queue(bcl);
+		tipc_link_push_queue(bcl);
 	if (unlikely(released && !list_empty(&bcl->waiting_ports)))
-		link_wakeup_ports(bcl, 0);
+		tipc_link_wakeup_ports(bcl, 0);
 	spin_unlock_bh(&bc_lock);
 }
 
 /** 
  * bclink_send_ack - unicast an ACK msg
  * 
- * net_lock and node lock set
+ * tipc_net_lock and node lock set
  */
 
 static void bclink_send_ack(struct node *n_ptr)
@@ -243,13 +243,13 @@
 	struct link *l_ptr = n_ptr->active_links[n_ptr->addr & 1];
 
 	if (l_ptr != NULL)
-		link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
+		tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
 }
 
 /** 
  * bclink_send_nack- broadcast a NACK msg
  * 
- * net_lock and node lock set
+ * tipc_net_lock and node lock set
  */
 
 static void bclink_send_nack(struct node *n_ptr)
@@ -271,11 +271,11 @@
 		msg_set_bcgap_to(msg, n_ptr->bclink.gap_to);
 		msg_set_bcast_tag(msg, tipc_own_tag);
 
-		if (bearer_send(&bcbearer->bearer, buf, 0)) {
+		if (tipc_bearer_send(&bcbearer->bearer, buf, 0)) {
 			bcl->stats.sent_nacks++;
 			buf_discard(buf);
 		} else {
-			bearer_schedule(bcl->b_ptr, bcl);
+			tipc_bearer_schedule(bcl->b_ptr, bcl);
 			bcl->proto_msg_queue = buf;
 			bcl->stats.bearer_congs++;
 		}
@@ -291,12 +291,12 @@
 }
 
 /** 
- * bclink_check_gap - send a NACK if a sequence gap exists
+ * tipc_bclink_check_gap - send a NACK if a sequence gap exists
  *
- * net_lock and node lock set
+ * tipc_net_lock and node lock set
  */
 
-void bclink_check_gap(struct node *n_ptr, u32 last_sent)
+void tipc_bclink_check_gap(struct node *n_ptr, u32 last_sent)
 {
 	if (!n_ptr->bclink.supported ||
 	    less_eq(last_sent, mod(n_ptr->bclink.last_in)))
@@ -309,19 +309,19 @@
 }
 
 /** 
- * bclink_peek_nack - process a NACK msg meant for another node
+ * tipc_bclink_peek_nack - process a NACK msg meant for another node
  * 
- * Only net_lock set.
+ * Only tipc_net_lock set.
  */
 
-void bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to)
+void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to)
 {
-	struct node *n_ptr = node_find(dest);
+	struct node *n_ptr = tipc_node_find(dest);
 	u32 my_after, my_to;
 
-	if (unlikely(!n_ptr || !node_is_up(n_ptr)))
+	if (unlikely(!n_ptr || !tipc_node_is_up(n_ptr)))
 		return;
-	node_lock(n_ptr);
+	tipc_node_lock(n_ptr);
 	/*
 	 * Modify gap to suppress unnecessary NACKs from this node
 	 */
@@ -364,20 +364,20 @@
 			bclink_set_gap(n_ptr);
 		}
 	}
-	node_unlock(n_ptr);
+	tipc_node_unlock(n_ptr);
 }
 
 /**
- * bclink_send_msg - broadcast a packet to all nodes in cluster
+ * tipc_bclink_send_msg - broadcast a packet to all nodes in cluster
  */
 
-int bclink_send_msg(struct sk_buff *buf)
+int tipc_bclink_send_msg(struct sk_buff *buf)
 {
 	int res;
 
 	spin_lock_bh(&bc_lock);
 
-	res = link_send_buf(bcl, buf);
+	res = tipc_link_send_buf(bcl, buf);
 	if (unlikely(res == -ELINKCONG))
 		buf_discard(buf);
 	else
@@ -393,22 +393,22 @@
 }
 
 /**
- * bclink_recv_pkt - receive a broadcast packet, and deliver upwards
+ * tipc_bclink_recv_pkt - receive a broadcast packet, and deliver upwards
  * 
- * net_lock is read_locked, no other locks set
+ * tipc_net_lock is read_locked, no other locks set
  */
 
-void bclink_recv_pkt(struct sk_buff *buf)
+void tipc_bclink_recv_pkt(struct sk_buff *buf)
 {        
 	struct tipc_msg *msg = buf_msg(buf);
-	struct node* node = node_find(msg_prevnode(msg));
+	struct node* node = tipc_node_find(msg_prevnode(msg));
 	u32 next_in;
 	u32 seqno;
 	struct sk_buff *deferred;
 
 	msg_dbg(msg, "<BC<<<");
 
-	if (unlikely(!node || !node_is_up(node) || !node->bclink.supported || 
+	if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported || 
 		     (msg_mc_netid(msg) != tipc_net_id))) {
 		buf_discard(buf);
 		return;
@@ -417,14 +417,14 @@
 	if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) {
 		msg_dbg(msg, "<BCNACK<<<");
 		if (msg_destnode(msg) == tipc_own_addr) {
-			node_lock(node);
-			bclink_acknowledge(node, msg_bcast_ack(msg));
-			node_unlock(node);
+			tipc_node_lock(node);
+			tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
+			tipc_node_unlock(node);
 			bcl->stats.recv_nacks++;
 			bclink_retransmit_pkt(msg_bcgap_after(msg),
 					      msg_bcgap_to(msg));
 		} else {
-			bclink_peek_nack(msg_destnode(msg),
+			tipc_bclink_peek_nack(msg_destnode(msg),
 					 msg_bcast_tag(msg),
 					 msg_bcgap_after(msg),
 					 msg_bcgap_to(msg));
@@ -433,7 +433,7 @@
 		return;
 	}
 
-	node_lock(node);
+	tipc_node_lock(node);
 receive:
 	deferred = node->bclink.deferred_head;
 	next_in = mod(node->bclink.last_in + 1);
@@ -448,26 +448,26 @@
 			bcl->stats.sent_acks++;
 		}
 		if (likely(msg_isdata(msg))) {
-			node_unlock(node);
-			port_recv_mcast(buf, NULL);
+			tipc_node_unlock(node);
+			tipc_port_recv_mcast(buf, NULL);
 		} else if (msg_user(msg) == MSG_BUNDLER) {
 			bcl->stats.recv_bundles++;
 			bcl->stats.recv_bundled += msg_msgcnt(msg);
-			node_unlock(node);
-			link_recv_bundle(buf);
+			tipc_node_unlock(node);
+			tipc_link_recv_bundle(buf);
 		} else if (msg_user(msg) == MSG_FRAGMENTER) {
 			bcl->stats.recv_fragments++;
-			if (link_recv_fragment(&node->bclink.defragm,
-					       &buf, &msg))
+			if (tipc_link_recv_fragment(&node->bclink.defragm,
+						    &buf, &msg))
 				bcl->stats.recv_fragmented++;
-			node_unlock(node);
-			net_route_msg(buf);
+			tipc_node_unlock(node);
+			tipc_net_route_msg(buf);
 		} else {
-			node_unlock(node);
-			net_route_msg(buf);
+			tipc_node_unlock(node);
+			tipc_net_route_msg(buf);
 		}
 		if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) {
-			node_lock(node);
+			tipc_node_lock(node);
 			buf = deferred;
 			msg = buf_msg(buf);
 			node->bclink.deferred_head = deferred->next;
@@ -478,9 +478,9 @@
 		u32 gap_after = node->bclink.gap_after;
 		u32 gap_to = node->bclink.gap_to;
 
-		if (link_defer_pkt(&node->bclink.deferred_head,
-				   &node->bclink.deferred_tail,
-				   buf)) {
+		if (tipc_link_defer_pkt(&node->bclink.deferred_head,
+					&node->bclink.deferred_tail,
+					buf)) {
 			node->bclink.nack_sync++;
 			bcl->stats.deferred_recv++;
 			if (seqno == mod(gap_after + 1))
@@ -497,10 +497,10 @@
 		bcl->stats.duplicates++;
 		buf_discard(buf);
 	}
-	node_unlock(node);
+	tipc_node_unlock(node);
 }
 
-u32 bclink_get_last_sent(void)
+u32 tipc_bclink_get_last_sent(void)
 {
 	u32 last_sent = mod(bcl->next_out_no - 1);
 
@@ -509,15 +509,15 @@
 	return last_sent;
 }
 
-u32 bclink_acks_missing(struct node *n_ptr)
+u32 tipc_bclink_acks_missing(struct node *n_ptr)
 {
 	return (n_ptr->bclink.supported &&
-		(bclink_get_last_sent() != n_ptr->bclink.acked));
+		(tipc_bclink_get_last_sent() != n_ptr->bclink.acked));
 }
 
 
 /**
- * bcbearer_send - send a packet through the broadcast pseudo-bearer
+ * tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer
  * 
  * Send through as many bearers as necessary to reach all nodes
  * that support TIPC multicasting.
@@ -525,9 +525,9 @@
  * Returns 0 if packet sent successfully, non-zero if not
  */
 
-int bcbearer_send(struct sk_buff *buf,
-		  struct tipc_bearer *unused1,
-		  struct tipc_media_addr *unused2)
+int tipc_bcbearer_send(struct sk_buff *buf,
+		       struct tipc_bearer *unused1,
+		       struct tipc_media_addr *unused2)
 {
 	static int send_count = 0;
 
@@ -541,8 +541,8 @@
 	if (likely(!msg_non_seq(buf_msg(buf)))) {
 		struct tipc_msg *msg;
 
-		assert(cluster_bcast_nodes.count != 0);
-		bcbuf_set_acks(buf, cluster_bcast_nodes.count);
+		assert(tipc_cltr_bcast_nodes.count != 0);
+		bcbuf_set_acks(buf, tipc_cltr_bcast_nodes.count);
 		msg = buf_msg(buf);
 		msg_set_non_seq(msg);
 		msg_set_mc_netid(msg, tipc_net_id);
@@ -555,7 +555,7 @@
 
 	/* Send buffer over bearers until all targets reached */
 	
-	remains = cluster_bcast_nodes;
+	remains = tipc_cltr_bcast_nodes;
 
 	for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
 		struct bearer *p = bcbearer->bpairs[bp_index].primary;
@@ -564,7 +564,7 @@
 		if (!p)
 			break;	/* no more bearers to try */
 
-		nmap_diff(&remains, &p->nodes, &remains_new);
+		tipc_nmap_diff(&remains, &p->nodes, &remains_new);
 		if (remains_new.count == remains.count)
 			continue;	/* bearer pair doesn't add anything */
 
@@ -597,10 +597,10 @@
 }
 
 /**
- * bcbearer_sort - create sets of bearer pairs used by broadcast bearer
+ * tipc_bcbearer_sort - create sets of bearer pairs used by broadcast bearer
  */
 
-void bcbearer_sort(void)
+void tipc_bcbearer_sort(void)
 {
 	struct bcbearer_pair *bp_temp = bcbearer->bpairs_temp;
 	struct bcbearer_pair *bp_curr;
@@ -614,7 +614,7 @@
 	memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp));
 
 	for (b_index = 0; b_index < MAX_BEARERS; b_index++) {
-		struct bearer *b = &bearers[b_index];
+		struct bearer *b = &tipc_bearers[b_index];
 
 		if (!b->active || !b->nodes.count)
 			continue;
@@ -630,7 +630,7 @@
 	bp_curr = bcbearer->bpairs;
 	memset(bcbearer->bpairs, 0, sizeof(bcbearer->bpairs));
 
-	for (pri = (TIPC_NUM_LINK_PRI - 1); pri >= 0; pri--) {
+	for (pri = TIPC_MAX_LINK_PRI; pri >= 0; pri--) {
 
 		if (!bp_temp[pri].primary)
 			continue;
@@ -638,8 +638,8 @@
 		bp_curr->primary = bp_temp[pri].primary;
 
 		if (bp_temp[pri].secondary) {
-			if (nmap_equal(&bp_temp[pri].primary->nodes,
-				       &bp_temp[pri].secondary->nodes)) {
+			if (tipc_nmap_equal(&bp_temp[pri].primary->nodes,
+					    &bp_temp[pri].secondary->nodes)) {
 				bp_curr->secondary = bp_temp[pri].secondary;
 			} else {
 				bp_curr++;
@@ -654,14 +654,14 @@
 }
 
 /**
- * bcbearer_push - resolve bearer congestion
+ * tipc_bcbearer_push - resolve bearer congestion
  * 
  * Forces bclink to push out any unsent packets, until all packets are gone
  * or congestion reoccurs.
  * No locks set when function called
  */
 
-void bcbearer_push(void)
+void tipc_bcbearer_push(void)
 {
 	struct bearer *b_ptr;
 
@@ -669,20 +669,20 @@
 	b_ptr = &bcbearer->bearer;
 	if (b_ptr->publ.blocked) {
 		b_ptr->publ.blocked = 0;
-		bearer_lock_push(b_ptr);
+		tipc_bearer_lock_push(b_ptr);
 	}
 	spin_unlock_bh(&bc_lock);
 }
 
 
-int bclink_stats(char *buf, const u32 buf_size)
+int tipc_bclink_stats(char *buf, const u32 buf_size)
 {
 	struct print_buf pb;
 
 	if (!bcl)
 		return 0;
 
-	printbuf_init(&pb, buf, buf_size);
+	tipc_printbuf_init(&pb, buf, buf_size);
 
 	spin_lock_bh(&bc_lock);
 
@@ -718,10 +718,10 @@
 		    : 0);
 
 	spin_unlock_bh(&bc_lock);
-	return printbuf_validate(&pb);
+	return tipc_printbuf_validate(&pb);
 }
 
-int bclink_reset_stats(void)
+int tipc_bclink_reset_stats(void)
 {
 	if (!bcl)
 		return -ENOPROTOOPT;
@@ -732,7 +732,7 @@
 	return TIPC_OK;
 }
 
-int bclink_set_queue_limits(u32 limit)
+int tipc_bclink_set_queue_limits(u32 limit)
 {
 	if (!bcl)
 		return -ENOPROTOOPT;
@@ -740,12 +740,12 @@
 		return -EINVAL;
 
 	spin_lock_bh(&bc_lock);
-	link_set_queue_limits(bcl, limit);
+	tipc_link_set_queue_limits(bcl, limit);
 	spin_unlock_bh(&bc_lock);
 	return TIPC_OK;
 }
 
-int bclink_init(void)
+int tipc_bclink_init(void)
 {
 	bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC);
 	bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC);
@@ -762,7 +762,7 @@
 	memset(bcbearer, 0, sizeof(struct bcbearer));
 	INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
 	bcbearer->bearer.media = &bcbearer->media;
-	bcbearer->media.send_msg = bcbearer_send;
+	bcbearer->media.send_msg = tipc_bcbearer_send;
 	sprintf(bcbearer->media.name, "tipc-multicast");
 
 	bcl = &bclink->link;
@@ -772,27 +772,27 @@
 	bclink->node.lock =  SPIN_LOCK_UNLOCKED;        
 	bcl->owner = &bclink->node;
         bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
-	link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
+	tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
 	bcl->b_ptr = &bcbearer->bearer;
 	bcl->state = WORKING_WORKING;
-	sprintf(bcl->name, bc_link_name);
+	sprintf(bcl->name, tipc_bclink_name);
 
 	if (BCLINK_LOG_BUF_SIZE) {
 		char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC);
 
 		if (!pb)
 			goto nomem;
-		printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE);
+		tipc_printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE);
 	}
 
 	return TIPC_OK;
 }
 
-void bclink_stop(void)
+void tipc_bclink_stop(void)
 {
 	spin_lock_bh(&bc_lock);
 	if (bcbearer) {
-		link_stop(bcl);
+		tipc_link_stop(bcl);
 		if (BCLINK_LOG_BUF_SIZE)
 			kfree(bcl->print_buf.buf);
 		bcl = NULL;
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 5430e52..0e3be2a 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -70,14 +70,14 @@
 
 struct node;
 
-extern char bc_link_name[];
+extern char tipc_bclink_name[];
 
 
 /**
  * nmap_get - determine if node exists in a node map
  */
 
-static inline int nmap_get(struct node_map *nm_ptr, u32 node)
+static inline int tipc_nmap_get(struct node_map *nm_ptr, u32 node)
 {
 	int n = tipc_node(node);
 	int w = n / WSIZE;
@@ -90,7 +90,7 @@
  * nmap_add - add a node to a node map
  */
 
-static inline void nmap_add(struct node_map *nm_ptr, u32 node)
+static inline void tipc_nmap_add(struct node_map *nm_ptr, u32 node)
 {
 	int n = tipc_node(node);
 	int w = n / WSIZE;
@@ -106,7 +106,7 @@
  * nmap_remove - remove a node from a node map
  */
 
-static inline void nmap_remove(struct node_map *nm_ptr, u32 node)
+static inline void tipc_nmap_remove(struct node_map *nm_ptr, u32 node)
 {
 	int n = tipc_node(node);
 	int w = n / WSIZE;
@@ -122,7 +122,7 @@
  * nmap_equal - test for equality of node maps
  */
 
-static inline int nmap_equal(struct node_map *nm_a, struct node_map *nm_b)
+static inline int tipc_nmap_equal(struct node_map *nm_a, struct node_map *nm_b)
 {
 	return !memcmp(nm_a, nm_b, sizeof(*nm_a));
 }
@@ -134,8 +134,8 @@
  * @nm_diff: output node map A-B (i.e. nodes of A that are not in B)
  */
 
-static inline void nmap_diff(struct node_map *nm_a, struct node_map *nm_b,
-			     struct node_map *nm_diff)
+static inline void tipc_nmap_diff(struct node_map *nm_a, struct node_map *nm_b,
+				  struct node_map *nm_diff)
 {
 	int stop = sizeof(nm_a->map) / sizeof(u32);
 	int w;
@@ -159,7 +159,7 @@
  * port_list_add - add a port to a port list, ensuring no duplicates
  */
 
-static inline void port_list_add(struct port_list *pl_ptr, u32 port)
+static inline void tipc_port_list_add(struct port_list *pl_ptr, u32 port)
 {
 	struct port_list *item = pl_ptr;
 	int i;
@@ -194,7 +194,7 @@
  * Note: First item is on stack, so it doesn't need to be released
  */
 
-static inline void port_list_free(struct port_list *pl_ptr)
+static inline void tipc_port_list_free(struct port_list *pl_ptr)
 {
 	struct port_list *item;
 	struct port_list *next;
@@ -206,18 +206,18 @@
 }
 
 
-int  bclink_init(void);
-void bclink_stop(void);
-void bclink_acknowledge(struct node *n_ptr, u32 acked);
-int  bclink_send_msg(struct sk_buff *buf);
-void bclink_recv_pkt(struct sk_buff *buf);
-u32  bclink_get_last_sent(void);
-u32  bclink_acks_missing(struct node *n_ptr);
-void bclink_check_gap(struct node *n_ptr, u32 seqno);
-int  bclink_stats(char *stats_buf, const u32 buf_size);
-int  bclink_reset_stats(void);
-int  bclink_set_queue_limits(u32 limit);
-void bcbearer_sort(void);
-void bcbearer_push(void);
+int  tipc_bclink_init(void);
+void tipc_bclink_stop(void);
+void tipc_bclink_acknowledge(struct node *n_ptr, u32 acked);
+int  tipc_bclink_send_msg(struct sk_buff *buf);
+void tipc_bclink_recv_pkt(struct sk_buff *buf);
+u32  tipc_bclink_get_last_sent(void);
+u32  tipc_bclink_acks_missing(struct node *n_ptr);
+void tipc_bclink_check_gap(struct node *n_ptr, u32 seqno);
+int  tipc_bclink_stats(char *stats_buf, const u32 buf_size);
+int  tipc_bclink_reset_stats(void);
+int  tipc_bclink_set_queue_limits(u32 limit);
+void tipc_bcbearer_sort(void);
+void tipc_bcbearer_push(void);
 
 #endif
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 3dd19fd..64dcb0f 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -48,7 +48,7 @@
 static struct media *media_list = 0;
 static u32 media_count = 0;
 
-struct bearer *bearers = 0;
+struct bearer *tipc_bearers = 0;
 
 /**
  * media_name_valid - validate media name
@@ -107,7 +107,7 @@
 	u32 i;
 	int res = -EINVAL;
 
-	write_lock_bh(&net_lock);
+	write_lock_bh(&tipc_net_lock);
 	if (!media_list)
 		goto exit;
 
@@ -119,7 +119,8 @@
 		warn("Media registration error: no broadcast address supplied\n");
 		goto exit;
 	}
-	if (bearer_priority >= TIPC_NUM_LINK_PRI) {
+	if ((bearer_priority < TIPC_MIN_LINK_PRI) &&
+	    (bearer_priority > TIPC_MAX_LINK_PRI)) {
 		warn("Media registration error: priority %u\n", bearer_priority);
 		goto exit;
 	}
@@ -164,15 +165,15 @@
 	dbg("Media <%s> registered\n", name);
 	res = 0;
 exit:
-	write_unlock_bh(&net_lock);
+	write_unlock_bh(&tipc_net_lock);
 	return res;
 }
 
 /**
- * media_addr_printf - record media address in print buffer
+ * tipc_media_addr_printf - record media address in print buffer
  */
 
-void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
+void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
 {
 	struct media *m_ptr;
 	u32 media_type;
@@ -200,25 +201,25 @@
 }
 
 /**
- * media_get_names - record names of registered media in buffer
+ * tipc_media_get_names - record names of registered media in buffer
  */
 
-struct sk_buff *media_get_names(void)
+struct sk_buff *tipc_media_get_names(void)
 {
 	struct sk_buff *buf;
 	struct media *m_ptr;
 	int i;
 
-	buf = cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
+	buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
 	if (!buf)
 		return NULL;
 
-	read_lock_bh(&net_lock);
+	read_lock_bh(&tipc_net_lock);
 	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
-		cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name, 
-			       strlen(m_ptr->name) + 1);
+		tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name, 
+				    strlen(m_ptr->name) + 1);
 	}
-	read_unlock_bh(&net_lock);
+	read_unlock_bh(&tipc_net_lock);
 	return buf;
 }
 
@@ -282,7 +283,7 @@
 	struct bearer *b_ptr;
 	u32 i;
 
-	for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
+	for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
 		if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
 			return b_ptr;
 	}
@@ -290,16 +291,16 @@
 }
 
 /**
- * bearer_find - locates bearer object with matching interface name
+ * tipc_bearer_find_interface - locates bearer object with matching interface name
  */
 
-struct bearer *bearer_find_interface(const char *if_name)
+struct bearer *tipc_bearer_find_interface(const char *if_name)
 {
 	struct bearer *b_ptr;
 	char *b_if_name;
 	u32 i;
 
-	for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
+	for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
 		if (!b_ptr->active)
 			continue;
 		b_if_name = strchr(b_ptr->publ.name, ':') + 1;
@@ -310,54 +311,54 @@
 }
 
 /**
- * bearer_get_names - record names of bearers in buffer
+ * tipc_bearer_get_names - record names of bearers in buffer
  */
 
-struct sk_buff *bearer_get_names(void)
+struct sk_buff *tipc_bearer_get_names(void)
 {
 	struct sk_buff *buf;
 	struct media *m_ptr;
 	struct bearer *b_ptr;
 	int i, j;
 
-	buf = cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
+	buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
 	if (!buf)
 		return NULL;
 
-	read_lock_bh(&net_lock);
+	read_lock_bh(&tipc_net_lock);
 	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
 		for (j = 0; j < MAX_BEARERS; j++) {
-			b_ptr = &bearers[j];
+			b_ptr = &tipc_bearers[j];
 			if (b_ptr->active && (b_ptr->media == m_ptr)) {
-				cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, 
-					       b_ptr->publ.name, 
-					       strlen(b_ptr->publ.name) + 1);
+				tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, 
+						    b_ptr->publ.name, 
+						    strlen(b_ptr->publ.name) + 1);
 			}
 		}
 	}
-	read_unlock_bh(&net_lock);
+	read_unlock_bh(&tipc_net_lock);
 	return buf;
 }
 
-void bearer_add_dest(struct bearer *b_ptr, u32 dest)
+void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest)
 {
-	nmap_add(&b_ptr->nodes, dest);
-	disc_update_link_req(b_ptr->link_req);
-	bcbearer_sort();
+	tipc_nmap_add(&b_ptr->nodes, dest);
+	tipc_disc_update_link_req(b_ptr->link_req);
+	tipc_bcbearer_sort();
 }
 
-void bearer_remove_dest(struct bearer *b_ptr, u32 dest)
+void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest)
 {
-	nmap_remove(&b_ptr->nodes, dest);
-	disc_update_link_req(b_ptr->link_req);
-	bcbearer_sort();
+	tipc_nmap_remove(&b_ptr->nodes, dest);
+	tipc_disc_update_link_req(b_ptr->link_req);
+	tipc_bcbearer_sort();
 }
 
 /*
  * bearer_push(): Resolve bearer congestion. Force the waiting
  * links to push out their unsent packets, one packet per link
  * per iteration, until all packets are gone or congestion reoccurs.
- * 'net_lock' is read_locked when this function is called
+ * 'tipc_net_lock' is read_locked when this function is called
  * bearer.lock must be taken before calling
  * Returns binary true(1) ore false(0)
  */
@@ -371,7 +372,7 @@
 
 	while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
 		list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) {
-			res = link_push_packet(ln);
+			res = tipc_link_push_packet(ln);
 			if (res == PUSH_FAILED)
 				break;
 			if (res == PUSH_FINISHED)
@@ -381,7 +382,7 @@
 	return list_empty(&b_ptr->cong_links);
 }
 
-void bearer_lock_push(struct bearer *b_ptr)
+void tipc_bearer_lock_push(struct bearer *b_ptr)
 {
 	int res;
 
@@ -389,7 +390,7 @@
 	res = bearer_push(b_ptr);
 	spin_unlock_bh(&b_ptr->publ.lock);
 	if (res)
-		bcbearer_push();
+		tipc_bcbearer_push();
 }
 
 
@@ -404,7 +405,7 @@
 	spin_lock_bh(&b_ptr->publ.lock);
 	b_ptr->continue_count++;
 	if (!list_empty(&b_ptr->cong_links))
-		k_signal((Handler)bearer_lock_push, (unsigned long)b_ptr);
+		tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr);
 	b_ptr->publ.blocked = 0;
 	spin_unlock_bh(&b_ptr->publ.lock);
 }
@@ -413,11 +414,11 @@
  * Schedule link for sending of messages after the bearer 
  * has been deblocked by 'continue()'. This method is called 
  * when somebody tries to send a message via this link while 
- * the bearer is congested. 'net_lock' is in read_lock here
+ * the bearer is congested. 'tipc_net_lock' is in read_lock here
  * bearer.lock is busy
  */
 
-static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr)
+static void tipc_bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr)
 {
 	list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
 }
@@ -426,24 +427,24 @@
  * Schedule link for sending of messages after the bearer 
  * has been deblocked by 'continue()'. This method is called 
  * when somebody tries to send a message via this link while 
- * the bearer is congested. 'net_lock' is in read_lock here,
+ * the bearer is congested. 'tipc_net_lock' is in read_lock here,
  * bearer.lock is free
  */
 
-void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr)
+void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr)
 {
 	spin_lock_bh(&b_ptr->publ.lock);
-	bearer_schedule_unlocked(b_ptr, l_ptr);
+	tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
 	spin_unlock_bh(&b_ptr->publ.lock);
 }
 
 
 /*
- * bearer_resolve_congestion(): Check if there is bearer congestion,
+ * tipc_bearer_resolve_congestion(): Check if there is bearer congestion,
  * and if there is, try to resolve it before returning.
- * 'net_lock' is read_locked when this function is called
+ * 'tipc_net_lock' is read_locked when this function is called
  */
-int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)
+int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)
 {
 	int res = 1;
 
@@ -451,7 +452,7 @@
 		return 1;
 	spin_lock_bh(&b_ptr->publ.lock);
 	if (!bearer_push(b_ptr)) {
-		bearer_schedule_unlocked(b_ptr, l_ptr);
+		tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
 		res = 0;
 	}
 	spin_unlock_bh(&b_ptr->publ.lock);
@@ -476,14 +477,19 @@
 
 	if (tipc_mode != TIPC_NET_MODE)
 		return -ENOPROTOOPT;
+
 	if (!bearer_name_validate(name, &b_name) ||
-	    !addr_domain_valid(bcast_scope) ||
-	    !in_scope(bcast_scope, tipc_own_addr) ||
-	    (priority > TIPC_NUM_LINK_PRI))
+	    !tipc_addr_domain_valid(bcast_scope) ||
+	    !in_scope(bcast_scope, tipc_own_addr))
 		return -EINVAL;
 
-	write_lock_bh(&net_lock);
-	if (!bearers)
+	if ((priority < TIPC_MIN_LINK_PRI ||
+	     priority > TIPC_MAX_LINK_PRI) &&
+	    (priority != TIPC_MEDIA_LINK_PRI))
+		return -EINVAL;
+
+	write_lock_bh(&tipc_net_lock);
+	if (!tipc_bearers)
 		goto failed;
 
 	m_ptr = media_find(b_name.media_name);
@@ -491,22 +497,23 @@
 		warn("No media <%s>\n", b_name.media_name);
 		goto failed;
 	}
-	if (priority == TIPC_NUM_LINK_PRI)
+
+	if (priority == TIPC_MEDIA_LINK_PRI)
 		priority = m_ptr->priority;
 
 restart:
 	bearer_id = MAX_BEARERS;
 	with_this_prio = 1;
 	for (i = MAX_BEARERS; i-- != 0; ) {
-		if (!bearers[i].active) {
+		if (!tipc_bearers[i].active) {
 			bearer_id = i;
 			continue;
 		}
-		if (!strcmp(name, bearers[i].publ.name)) {
+		if (!strcmp(name, tipc_bearers[i].publ.name)) {
 			warn("Bearer <%s> already enabled\n", name);
 			goto failed;
 		}
-		if ((bearers[i].priority == priority) &&
+		if ((tipc_bearers[i].priority == priority) &&
 		    (++with_this_prio > 2)) {
 			if (priority-- == 0) {
 				warn("Third bearer <%s> with priority %u, unable to lower to %u\n",
@@ -523,7 +530,7 @@
 		goto failed;
 	}
 
-	b_ptr = &bearers[bearer_id];
+	b_ptr = &tipc_bearers[bearer_id];
 	memset(b_ptr, 0, sizeof(struct bearer));
 
 	strcpy(b_ptr->publ.name, name);
@@ -542,16 +549,16 @@
 	INIT_LIST_HEAD(&b_ptr->cong_links);
 	INIT_LIST_HEAD(&b_ptr->links);
 	if (m_ptr->bcast) {
-		b_ptr->link_req = disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
-						     bcast_scope, 2);
+		b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
+							  bcast_scope, 2);
 	}
 	b_ptr->publ.lock = SPIN_LOCK_UNLOCKED;
-	write_unlock_bh(&net_lock);
-	info("Enabled bearer <%s>, discovery domain %s\n",
-	     name, addr_string_fill(addr_string, bcast_scope));
+	write_unlock_bh(&tipc_net_lock);
+	info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
+	     name, addr_string_fill(addr_string, bcast_scope), priority);
 	return 0;
 failed:
-	write_unlock_bh(&net_lock);
+	write_unlock_bh(&tipc_net_lock);
 	return res;
 }
 
@@ -569,11 +576,11 @@
 	if (tipc_mode != TIPC_NET_MODE)
 		return -ENOPROTOOPT;
 
-	read_lock_bh(&net_lock);
+	read_lock_bh(&tipc_net_lock);
 	b_ptr = bearer_find(name);
 	if (!b_ptr) {
 		warn("Attempt to block unknown bearer <%s>\n", name);
-		read_unlock_bh(&net_lock);
+		read_unlock_bh(&tipc_net_lock);
 		return -EINVAL;
 	}
 
@@ -583,11 +590,11 @@
 		struct node *n_ptr = l_ptr->owner;
 
 		spin_lock_bh(&n_ptr->lock);
-		link_reset(l_ptr);
+		tipc_link_reset(l_ptr);
 		spin_unlock_bh(&n_ptr->lock);
 	}
 	spin_unlock_bh(&b_ptr->publ.lock);
-	read_unlock_bh(&net_lock);
+	read_unlock_bh(&tipc_net_lock);
 	info("Blocked bearer <%s>\n", name);
 	return TIPC_OK;
 }
@@ -595,7 +602,7 @@
 /**
  * bearer_disable -
  * 
- * Note: This routine assumes caller holds net_lock.
+ * Note: This routine assumes caller holds tipc_net_lock.
  */
 
 static int bearer_disable(const char *name)
@@ -613,19 +620,19 @@
 		return -EINVAL;
 	}
 
-	disc_stop_link_req(b_ptr->link_req);
+	tipc_disc_stop_link_req(b_ptr->link_req);
 	spin_lock_bh(&b_ptr->publ.lock);
 	b_ptr->link_req = NULL;
 	b_ptr->publ.blocked = 1;
 	if (b_ptr->media->disable_bearer) {
 		spin_unlock_bh(&b_ptr->publ.lock);
-		write_unlock_bh(&net_lock);
+		write_unlock_bh(&tipc_net_lock);
 		b_ptr->media->disable_bearer(&b_ptr->publ);
-		write_lock_bh(&net_lock);
+		write_lock_bh(&tipc_net_lock);
 		spin_lock_bh(&b_ptr->publ.lock);
 	}
 	list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
-		link_delete(l_ptr);
+		tipc_link_delete(l_ptr);
 	}
 	spin_unlock_bh(&b_ptr->publ.lock);
 	info("Disabled bearer <%s>\n", name);
@@ -637,54 +644,54 @@
 {
 	int res;
 
-	write_lock_bh(&net_lock);
+	write_lock_bh(&tipc_net_lock);
 	res = bearer_disable(name);
-	write_unlock_bh(&net_lock);
+	write_unlock_bh(&tipc_net_lock);
 	return res;
 }
 
 
 
-int bearer_init(void)
+int tipc_bearer_init(void)
 {
 	int res;
 
-	write_lock_bh(&net_lock);
-	bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC);
+	write_lock_bh(&tipc_net_lock);
+	tipc_bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC);
 	media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC);
-	if (bearers && media_list) {
-		memset(bearers, 0, MAX_BEARERS * sizeof(struct bearer));
+	if (tipc_bearers && media_list) {
+		memset(tipc_bearers, 0, MAX_BEARERS * sizeof(struct bearer));
 		memset(media_list, 0, MAX_MEDIA * sizeof(struct media));
 		res = TIPC_OK;
 	} else {
-		kfree(bearers);
+		kfree(tipc_bearers);
 		kfree(media_list);
-		bearers = 0;
+		tipc_bearers = 0;
 		media_list = 0;
 		res = -ENOMEM;
 	}
-	write_unlock_bh(&net_lock);
+	write_unlock_bh(&tipc_net_lock);
 	return res;
 }
 
-void bearer_stop(void)
+void tipc_bearer_stop(void)
 {
 	u32 i;
 
-	if (!bearers)
+	if (!tipc_bearers)
 		return;
 
 	for (i = 0; i < MAX_BEARERS; i++) {
-		if (bearers[i].active)
-			bearers[i].publ.blocked = 1;
+		if (tipc_bearers[i].active)
+			tipc_bearers[i].publ.blocked = 1;
 	}
 	for (i = 0; i < MAX_BEARERS; i++) {
-		if (bearers[i].active)
-			bearer_disable(bearers[i].publ.name);
+		if (tipc_bearers[i].active)
+			bearer_disable(tipc_bearers[i].publ.name);
 	}
-	kfree(bearers);
+	kfree(tipc_bearers);
 	kfree(media_list);
-	bearers = 0;
+	tipc_bearers = 0;
 	media_list = 0;
 	media_count = 0;
 }
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 21e63d3..c4e7c1c 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -37,7 +37,7 @@
 #ifndef _TIPC_BEARER_H
 #define _TIPC_BEARER_H
 
-#include <net/tipc/tipc_bearer.h>
+#include "core.h"
 #include "bcast.h"
 
 #define MAX_BEARERS 8
@@ -114,26 +114,24 @@
 
 struct link;
 
-extern struct bearer *bearers;
+extern struct bearer *tipc_bearers;
 
-void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);
-struct sk_buff *media_get_names(void);
+void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);
+struct sk_buff *tipc_media_get_names(void);
 
-struct sk_buff *bearer_get_names(void);
-void bearer_add_dest(struct bearer *b_ptr, u32 dest);
-void bearer_remove_dest(struct bearer *b_ptr, u32 dest);
-void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr);
-struct bearer *bearer_find_interface(const char *if_name);
-int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr);
-int bearer_init(void);
-void bearer_stop(void);
-int bearer_broadcast(struct sk_buff *buf, struct tipc_bearer *b_ptr,
-		     struct tipc_media_addr *dest);
-void bearer_lock_push(struct bearer *b_ptr);
+struct sk_buff *tipc_bearer_get_names(void);
+void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest);
+void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest);
+void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr);
+struct bearer *tipc_bearer_find_interface(const char *if_name);
+int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr);
+int tipc_bearer_init(void);
+void tipc_bearer_stop(void);
+void tipc_bearer_lock_push(struct bearer *b_ptr);
 
 
 /**
- * bearer_send- sends buffer to destination over bearer 
+ * tipc_bearer_send- sends buffer to destination over bearer 
  * 
  * Returns true (1) if successful, or false (0) if unable to send
  * 
@@ -150,23 +148,23 @@
  * and let TIPC's link code deal with the undelivered message. 
  */
 
-static inline int bearer_send(struct bearer *b_ptr, struct sk_buff *buf,
-			      struct tipc_media_addr *dest)
+static inline int tipc_bearer_send(struct bearer *b_ptr, struct sk_buff *buf,
+				   struct tipc_media_addr *dest)
 {
 	return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest);
 }
 
 /**
- * bearer_congested - determines if bearer is currently congested
+ * tipc_bearer_congested - determines if bearer is currently congested
  */
 
-static inline int bearer_congested(struct bearer *b_ptr, struct link *l_ptr)
+static inline int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr)
 {
 	if (unlikely(b_ptr->publ.blocked))
 		return 1;
 	if (likely(list_empty(&b_ptr->cong_links)))
 		return 0;
-	return !bearer_resolve_congestion(b_ptr, l_ptr);
+	return !tipc_bearer_resolve_congestion(b_ptr, l_ptr);
 }
 
 #endif
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c
index f0f7bac..ab974ca 100644
--- a/net/tipc/cluster.c
+++ b/net/tipc/cluster.c
@@ -44,15 +44,15 @@
 #include "msg.h"
 #include "bearer.h"
 
-void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, 
-		       u32 lower, u32 upper);
-struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest);
+void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf, 
+			 u32 lower, u32 upper);
+struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest);
 
-struct node **local_nodes = 0;
-struct node_map cluster_bcast_nodes = {0,{0,}};
-u32 highest_allowed_slave = 0;
+struct node **tipc_local_nodes = 0;
+struct node_map tipc_cltr_bcast_nodes = {0,{0,}};
+u32 tipc_highest_allowed_slave = 0;
 
-struct cluster *cluster_create(u32 addr)
+struct cluster *tipc_cltr_create(u32 addr)
 {
 	struct _zone *z_ptr;
 	struct cluster *c_ptr;
@@ -77,16 +77,16 @@
 	}
 	memset(c_ptr->nodes, 0, alloc);  
 	if (in_own_cluster(addr))
-		local_nodes = c_ptr->nodes;
+		tipc_local_nodes = c_ptr->nodes;
 	c_ptr->highest_slave = LOWEST_SLAVE - 1;
 	c_ptr->highest_node = 0;
 	
-	z_ptr = zone_find(tipc_zone(addr));
+	z_ptr = tipc_zone_find(tipc_zone(addr));
 	if (z_ptr == NULL) {
-		z_ptr = zone_create(addr);
+		z_ptr = tipc_zone_create(addr);
 	}
 	if (z_ptr != NULL) {
-		zone_attach_cluster(z_ptr, c_ptr);
+		tipc_zone_attach_cluster(z_ptr, c_ptr);
 		c_ptr->owner = z_ptr;
 	}
 	else {
@@ -97,23 +97,23 @@
 	return c_ptr;
 }
 
-void cluster_delete(struct cluster *c_ptr)
+void tipc_cltr_delete(struct cluster *c_ptr)
 {
 	u32 n_num;
 
 	if (!c_ptr)
 		return;
 	for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) {
-		node_delete(c_ptr->nodes[n_num]);
+		tipc_node_delete(c_ptr->nodes[n_num]);
 	}
 	for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) {
-		node_delete(c_ptr->nodes[n_num]);
+		tipc_node_delete(c_ptr->nodes[n_num]);
 	}
 	kfree(c_ptr->nodes);
 	kfree(c_ptr);
 }
 
-u32 cluster_next_node(struct cluster *c_ptr, u32 addr)
+u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr)
 {
 	struct node *n_ptr;
 	u32 n_num = tipc_node(addr) + 1;
@@ -122,24 +122,24 @@
 		return addr;
 	for (; n_num <= c_ptr->highest_node; n_num++) {
 		n_ptr = c_ptr->nodes[n_num];
-		if (n_ptr && node_has_active_links(n_ptr))
+		if (n_ptr && tipc_node_has_active_links(n_ptr))
 			return n_ptr->addr;
 	}
 	for (n_num = 1; n_num < tipc_node(addr); n_num++) {
 		n_ptr = c_ptr->nodes[n_num];
-		if (n_ptr && node_has_active_links(n_ptr))
+		if (n_ptr && tipc_node_has_active_links(n_ptr))
 			return n_ptr->addr;
 	}
 	return 0;
 }
 
-void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr)
+void tipc_cltr_attach_node(struct cluster *c_ptr, struct node *n_ptr)
 {
 	u32 n_num = tipc_node(n_ptr->addr);
 	u32 max_n_num = tipc_max_nodes;
 
 	if (in_own_cluster(n_ptr->addr))
-		max_n_num = highest_allowed_slave;
+		max_n_num = tipc_highest_allowed_slave;
 	assert(n_num > 0);
 	assert(n_num <= max_n_num);
 	assert(c_ptr->nodes[n_num] == 0);
@@ -149,12 +149,12 @@
 }
 
 /**
- * cluster_select_router - select router to a cluster
+ * tipc_cltr_select_router - select router to a cluster
  * 
  * Uses deterministic and fair algorithm.
  */
 
-u32 cluster_select_router(struct cluster *c_ptr, u32 ref)
+u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref)
 {
 	u32 n_num;
 	u32 ulim = c_ptr->highest_node;
@@ -174,29 +174,29 @@
 
 	/* Lookup upwards with wrap-around */
 	do {
-		if (node_is_up(c_ptr->nodes[n_num]))
+		if (tipc_node_is_up(c_ptr->nodes[n_num]))
 			break;
 	} while (++n_num <= ulim);
 	if (n_num > ulim) {
 		n_num = 1;
 		do {
-			if (node_is_up(c_ptr->nodes[n_num]))
+			if (tipc_node_is_up(c_ptr->nodes[n_num]))
 				break;
 		} while (++n_num < tstart);
 		if (n_num == tstart)
 			return 0;
 	}
 	assert(n_num <= ulim);
-	return node_select_router(c_ptr->nodes[n_num], ref);
+	return tipc_node_select_router(c_ptr->nodes[n_num], ref);
 }
 
 /**
- * cluster_select_node - select destination node within a remote cluster
+ * tipc_cltr_select_node - select destination node within a remote cluster
  * 
  * Uses deterministic and fair algorithm.
  */
 
-struct node *cluster_select_node(struct cluster *c_ptr, u32 selector)
+struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector)
 {
 	u32 n_num;
 	u32 mask = tipc_max_nodes;
@@ -215,11 +215,11 @@
 
 	/* Lookup upwards with wrap-around */
 	for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) {
-		if (node_has_active_links(c_ptr->nodes[n_num]))
+		if (tipc_node_has_active_links(c_ptr->nodes[n_num]))
 			return c_ptr->nodes[n_num];
 	}
 	for (n_num = 1; n_num < start_entry; n_num++) {
-		if (node_has_active_links(c_ptr->nodes[n_num]))
+		if (tipc_node_has_active_links(c_ptr->nodes[n_num]))
 			return c_ptr->nodes[n_num];
 	}
 	return 0;
@@ -229,7 +229,7 @@
  *    Routing table management: See description in node.c
  */
 
-struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest)
+struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest)
 {
 	u32 size = INT_H_SIZE + data_size;
 	struct sk_buff *buf = buf_acquire(size);
@@ -243,39 +243,39 @@
 	return buf;
 }
 
-void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest,
+void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest,
 			     u32 lower, u32 upper)
 {
-	struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr);
+	struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr);
 	struct tipc_msg *msg;
 
 	if (buf) {
 		msg = buf_msg(buf);
 		msg_set_remote_node(msg, dest);
 		msg_set_type(msg, ROUTE_ADDITION);
-		cluster_multicast(c_ptr, buf, lower, upper);
+		tipc_cltr_multicast(c_ptr, buf, lower, upper);
 	} else {
 		warn("Memory squeeze: broadcast of new route failed\n");
 	}
 }
 
-void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest,
-			      u32 lower, u32 upper)
+void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest,
+				u32 lower, u32 upper)
 {
-	struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr);
+	struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr);
 	struct tipc_msg *msg;
 
 	if (buf) {
 		msg = buf_msg(buf);
 		msg_set_remote_node(msg, dest);
 		msg_set_type(msg, ROUTE_REMOVAL);
-		cluster_multicast(c_ptr, buf, lower, upper);
+		tipc_cltr_multicast(c_ptr, buf, lower, upper);
 	} else {
 		warn("Memory squeeze: broadcast of lost route failed\n");
 	}
 }
 
-void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest)
+void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest)
 {
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
@@ -288,21 +288,21 @@
 	assert(in_own_cluster(c_ptr->addr));
 	if (highest <= LOWEST_SLAVE)
 		return;
-	buf = cluster_prepare_routing_msg(highest - LOWEST_SLAVE + 1,
-					  c_ptr->addr);
+	buf = tipc_cltr_prepare_routing_msg(highest - LOWEST_SLAVE + 1,
+					    c_ptr->addr);
 	if (buf) {
 		msg = buf_msg(buf);
 		msg_set_remote_node(msg, c_ptr->addr);
 		msg_set_type(msg, SLAVE_ROUTING_TABLE);
 		for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) {
 			if (c_ptr->nodes[n_num] && 
-			    node_has_active_links(c_ptr->nodes[n_num])) {
+			    tipc_node_has_active_links(c_ptr->nodes[n_num])) {
 				send = 1;
 				msg_set_dataoctet(msg, n_num);
 			}
 		}
 		if (send)
-			link_send(buf, dest, dest);
+			tipc_link_send(buf, dest, dest);
 		else
 			buf_discard(buf);
 	} else {
@@ -310,7 +310,7 @@
 	}
 }
 
-void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest)
+void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest)
 {
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
@@ -323,20 +323,20 @@
 	assert(!is_slave(dest));
 	assert(in_own_cluster(dest));
 	highest = c_ptr->highest_node;
-	buf = cluster_prepare_routing_msg(highest + 1, c_ptr->addr);
+	buf = tipc_cltr_prepare_routing_msg(highest + 1, c_ptr->addr);
 	if (buf) {
 		msg = buf_msg(buf);
 		msg_set_remote_node(msg, c_ptr->addr);
 		msg_set_type(msg, EXT_ROUTING_TABLE);
 		for (n_num = 1; n_num <= highest; n_num++) {
 			if (c_ptr->nodes[n_num] && 
-			    node_has_active_links(c_ptr->nodes[n_num])) {
+			    tipc_node_has_active_links(c_ptr->nodes[n_num])) {
 				send = 1;
 				msg_set_dataoctet(msg, n_num);
 			}
 		}
 		if (send)
-			link_send(buf, dest, dest);
+			tipc_link_send(buf, dest, dest);
 		else
 			buf_discard(buf);
 	} else {
@@ -344,7 +344,7 @@
 	}
 }
 
-void cluster_send_local_routes(struct cluster *c_ptr, u32 dest)
+void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest)
 {
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
@@ -354,20 +354,20 @@
 
 	assert(is_slave(dest));
 	assert(in_own_cluster(c_ptr->addr));
-	buf = cluster_prepare_routing_msg(highest, c_ptr->addr);
+	buf = tipc_cltr_prepare_routing_msg(highest, c_ptr->addr);
 	if (buf) {
 		msg = buf_msg(buf);
 		msg_set_remote_node(msg, c_ptr->addr);
 		msg_set_type(msg, LOCAL_ROUTING_TABLE);
 		for (n_num = 1; n_num <= highest; n_num++) {
 			if (c_ptr->nodes[n_num] && 
-			    node_has_active_links(c_ptr->nodes[n_num])) {
+			    tipc_node_has_active_links(c_ptr->nodes[n_num])) {
 				send = 1;
 				msg_set_dataoctet(msg, n_num);
 			}
 		}
 		if (send)
-			link_send(buf, dest, dest);
+			tipc_link_send(buf, dest, dest);
 		else
 			buf_discard(buf);
 	} else {
@@ -375,7 +375,7 @@
 	}
 }
 
-void cluster_recv_routing_table(struct sk_buff *buf)
+void tipc_cltr_recv_routing_table(struct sk_buff *buf)
 {
 	struct tipc_msg *msg = buf_msg(buf);
 	struct cluster *c_ptr;
@@ -388,9 +388,9 @@
 	u32 c_num;
 	u32 n_num;
 
-	c_ptr = cluster_find(rem_node);
+	c_ptr = tipc_cltr_find(rem_node);
 	if (!c_ptr) {
-		c_ptr = cluster_create(rem_node);
+		c_ptr = tipc_cltr_create(rem_node);
 		if (!c_ptr) {
 			buf_discard(buf);
 			return;
@@ -412,10 +412,10 @@
 				u32 addr = tipc_addr(z_num, c_num, n_num);
 				n_ptr = c_ptr->nodes[n_num];
 				if (!n_ptr) {
-					n_ptr = node_create(addr);
+					n_ptr = tipc_node_create(addr);
 				}
 				if (n_ptr)
-					node_add_router(n_ptr, router);
+					tipc_node_add_router(n_ptr, router);
 			}
 		}
 		break;
@@ -428,10 +428,10 @@
 				u32 addr = tipc_addr(z_num, c_num, slave_num);
 				n_ptr = c_ptr->nodes[slave_num];
 				if (!n_ptr) {
-					n_ptr = node_create(addr);
+					n_ptr = tipc_node_create(addr);
 				}
 				if (n_ptr)
-					node_add_router(n_ptr, router);
+					tipc_node_add_router(n_ptr, router);
 			}
 		}
 		break;
@@ -445,9 +445,9 @@
 		}
 		n_ptr = c_ptr->nodes[tipc_node(rem_node)];
 		if (!n_ptr)
-			n_ptr = node_create(rem_node);
+			n_ptr = tipc_node_create(rem_node);
 		if (n_ptr)
-			node_add_router(n_ptr, router);
+			tipc_node_add_router(n_ptr, router);
 		break;
 	case ROUTE_REMOVAL:
 		if (!is_slave(tipc_own_addr)) {
@@ -459,7 +459,7 @@
 		}
 		n_ptr = c_ptr->nodes[tipc_node(rem_node)];
 		if (n_ptr)
-			node_remove_router(n_ptr, router);
+			tipc_node_remove_router(n_ptr, router);
 		break;
 	default:
 		assert(!"Illegal routing manager message received\n");
@@ -467,7 +467,7 @@
 	buf_discard(buf);
 }
 
-void cluster_remove_as_router(struct cluster *c_ptr, u32 router)
+void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router)
 {
 	u32 start_entry;
 	u32 tstop;
@@ -486,17 +486,17 @@
 
 	for (n_num = start_entry; n_num <= tstop; n_num++) {
 		if (c_ptr->nodes[n_num]) {
-			node_remove_router(c_ptr->nodes[n_num], router);
+			tipc_node_remove_router(c_ptr->nodes[n_num], router);
 		}
 	}
 }
 
 /**
- * cluster_multicast - multicast message to local nodes 
+ * tipc_cltr_multicast - multicast message to local nodes 
  */
 
-void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, 
-		       u32 lower, u32 upper)
+void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf, 
+			 u32 lower, u32 upper)
 {
 	struct sk_buff *buf_copy;
 	struct node *n_ptr;
@@ -505,9 +505,9 @@
 
 	assert(lower <= upper);
 	assert(((lower >= 1) && (lower <= tipc_max_nodes)) ||
-	       ((lower >= LOWEST_SLAVE) && (lower <= highest_allowed_slave)));
+	       ((lower >= LOWEST_SLAVE) && (lower <= tipc_highest_allowed_slave)));
 	assert(((upper >= 1) && (upper <= tipc_max_nodes)) ||
-	       ((upper >= LOWEST_SLAVE) && (upper <= highest_allowed_slave)));
+	       ((upper >= LOWEST_SLAVE) && (upper <= tipc_highest_allowed_slave)));
 	assert(in_own_cluster(c_ptr->addr));
 
 	tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node;
@@ -515,22 +515,22 @@
 		tstop = upper;
 	for (n_num = lower; n_num <= tstop; n_num++) {
 		n_ptr = c_ptr->nodes[n_num];
-		if (n_ptr && node_has_active_links(n_ptr)) {
+		if (n_ptr && tipc_node_has_active_links(n_ptr)) {
 			buf_copy = skb_copy(buf, GFP_ATOMIC);
 			if (buf_copy == NULL)
 				break;
 			msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
-			link_send(buf_copy, n_ptr->addr, n_ptr->addr);
+			tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr);
 		}
 	}
 	buf_discard(buf);
 }
 
 /**
- * cluster_broadcast - broadcast message to all nodes within cluster
+ * tipc_cltr_broadcast - broadcast message to all nodes within cluster
  */
 
-void cluster_broadcast(struct sk_buff *buf)
+void tipc_cltr_broadcast(struct sk_buff *buf)
 {
 	struct sk_buff *buf_copy;
 	struct cluster *c_ptr;
@@ -541,7 +541,7 @@
 	u32 node_type;
 
 	if (tipc_mode == TIPC_NET_MODE) {
-		c_ptr = cluster_find(tipc_own_addr);
+		c_ptr = tipc_cltr_find(tipc_own_addr);
 		assert(in_own_cluster(c_ptr->addr));	/* For now */
 
 		/* Send to standard nodes, then repeat loop sending to slaves */
@@ -550,14 +550,14 @@
 		for (node_type = 1; node_type <= 2; node_type++) {
 			for (n_num = tstart; n_num <= tstop; n_num++) {
 				n_ptr = c_ptr->nodes[n_num];
-				if (n_ptr && node_has_active_links(n_ptr)) {
+				if (n_ptr && tipc_node_has_active_links(n_ptr)) {
 					buf_copy = skb_copy(buf, GFP_ATOMIC);
 					if (buf_copy == NULL)
 						goto exit;
 					msg_set_destnode(buf_msg(buf_copy), 
 							 n_ptr->addr);
-					link_send(buf_copy, n_ptr->addr, 
-						  n_ptr->addr);
+					tipc_link_send(buf_copy, n_ptr->addr, 
+						       n_ptr->addr);
 				}
 			}
 			tstart = LOWEST_SLAVE;
@@ -568,9 +568,9 @@
 	buf_discard(buf);
 }
 
-int cluster_init(void)
+int tipc_cltr_init(void)
 {
-	highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves;
-	return cluster_create(tipc_own_addr) ? TIPC_OK : -ENOMEM;
+	tipc_highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves;
+	return tipc_cltr_create(tipc_own_addr) ? TIPC_OK : -ENOMEM;
 }
 
diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h
index 1ffb095..9963642 100644
--- a/net/tipc/cluster.h
+++ b/net/tipc/cluster.h
@@ -60,29 +60,29 @@
 };
 
 
-extern struct node **local_nodes;
-extern u32 highest_allowed_slave;
-extern struct node_map cluster_bcast_nodes;
+extern struct node **tipc_local_nodes;
+extern u32 tipc_highest_allowed_slave;
+extern struct node_map tipc_cltr_bcast_nodes;
 
-void cluster_remove_as_router(struct cluster *c_ptr, u32 router);
-void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest);
-struct node *cluster_select_node(struct cluster *c_ptr, u32 selector);
-u32 cluster_select_router(struct cluster *c_ptr, u32 ref);
-void cluster_recv_routing_table(struct sk_buff *buf);
-struct cluster *cluster_create(u32 addr);
-void cluster_delete(struct cluster *c_ptr);
-void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr);
-void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest);
-void cluster_broadcast(struct sk_buff *buf);
-int cluster_init(void);
-u32 cluster_next_node(struct cluster *c_ptr, u32 addr);
-void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
-void cluster_send_local_routes(struct cluster *c_ptr, u32 dest);
-void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
+void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router);
+void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest);
+struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector);
+u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref);
+void tipc_cltr_recv_routing_table(struct sk_buff *buf);
+struct cluster *tipc_cltr_create(u32 addr);
+void tipc_cltr_delete(struct cluster *c_ptr);
+void tipc_cltr_attach_node(struct cluster *c_ptr, struct node *n_ptr);
+void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest);
+void tipc_cltr_broadcast(struct sk_buff *buf);
+int tipc_cltr_init(void);
+u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr);
+void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
+void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest);
+void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
 
-static inline struct cluster *cluster_find(u32 addr)
+static inline struct cluster *tipc_cltr_find(u32 addr)
 {
-	struct _zone *z_ptr = zone_find(addr);
+	struct _zone *z_ptr = tipc_zone_find(addr);
 
 	if (z_ptr)
 		return z_ptr->clusters[1];
diff --git a/net/tipc/config.c b/net/tipc/config.c
index 8ddef4f..3c8e674 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -70,13 +70,13 @@
 static int rep_headroom;		/* reply message headroom to use */
 
 
-void cfg_link_event(u32 addr, char *name, int up)
+void tipc_cfg_link_event(u32 addr, char *name, int up)
 {
 	/* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */
 }
 
 
-struct sk_buff *cfg_reply_alloc(int payload_size)
+struct sk_buff *tipc_cfg_reply_alloc(int payload_size)
 {
 	struct sk_buff *buf;
 
@@ -86,14 +86,14 @@
 	return buf;
 }
 
-int cfg_append_tlv(struct sk_buff *buf, int tlv_type, 
-		   void *tlv_data, int tlv_data_size)
+int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, 
+			void *tlv_data, int tlv_data_size)
 {
 	struct tlv_desc *tlv = (struct tlv_desc *)buf->tail;
 	int new_tlv_space = TLV_SPACE(tlv_data_size);
 
 	if (skb_tailroom(buf) < new_tlv_space) {
-		dbg("cfg_append_tlv unable to append TLV\n");
+		dbg("tipc_cfg_append_tlv unable to append TLV\n");
 		return 0;
 	}
 	skb_put(buf, new_tlv_space);
@@ -104,28 +104,28 @@
 	return 1;
 }
 
-struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value)
+struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value)
 {
 	struct sk_buff *buf;
 	u32 value_net;
 
-	buf = cfg_reply_alloc(TLV_SPACE(sizeof(value)));
+	buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value)));
 	if (buf) {
 		value_net = htonl(value);
-		cfg_append_tlv(buf, tlv_type, &value_net, 
-			       sizeof(value_net));
+		tipc_cfg_append_tlv(buf, tlv_type, &value_net, 
+				    sizeof(value_net));
 	}
 	return buf;
 }
 
-struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string)
+struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)
 {
 	struct sk_buff *buf;
 	int string_len = strlen(string) + 1;
 
-	buf = cfg_reply_alloc(TLV_SPACE(string_len));
+	buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len));
 	if (buf)
-		cfg_append_tlv(buf, tlv_type, string, string_len);
+		tipc_cfg_append_tlv(buf, tlv_type, string, string_len);
 	return buf;
 }
 
@@ -246,7 +246,7 @@
 	exit:
 	rmsg.result_len = htonl(msg_sect[1].iov_len);
 	rmsg.retval = htonl(rv);
-	cfg_respond(msg_sect, 2u, orig);
+	tipc_cfg_respond(msg_sect, 2u, orig);
 }
 #endif
 
@@ -255,26 +255,26 @@
 	struct tipc_bearer_config *args;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
 	if (tipc_enable_bearer(args->name,
 			       ntohl(args->detect_scope),
 			       ntohl(args->priority)))
-		return cfg_reply_error_string("unable to enable bearer");
+		return tipc_cfg_reply_error_string("unable to enable bearer");
 
-	return cfg_reply_none();
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_disable_bearer(void)
 {
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area)))
-		return cfg_reply_error_string("unable to disable bearer");
+		return tipc_cfg_reply_error_string("unable to disable bearer");
 
-	return cfg_reply_none();
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_own_addr(void)
@@ -282,25 +282,25 @@
 	u32 addr;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	addr = *(u32 *)TLV_DATA(req_tlv_area);
 	addr = ntohl(addr);
 	if (addr == tipc_own_addr)
-		return cfg_reply_none();
-	if (!addr_node_valid(addr))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (node address)");
+		return tipc_cfg_reply_none();
+	if (!tipc_addr_node_valid(addr))
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (node address)");
 	if (tipc_own_addr)
-		return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-					      " (cannot change node address once assigned)");
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+						   " (cannot change node address once assigned)");
 
 	spin_unlock_bh(&config_lock);
-	stop_net();
+	tipc_core_stop_net();
 	tipc_own_addr = addr;
-	start_net();
+	tipc_core_start_net();
 	spin_lock_bh(&config_lock);
-	return cfg_reply_none();
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_remote_mng(void)
@@ -308,12 +308,12 @@
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	tipc_remote_management = (value != 0);
-	return cfg_reply_none();
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_max_publications(void)
@@ -321,15 +321,15 @@
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	if (value != delimit(value, 1, 65535))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (max publications must be 1-65535)");
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (max publications must be 1-65535)");
 	tipc_max_publications = value;
-	return cfg_reply_none();
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_max_subscriptions(void)
@@ -337,15 +337,15 @@
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	if (value != delimit(value, 1, 65535))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (max subscriptions must be 1-65535");
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (max subscriptions must be 1-65535");
 	tipc_max_subscriptions = value;
-	return cfg_reply_none();
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_max_ports(void)
@@ -354,31 +354,31 @@
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	if (value != delimit(value, 127, 65535))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (max ports must be 127-65535)");
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (max ports must be 127-65535)");
 
 	if (value == tipc_max_ports)
-		return cfg_reply_none();
+		return tipc_cfg_reply_none();
 
 	if (atomic_read(&tipc_user_count) > 2)
-		return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-					      " (cannot change max ports while TIPC users exist)");
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+						   " (cannot change max ports while TIPC users exist)");
 
 	spin_unlock_bh(&config_lock);
 	orig_mode = tipc_get_mode();
 	if (orig_mode == TIPC_NET_MODE)
-		stop_net();
-	stop_core();
+		tipc_core_stop_net();
+	tipc_core_stop();
 	tipc_max_ports = value;
-	start_core();
+	tipc_core_start();
 	if (orig_mode == TIPC_NET_MODE)
-		start_net();
+		tipc_core_start_net();
 	spin_lock_bh(&config_lock);
-	return cfg_reply_none();
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *set_net_max(int value, int *parameter)
@@ -388,13 +388,13 @@
 	if (value != *parameter) {
 		orig_mode = tipc_get_mode();
 		if (orig_mode == TIPC_NET_MODE)
-			stop_net();
+			tipc_core_stop_net();
 		*parameter = value;
 		if (orig_mode == TIPC_NET_MODE)
-			start_net();
+			tipc_core_start_net();
 	}
 
-	return cfg_reply_none();
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_max_zones(void)
@@ -402,12 +402,12 @@
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	if (value != delimit(value, 1, 255))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (max zones must be 1-255)");
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (max zones must be 1-255)");
 	return set_net_max(value, &tipc_max_zones);
 }
 
@@ -416,13 +416,13 @@
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	if (value != 1)
-		return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-					      " (max clusters fixed at 1)");
-	return cfg_reply_none();
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+						   " (max clusters fixed at 1)");
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_max_nodes(void)
@@ -430,12 +430,12 @@
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	if (value != delimit(value, 8, 2047))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (max nodes must be 8-2047)");
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (max nodes must be 8-2047)");
 	return set_net_max(value, &tipc_max_nodes);
 }
 
@@ -444,13 +444,13 @@
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	if (value != 0)
-		return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-					      " (max secondary nodes fixed at 0)");
-	return cfg_reply_none();
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+						   " (max secondary nodes fixed at 0)");
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_netid(void)
@@ -458,22 +458,22 @@
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	if (value != delimit(value, 1, 9999))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (network id must be 1-9999)");
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (network id must be 1-9999)");
 
 	if (tipc_own_addr)
-		return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-					      " (cannot change network id once part of network)");
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+						   " (cannot change network id once part of network)");
 	
 	return set_net_max(value, &tipc_net_id);
 }
 
-struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
-			   int request_space, int reply_headroom)
+struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
+				int request_space, int reply_headroom)
 {
 	struct sk_buff *rep_tlv_buf;
 
@@ -490,19 +490,19 @@
 	if (likely(orig_node == tipc_own_addr)) {
 		/* command is permitted */
 	} else if (cmd >= 0x8000) {
-		rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-						     " (cannot be done remotely)");
+		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+							  " (cannot be done remotely)");
 		goto exit;
 	} else if (!tipc_remote_management) {
-		rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NO_REMOTE);
+		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE);
 		goto exit;
 	}
 	else if (cmd >= 0x4000) {
 		u32 domain = 0;
 
-		if ((nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) ||
+		if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) ||
 		    (domain != orig_node)) {
-			rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR);
+			rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR);
 			goto exit;
 		}
 	}
@@ -511,50 +511,50 @@
 
 	switch (cmd) {
 	case TIPC_CMD_NOOP:
-		rep_tlv_buf = cfg_reply_none();
+		rep_tlv_buf = tipc_cfg_reply_none();
 		break;
 	case TIPC_CMD_GET_NODES:
-		rep_tlv_buf = node_get_nodes(req_tlv_area, req_tlv_space);
+		rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space);
 		break;
 	case TIPC_CMD_GET_LINKS:
-		rep_tlv_buf = node_get_links(req_tlv_area, req_tlv_space);
+		rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space);
 		break;
 	case TIPC_CMD_SHOW_LINK_STATS:
-		rep_tlv_buf = link_cmd_show_stats(req_tlv_area, req_tlv_space);
+		rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space);
 		break;
 	case TIPC_CMD_RESET_LINK_STATS:
-		rep_tlv_buf = link_cmd_reset_stats(req_tlv_area, req_tlv_space);
+		rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space);
 		break;
 	case TIPC_CMD_SHOW_NAME_TABLE:
-		rep_tlv_buf = nametbl_get(req_tlv_area, req_tlv_space);
+		rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space);
 		break;
 	case TIPC_CMD_GET_BEARER_NAMES:
-		rep_tlv_buf = bearer_get_names();
+		rep_tlv_buf = tipc_bearer_get_names();
 		break;
 	case TIPC_CMD_GET_MEDIA_NAMES:
-		rep_tlv_buf = media_get_names();
+		rep_tlv_buf = tipc_media_get_names();
 		break;
 	case TIPC_CMD_SHOW_PORTS:
-		rep_tlv_buf = port_get_ports();
+		rep_tlv_buf = tipc_port_get_ports();
 		break;
 #if 0
 	case TIPC_CMD_SHOW_PORT_STATS:
 		rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space);
 		break;
 	case TIPC_CMD_RESET_PORT_STATS:
-		rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED);
+		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED);
 		break;
 #endif
 	case TIPC_CMD_SET_LOG_SIZE:
-		rep_tlv_buf = log_resize(req_tlv_area, req_tlv_space);
+		rep_tlv_buf = tipc_log_resize(req_tlv_area, req_tlv_space);
 		break;
 	case TIPC_CMD_DUMP_LOG:
-		rep_tlv_buf = log_dump();
+		rep_tlv_buf = tipc_log_dump();
 		break;
 	case TIPC_CMD_SET_LINK_TOL:
 	case TIPC_CMD_SET_LINK_PRI:
 	case TIPC_CMD_SET_LINK_WINDOW:
-		rep_tlv_buf = link_cmd_config(req_tlv_area, req_tlv_space, cmd);
+		rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd);
 		break;
 	case TIPC_CMD_ENABLE_BEARER:
 		rep_tlv_buf = cfg_enable_bearer();
@@ -593,31 +593,31 @@
 		rep_tlv_buf = cfg_set_netid();
 		break;
 	case TIPC_CMD_GET_REMOTE_MNG:
-		rep_tlv_buf = cfg_reply_unsigned(tipc_remote_management);
+		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management);
 		break;
 	case TIPC_CMD_GET_MAX_PORTS:
-		rep_tlv_buf = cfg_reply_unsigned(tipc_max_ports);
+		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports);
 		break;
 	case TIPC_CMD_GET_MAX_PUBL:
-		rep_tlv_buf = cfg_reply_unsigned(tipc_max_publications);
+		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications);
 		break;
 	case TIPC_CMD_GET_MAX_SUBSCR:
-		rep_tlv_buf = cfg_reply_unsigned(tipc_max_subscriptions);
+		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions);
 		break;
 	case TIPC_CMD_GET_MAX_ZONES:
-		rep_tlv_buf = cfg_reply_unsigned(tipc_max_zones);
+		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_zones);
 		break;
 	case TIPC_CMD_GET_MAX_CLUSTERS:
-		rep_tlv_buf = cfg_reply_unsigned(tipc_max_clusters);
+		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_clusters);
 		break;
 	case TIPC_CMD_GET_MAX_NODES:
-		rep_tlv_buf = cfg_reply_unsigned(tipc_max_nodes);
+		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes);
 		break;
 	case TIPC_CMD_GET_MAX_SLAVES:
-		rep_tlv_buf = cfg_reply_unsigned(tipc_max_slaves);
+		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_slaves);
 		break;
 	case TIPC_CMD_GET_NETID:
-		rep_tlv_buf = cfg_reply_unsigned(tipc_net_id);
+		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
 		break;
 	default:
 		rep_tlv_buf = NULL;
@@ -655,11 +655,11 @@
 
 	/* Generate reply for request (if can't, return request) */
 
-	rep_buf = cfg_do_cmd(orig->node,
-			     ntohs(req_hdr->tcm_type), 
-			     msg + sizeof(*req_hdr),
-			     size - sizeof(*req_hdr),
-			     BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr));
+	rep_buf = tipc_cfg_do_cmd(orig->node,
+				  ntohs(req_hdr->tcm_type), 
+				  msg + sizeof(*req_hdr),
+				  size - sizeof(*req_hdr),
+				  BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr));
 	if (rep_buf) {
 		skb_push(rep_buf, sizeof(*rep_hdr));
 		rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data;
@@ -675,7 +675,7 @@
 	tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len);
 }
 
-int cfg_init(void)
+int tipc_cfg_init(void)
 {
 	struct tipc_name_seq seq;
 	int res;
@@ -696,7 +696,7 @@
 
 	seq.type = TIPC_CFG_SRV;
 	seq.lower = seq.upper = tipc_own_addr;
-	res = nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq);
+	res = tipc_nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq);
 	if (res)
 		goto failed;
 
@@ -709,7 +709,7 @@
 	return res;
 }
 
-void cfg_stop(void)
+void tipc_cfg_stop(void)
 {
 	if (mng.user_ref) {
 		tipc_detach(mng.user_ref);
diff --git a/net/tipc/config.h b/net/tipc/config.h
index 646377d..7a728f9 100644
--- a/net/tipc/config.h
+++ b/net/tipc/config.h
@@ -39,42 +39,41 @@
 
 /* ---------------------------------------------------------------------- */
 
-#include <linux/tipc.h>
-#include <linux/tipc_config.h>
+#include "core.h"
 #include "link.h"
 
-struct sk_buff *cfg_reply_alloc(int payload_size);
-int cfg_append_tlv(struct sk_buff *buf, int tlv_type, 
-		   void *tlv_data, int tlv_data_size);
-struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value);
-struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string);
+struct sk_buff *tipc_cfg_reply_alloc(int payload_size);
+int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, 
+			void *tlv_data, int tlv_data_size);
+struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value);
+struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string);
 
-static inline struct sk_buff *cfg_reply_none(void)
+static inline struct sk_buff *tipc_cfg_reply_none(void)
 {
-	return cfg_reply_alloc(0);
+	return tipc_cfg_reply_alloc(0);
 }
 
-static inline struct sk_buff *cfg_reply_unsigned(u32 value)
+static inline struct sk_buff *tipc_cfg_reply_unsigned(u32 value)
 {
-	return cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
+	return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
 }
 
-static inline struct sk_buff *cfg_reply_error_string(char *string)
+static inline struct sk_buff *tipc_cfg_reply_error_string(char *string)
 {
-	return cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string);
+	return tipc_cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string);
 }
 
-static inline struct sk_buff *cfg_reply_ultra_string(char *string)
+static inline struct sk_buff *tipc_cfg_reply_ultra_string(char *string)
 {
-	return cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string);
+	return tipc_cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string);
 }
 
-struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, 
-			   const void *req_tlv_area, int req_tlv_space, 
-			   int headroom);
+struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, 
+				const void *req_tlv_area, int req_tlv_space, 
+				int headroom);
 
-void cfg_link_event(u32 addr, char *name, int up);
-int  cfg_init(void);
-void cfg_stop(void);
+void tipc_cfg_link_event(u32 addr, char *name, int up);
+int  tipc_cfg_init(void);
+void tipc_cfg_stop(void);
 
 #endif
diff --git a/net/tipc/core.c b/net/tipc/core.c
index e83ac06..3d0a8ee 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -37,7 +37,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/random.h>
 
 #include "core.h"
@@ -49,14 +48,14 @@
 #include "subscr.h"
 #include "config.h"
 
-int  eth_media_start(void);
-void eth_media_stop(void);
-int  handler_start(void);
-void handler_stop(void);
-int  socket_init(void);
-void socket_stop(void);
-int  netlink_start(void);
-void netlink_stop(void);
+int  tipc_eth_media_start(void);
+void tipc_eth_media_stop(void);
+int  tipc_handler_start(void);
+void tipc_handler_stop(void);
+int  tipc_socket_init(void);
+void tipc_socket_stop(void);
+int  tipc_netlink_start(void);
+void tipc_netlink_stop(void);
 
 #define MOD_NAME "tipc_start: "
 
@@ -113,56 +112,56 @@
 }
 
 /**
- * stop_net - shut down TIPC networking sub-systems
+ * tipc_core_stop_net - shut down TIPC networking sub-systems
  */
 
-void stop_net(void)
+void tipc_core_stop_net(void)
 {
-	eth_media_stop();
-	tipc_stop_net();
+	tipc_eth_media_stop();
+	tipc_net_stop();
 }
 
 /**
  * start_net - start TIPC networking sub-systems
  */
 
-int start_net(void)
+int tipc_core_start_net(void)
 {
 	int res;
 
-	if ((res = tipc_start_net()) ||
-	    (res = eth_media_start())) {
-		stop_net();
+	if ((res = tipc_net_start()) ||
+	    (res = tipc_eth_media_start())) {
+		tipc_core_stop_net();
 	}
 	return res;
 }
 
 /**
- * stop_core - switch TIPC from SINGLE NODE to NOT RUNNING mode
+ * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode
  */
 
-void stop_core(void)
+void tipc_core_stop(void)
 {
 	if (tipc_mode != TIPC_NODE_MODE)
 		return;
 
 	tipc_mode = TIPC_NOT_RUNNING;
 
-	netlink_stop();
-	handler_stop();
-	cfg_stop();
-	subscr_stop();
-	reg_stop();
-	nametbl_stop();
-	ref_table_stop();
-	socket_stop();
+	tipc_netlink_stop();
+	tipc_handler_stop();
+	tipc_cfg_stop();
+	tipc_subscr_stop();
+	tipc_reg_stop();
+	tipc_nametbl_stop();
+	tipc_ref_table_stop();
+	tipc_socket_stop();
 }
 
 /**
- * start_core - switch TIPC from NOT RUNNING to SINGLE NODE mode
+ * tipc_core_start - switch TIPC from NOT RUNNING to SINGLE NODE mode
  */
 
-int start_core(void)
+int tipc_core_start(void)
 {
 	int res;
 
@@ -172,16 +171,16 @@
 	get_random_bytes(&tipc_random, sizeof(tipc_random));
 	tipc_mode = TIPC_NODE_MODE;
 
-	if ((res = handler_start()) || 
-	    (res = ref_table_init(tipc_max_ports + tipc_max_subscriptions,
-				  tipc_random)) ||
-	    (res = reg_start()) ||
-	    (res = nametbl_init()) ||
-            (res = k_signal((Handler)subscr_start, 0)) ||
-	    (res = k_signal((Handler)cfg_init, 0)) || 
-	    (res = netlink_start()) ||
-	    (res = socket_init())) {
-		stop_core();
+	if ((res = tipc_handler_start()) || 
+	    (res = tipc_ref_table_init(tipc_max_ports + tipc_max_subscriptions,
+				       tipc_random)) ||
+	    (res = tipc_reg_start()) ||
+	    (res = tipc_nametbl_init()) ||
+            (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) ||
+	    (res = tipc_k_signal((Handler)tipc_cfg_init, 0)) || 
+	    (res = tipc_netlink_start()) ||
+	    (res = tipc_socket_init())) {
+		tipc_core_stop();
 	}
 	return res;
 }
@@ -191,7 +190,7 @@
 {
 	int res;
 
-	log_reinit(CONFIG_TIPC_LOG);
+	tipc_log_reinit(CONFIG_TIPC_LOG);
 	info("Activated (compiled " __DATE__ " " __TIME__ ")\n");
 
 	tipc_own_addr = 0;
@@ -205,7 +204,7 @@
 	tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047);
 	tipc_net_id = 4711;
 
-	if ((res = start_core()))
+	if ((res = tipc_core_start()))
 		err("Unable to start in single node mode\n");
 	else	
 		info("Started in single node mode\n");
@@ -214,10 +213,10 @@
 
 static void __exit tipc_exit(void)
 {
-	stop_net();
-	stop_core();
+	tipc_core_stop_net();
+	tipc_core_stop();
 	info("Deactivated\n");
-	log_stop();
+	tipc_log_stop();
 }
 
 module_init(tipc_init);
diff --git a/net/tipc/core.h b/net/tipc/core.h
index b69b60b..1f2e8b2 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -37,6 +37,11 @@
 #ifndef _TIPC_CORE_H
 #define _TIPC_CORE_H
 
+#include <linux/tipc.h>
+#include <linux/tipc_config.h>
+#include <net/tipc/tipc_msg.h>
+#include <net/tipc/tipc_port.h>
+#include <net/tipc/tipc_bearer.h>
 #include <net/tipc/tipc.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -60,9 +65,9 @@
 #define assert(i)  BUG_ON(!(i))
 
 struct tipc_msg;
-extern struct print_buf *CONS, *LOG;
-extern struct print_buf *TEE(struct print_buf *, struct print_buf *);
-void msg_print(struct print_buf*,struct tipc_msg *,const char*);
+extern struct print_buf *TIPC_CONS, *TIPC_LOG;
+extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *);
+void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*);
 void tipc_printf(struct print_buf *, const char *fmt, ...);
 void tipc_dump(struct print_buf*,const char *fmt, ...);
 
@@ -79,7 +84,7 @@
 #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg)
 
 #define dbg(fmt, arg...)  do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
-#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) msg_print(DBG_OUTPUT, msg, txt);} while(0)
+#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
 #define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
 
 
@@ -89,15 +94,15 @@
  * here, or on a per .c file basis, by redefining these symbols.  The following
  * print buffer options are available:
  *
- * NULL			: Output to null print buffer (i.e. print nowhere)
- * CONS			: Output to system console
- * LOG			: Output to TIPC log buffer 
- * &buf 		: Output to user-defined buffer (struct print_buf *)
- * TEE(&buf_a,&buf_b)	: Output to two print buffers (eg. TEE(CONS,LOG) )
+ * NULL				: Output to null print buffer (i.e. print nowhere)
+ * TIPC_CONS			: Output to system console
+ * TIPC_LOG			: Output to TIPC log buffer 
+ * &buf				: Output to user-defined buffer (struct print_buf *)
+ * TIPC_TEE(&buf_a,&buf_b)	: Output to two print buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG) )
  */
 
 #ifndef TIPC_OUTPUT
-#define TIPC_OUTPUT TEE(CONS,LOG)
+#define TIPC_OUTPUT TIPC_TEE(TIPC_CONS,TIPC_LOG)
 #endif
 
 #ifndef DBG_OUTPUT
@@ -162,10 +167,10 @@
  * Routines available to privileged subsystems
  */
 
-extern int  start_core(void);
-extern void stop_core(void);
-extern int  start_net(void);
-extern void stop_net(void);
+extern int  tipc_core_start(void);
+extern void tipc_core_stop(void);
+extern int  tipc_core_start_net(void);
+extern void tipc_core_stop_net(void);
 
 static inline int delimit(int val, int min, int max)
 {
@@ -183,7 +188,7 @@
 
 typedef void (*Handler) (unsigned long);
 
-u32 k_signal(Handler routine, unsigned long argument);
+u32 tipc_k_signal(Handler routine, unsigned long argument);
 
 /**
  * k_init_timer - initialize a timer
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index 7ed60a1..4f4beef 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -44,10 +44,10 @@
 static spinlock_t print_lock = SPIN_LOCK_UNLOCKED;
 
 static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
-struct print_buf *CONS = &cons_buf;
+struct print_buf *TIPC_CONS = &cons_buf;
 
 static struct print_buf log_buf = { NULL, 0, NULL, NULL };
-struct print_buf *LOG = &log_buf;
+struct print_buf *TIPC_LOG = &log_buf;
 
 
 #define FORMAT(PTR,LEN,FMT) \
@@ -66,15 +66,15 @@
  *    simultaneous use of the print buffer(s) being manipulated.
  * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of
  *    'print_string' and to protect its print buffer(s).
- * 3) TEE() uses 'print_lock' to protect its print buffer(s).
- * 4) Routines of the form log_XXX() uses 'print_lock' to protect LOG.
+ * 3) TIPC_TEE() uses 'print_lock' to protect its print buffer(s).
+ * 4) Routines of the form log_XXX() uses 'print_lock' to protect TIPC_LOG.
  */
 
 /**
- * printbuf_init - initialize print buffer to empty
+ * tipc_printbuf_init - initialize print buffer to empty
  */
 
-void printbuf_init(struct print_buf *pb, char *raw, u32 sz)
+void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz)
 {
 	if (!pb || !raw || (sz < (MAX_STRING + 1)))
 		return;
@@ -87,26 +87,26 @@
 }
 
 /**
- * printbuf_reset - reinitialize print buffer to empty state
+ * tipc_printbuf_reset - reinitialize print buffer to empty state
  */
 
-void printbuf_reset(struct print_buf *pb)
+void tipc_printbuf_reset(struct print_buf *pb)
 {
 	if (pb && pb->buf)
-		printbuf_init(pb, pb->buf, pb->size);
+		tipc_printbuf_init(pb, pb->buf, pb->size);
 }
 
 /**
- * printbuf_empty - test if print buffer is in empty state
+ * tipc_printbuf_empty - test if print buffer is in empty state
  */
 
-int printbuf_empty(struct print_buf *pb)
+int tipc_printbuf_empty(struct print_buf *pb)
 {
 	return (!pb || !pb->buf || (pb->crs == pb->buf));
 }
 
 /**
- * printbuf_validate - check for print buffer overflow
+ * tipc_printbuf_validate - check for print buffer overflow
  * 
  * Verifies that a print buffer has captured all data written to it. 
  * If data has been lost, linearize buffer and prepend an error message
@@ -114,7 +114,7 @@
  * Returns length of print buffer data string (including trailing NULL)
  */
 
-int printbuf_validate(struct print_buf *pb)
+int tipc_printbuf_validate(struct print_buf *pb)
 {
         char *err = "             *** PRINT BUFFER WRAPPED AROUND ***\n";
         char *cp_buf;
@@ -126,13 +126,13 @@
 	if (pb->buf[pb->size - 1] == '\0') {
                 cp_buf = kmalloc(pb->size, GFP_ATOMIC);
                 if (cp_buf != NULL){
-                        printbuf_init(&cb, cp_buf, pb->size);
-                        printbuf_move(&cb, pb);
-                        printbuf_move(pb, &cb);
+                        tipc_printbuf_init(&cb, cp_buf, pb->size);
+                        tipc_printbuf_move(&cb, pb);
+                        tipc_printbuf_move(pb, &cb);
                         kfree(cp_buf);
                         memcpy(pb->buf, err, strlen(err));
                 } else {
-                        printbuf_reset(pb);
+                        tipc_printbuf_reset(pb);
                         tipc_printf(pb, err);
                 }
 	}
@@ -140,13 +140,13 @@
 }
 
 /**
- * printbuf_move - move print buffer contents to another print buffer
+ * tipc_printbuf_move - move print buffer contents to another print buffer
  * 
  * Current contents of destination print buffer (if any) are discarded.
  * Source print buffer becomes empty if a successful move occurs.
  */
 
-void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
+void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
 {
 	int len;
 
@@ -156,12 +156,12 @@
 		return;
 
 	if (!pb_from || !pb_from->buf) {
-		printbuf_reset(pb_to);
+		tipc_printbuf_reset(pb_to);
 		return;
 	}
 
 	if (pb_to->size < pb_from->size) {
-		printbuf_reset(pb_to);
+		tipc_printbuf_reset(pb_to);
 		tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***");
 		return;
 	}
@@ -179,7 +179,7 @@
 	strcpy(pb_to->crs, pb_from->buf);
 	pb_to->crs += len;
 
-	printbuf_reset(pb_from);
+	tipc_printbuf_reset(pb_from);
 }
 
 /**
@@ -199,7 +199,7 @@
 		strcpy(print_string, "*** STRING TOO LONG ***");
 
 	while (pb) {
-		if (pb == CONS)
+		if (pb == TIPC_CONS)
 			printk(print_string);
 		else if (pb->buf) {
 			chars_left = pb->buf + pb->size - pb->crs - 1;
@@ -223,10 +223,10 @@
 }
 
 /**
- * TEE - perform next output operation on both print buffers  
+ * TIPC_TEE - perform next output operation on both print buffers  
  */
 
-struct print_buf *TEE(struct print_buf *b0, struct print_buf *b1)
+struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
 {
 	struct print_buf *pb = b0;
 
@@ -294,96 +294,96 @@
 	int len;
 
 	spin_lock_bh(&print_lock);
-	FORMAT(CONS->buf, len, fmt);
-	printk(CONS->buf);
+	FORMAT(TIPC_CONS->buf, len, fmt);
+	printk(TIPC_CONS->buf);
 
 	for (; pb; pb = pb->next) {
-		if (pb == CONS)
+		if (pb == TIPC_CONS)
 			continue;
 		printk("\n---- Start of dump,%s log ----\n\n", 
-		       (pb == LOG) ? "global" : "local");
+		       (pb == TIPC_LOG) ? "global" : "local");
 		printbuf_dump(pb);
-		printbuf_reset(pb);
+		tipc_printbuf_reset(pb);
 		printk("\n-------- End of dump --------\n");
 	}
 	spin_unlock_bh(&print_lock);
 }
 
 /**
- * log_stop - free up TIPC log print buffer 
+ * tipc_log_stop - free up TIPC log print buffer 
  */
 
-void log_stop(void)
+void tipc_log_stop(void)
 {
 	spin_lock_bh(&print_lock);
-	if (LOG->buf) {
-		kfree(LOG->buf);
-		LOG->buf = NULL;
+	if (TIPC_LOG->buf) {
+		kfree(TIPC_LOG->buf);
+		TIPC_LOG->buf = NULL;
 	}
 	spin_unlock_bh(&print_lock);
 }
 
 /**
- * log_reinit - set TIPC log print buffer to specified size
+ * tipc_log_reinit - set TIPC log print buffer to specified size
  */
 
-void log_reinit(int log_size)
+void tipc_log_reinit(int log_size)
 {
-	log_stop();
+	tipc_log_stop();
 
 	if (log_size) {
 		if (log_size <= MAX_STRING)
 			log_size = MAX_STRING + 1;
 		spin_lock_bh(&print_lock);
-		printbuf_init(LOG, kmalloc(log_size, GFP_ATOMIC), log_size);
+		tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), log_size);
 		spin_unlock_bh(&print_lock);
 	}
 }
 
 /**
- * log_resize - reconfigure size of TIPC log buffer
+ * tipc_log_resize - reconfigure size of TIPC log buffer
  */
 
-struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space)
+struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space)
 {
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
 	if (value != delimit(value, 0, 32768))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (log size must be 0-32768)");
-	log_reinit(value);
-	return cfg_reply_none();
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (log size must be 0-32768)");
+	tipc_log_reinit(value);
+	return tipc_cfg_reply_none();
 }
 
 /**
- * log_dump - capture TIPC log buffer contents in configuration message
+ * tipc_log_dump - capture TIPC log buffer contents in configuration message
  */
 
-struct sk_buff *log_dump(void)
+struct sk_buff *tipc_log_dump(void)
 {
 	struct sk_buff *reply;
 
 	spin_lock_bh(&print_lock);
-	if (!LOG->buf)
-		reply = cfg_reply_ultra_string("log not activated\n");
-	else if (printbuf_empty(LOG))
-		reply = cfg_reply_ultra_string("log is empty\n");
+	if (!TIPC_LOG->buf)
+		reply = tipc_cfg_reply_ultra_string("log not activated\n");
+	else if (tipc_printbuf_empty(TIPC_LOG))
+		reply = tipc_cfg_reply_ultra_string("log is empty\n");
 	else {
 		struct tlv_desc *rep_tlv;
 		struct print_buf pb;
 		int str_len;
 
-		str_len = min(LOG->size, 32768u);
-		reply = cfg_reply_alloc(TLV_SPACE(str_len));
+		str_len = min(TIPC_LOG->size, 32768u);
+		reply = tipc_cfg_reply_alloc(TLV_SPACE(str_len));
 		if (reply) {
 			rep_tlv = (struct tlv_desc *)reply->data;
-			printbuf_init(&pb, TLV_DATA(rep_tlv), str_len);
-			printbuf_move(&pb, LOG);
+			tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), str_len);
+			tipc_printbuf_move(&pb, TIPC_LOG);
 			str_len = strlen(TLV_DATA(rep_tlv)) + 1;
 			skb_put(reply, TLV_SPACE(str_len));
 			TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
index c6b2a64..227f050 100644
--- a/net/tipc/dbg.h
+++ b/net/tipc/dbg.h
@@ -44,16 +44,16 @@
 	struct print_buf *next;
 };
 
-void printbuf_init(struct print_buf *pb, char *buf, u32 sz);
-void printbuf_reset(struct print_buf *pb);
-int  printbuf_empty(struct print_buf *pb);
-int  printbuf_validate(struct print_buf *pb);
-void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from);
+void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 sz);
+void tipc_printbuf_reset(struct print_buf *pb);
+int  tipc_printbuf_empty(struct print_buf *pb);
+int  tipc_printbuf_validate(struct print_buf *pb);
+void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from);
 
-void log_reinit(int log_size);
-void log_stop(void);
+void tipc_log_reinit(int log_size);
+void tipc_log_stop(void);
 
-struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space);
-struct sk_buff *log_dump(void);
+struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space);
+struct sk_buff *tipc_log_dump(void);
 
 #endif
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index b106ef1..53ba463 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -93,7 +93,7 @@
  * disc_lost_link(): A link has lost contact
  */
 
-void disc_link_event(u32 addr, char *name, int up) 
+void tipc_disc_link_event(u32 addr, char *name, int up) 
 {
 	if (in_own_cluster(addr))
 		return;
@@ -103,17 +103,17 @@
 }
 
 /** 
- * disc_init_msg - initialize a link setup message
+ * tipc_disc_init_msg - initialize a link setup message
  * @type: message type (request or response)
  * @req_links: number of links associated with message
  * @dest_domain: network domain of node(s) which should respond to message
  * @b_ptr: ptr to bearer issuing message
  */
 
-struct sk_buff *disc_init_msg(u32 type,
-			      u32 req_links,
-			      u32 dest_domain,
-			      struct bearer *b_ptr)
+struct sk_buff *tipc_disc_init_msg(u32 type,
+				   u32 req_links,
+				   u32 dest_domain,
+				   struct bearer *b_ptr)
 {
 	struct sk_buff *buf = buf_acquire(DSC_H_SIZE);
 	struct tipc_msg *msg;
@@ -132,11 +132,11 @@
 }
 
 /**
- * disc_recv_msg - handle incoming link setup message (request or response)
+ * tipc_disc_recv_msg - handle incoming link setup message (request or response)
  * @buf: buffer containing message
  */
 
-void disc_recv_msg(struct sk_buff *buf)
+void tipc_disc_recv_msg(struct sk_buff *buf)
 {
 	struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle;
 	struct link *link;
@@ -153,9 +153,9 @@
 
 	if (net_id != tipc_net_id)
 		return;
-	if (!addr_domain_valid(dest))
+	if (!tipc_addr_domain_valid(dest))
 		return;
-	if (!addr_node_valid(orig))
+	if (!tipc_addr_node_valid(orig))
 		return;
 	if (orig == tipc_own_addr)
 		return;
@@ -169,11 +169,11 @@
 		/* Always accept link here */
 		struct sk_buff *rbuf;
 		struct tipc_media_addr *addr;
-		struct node *n_ptr = node_find(orig);
+		struct node *n_ptr = tipc_node_find(orig);
 		int link_up;
 		dbg(" in own cluster\n");
 		if (n_ptr == NULL) {
-			n_ptr = node_create(orig);
+			n_ptr = tipc_node_create(orig);
 		}
 		if (n_ptr == NULL) {
 			warn("Memory squeeze; Failed to create node\n");
@@ -183,7 +183,7 @@
 		link = n_ptr->links[b_ptr->identity];
 		if (!link) {
 			dbg("creating link\n");
-			link = link_create(b_ptr, orig, &media_addr);
+			link = tipc_link_create(b_ptr, orig, &media_addr);
 			if (!link) {
 				spin_unlock_bh(&n_ptr->lock);                
 				return;
@@ -196,13 +196,13 @@
 			warn("New bearer address for %s\n", 
 			     addr_string_fill(addr_string, orig));
 			memcpy(addr, &media_addr, sizeof(*addr));
-			link_reset(link);     
+			tipc_link_reset(link);     
 		}
-		link_up = link_is_up(link);
+		link_up = tipc_link_is_up(link);
 		spin_unlock_bh(&n_ptr->lock);                
 		if ((type == DSC_RESP_MSG) || link_up)
 			return;
-		rbuf = disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
+		rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
 		if (rbuf != NULL) {
 			msg_dbg(buf_msg(rbuf),"SEND:");
 			b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr);
@@ -212,11 +212,11 @@
 }
 
 /**
- * disc_stop_link_req - stop sending periodic link setup requests
+ * tipc_disc_stop_link_req - stop sending periodic link setup requests
  * @req: ptr to link request structure
  */
 
-void disc_stop_link_req(struct link_req *req) 
+void tipc_disc_stop_link_req(struct link_req *req) 
 {
 	if (!req)
 		return;
@@ -228,11 +228,11 @@
 } 
 
 /**
- * disc_update_link_req - update frequency of periodic link setup requests
+ * tipc_disc_update_link_req - update frequency of periodic link setup requests
  * @req: ptr to link request structure
  */
 
-void disc_update_link_req(struct link_req *req) 
+void tipc_disc_update_link_req(struct link_req *req) 
 {
 	if (!req)
 		return;
@@ -282,7 +282,7 @@
 }
 
 /**
- * disc_init_link_req - start sending periodic link setup requests
+ * tipc_disc_init_link_req - start sending periodic link setup requests
  * @b_ptr: ptr to bearer issuing requests
  * @dest: destination address for request messages
  * @dest_domain: network domain of node(s) which should respond to message
@@ -291,10 +291,10 @@
  * Returns pointer to link request structure, or NULL if unable to create.
  */
 
-struct link_req *disc_init_link_req(struct bearer *b_ptr, 
-				    const struct tipc_media_addr *dest,
-				    u32 dest_domain,
-				    u32 req_links) 
+struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, 
+					 const struct tipc_media_addr *dest,
+					 u32 dest_domain,
+					 u32 req_links) 
 {
 	struct link_req *req;
 
@@ -302,7 +302,7 @@
 	if (!req)
 		return NULL;
 
-	req->buf = disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr);
+	req->buf = tipc_disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr);
 	if (!req->buf) {
 		kfree(req);
 		return NULL;
diff --git a/net/tipc/discover.h b/net/tipc/discover.h
index 2a6114d..0454fd1 100644
--- a/net/tipc/discover.h
+++ b/net/tipc/discover.h
@@ -37,20 +37,20 @@
 #ifndef _TIPC_DISCOVER_H
 #define _TIPC_DISCOVER_H
 
-#include <linux/tipc.h>
+#include "core.h"
 
 struct link_req;
 
-struct link_req *disc_init_link_req(struct bearer *b_ptr, 
-			            const struct tipc_media_addr *dest,
-			            u32 dest_domain,
-			            u32 req_links);
-void disc_update_link_req(struct link_req *req);
-void disc_stop_link_req(struct link_req *req);
+struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, 
+					 const struct tipc_media_addr *dest,
+					 u32 dest_domain,
+					 u32 req_links);
+void tipc_disc_update_link_req(struct link_req *req);
+void tipc_disc_stop_link_req(struct link_req *req);
 
-void disc_recv_msg(struct sk_buff *buf);
+void tipc_disc_recv_msg(struct sk_buff *buf);
 
-void disc_link_event(u32 addr, char *name, int up);
+void tipc_disc_link_event(u32 addr, char *name, int up);
 #if 0
 int  disc_create_link(const struct tipc_link_create *argv);
 #endif
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 34d0462..1f8d83b 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -38,13 +38,11 @@
 #include <net/tipc/tipc_bearer.h>
 #include <net/tipc/tipc_msg.h>
 #include <linux/netdevice.h>
-#include <linux/version.h>
 
 #define MAX_ETH_BEARERS		2
-#define TIPC_PROTOCOL		0x88ca
-#define ETH_LINK_PRIORITY	10
+#define ETH_LINK_PRIORITY	TIPC_DEF_LINK_PRI
 #define ETH_LINK_TOLERANCE	TIPC_DEF_LINK_TOL
-
+#define ETH_LINK_WINDOW		TIPC_DEF_LINK_WIN
 
 /**
  * struct eth_bearer - Ethernet bearer data structure
@@ -78,7 +76,7 @@
 		clone->nh.raw = clone->data;
 		dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
 		clone->dev = dev;
-		dev->hard_header(clone, dev, TIPC_PROTOCOL, 
+		dev->hard_header(clone, dev, ETH_P_TIPC, 
 				 &dest->dev_addr.eth_addr,
 				 dev->dev_addr, clone->len);
 		dev_queue_xmit(clone);
@@ -141,7 +139,7 @@
 		return -EDQUOT;
 	if (!eb_ptr->dev) {
 		eb_ptr->dev = dev;
-		eb_ptr->tipc_packet_type.type = __constant_htons(TIPC_PROTOCOL);
+		eb_ptr->tipc_packet_type.type = __constant_htons(ETH_P_TIPC);
 		eb_ptr->tipc_packet_type.dev = dev;
 		eb_ptr->tipc_packet_type.func = recv_msg;
 		eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
@@ -240,13 +238,13 @@
 }
 
 /**
- * eth_media_start - activate Ethernet bearer support
+ * tipc_eth_media_start - activate Ethernet bearer support
  *
  * Register Ethernet media type with TIPC bearer code.  Also register
  * with OS for notifications about device state changes.
  */
 
-int eth_media_start(void)
+int tipc_eth_media_start(void)
 {                       
 	struct tipc_media_addr bcast_addr;
 	int res;
@@ -260,7 +258,7 @@
 	res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth",
 				  enable_bearer, disable_bearer, send_msg, 
 				  eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY, 
-				  ETH_LINK_TOLERANCE, TIPC_DEF_LINK_WIN);
+				  ETH_LINK_TOLERANCE, ETH_LINK_WINDOW);
 	if (res)
 		return res;
 
@@ -273,10 +271,10 @@
 }
 
 /**
- * eth_media_stop - deactivate Ethernet bearer support
+ * tipc_eth_media_stop - deactivate Ethernet bearer support
  */
 
-void eth_media_stop(void)
+void tipc_eth_media_stop(void)
 {
 	int i;
 
diff --git a/net/tipc/handler.c b/net/tipc/handler.c
index f320010..966f70a 100644
--- a/net/tipc/handler.c
+++ b/net/tipc/handler.c
@@ -52,7 +52,7 @@
 static DECLARE_TASKLET_DISABLED(tipc_tasklet, process_signal_queue, 0);
 
 
-unsigned int k_signal(Handler routine, unsigned long argument)
+unsigned int tipc_k_signal(Handler routine, unsigned long argument)
 {
 	struct queue_item *item;
 
@@ -93,7 +93,7 @@
 	spin_unlock_bh(&qitem_lock);
 }
 
-int handler_start(void)
+int tipc_handler_start(void)
 {
 	tipc_queue_item_cache = 
 		kmem_cache_create("tipc_queue_items", sizeof(struct queue_item),
@@ -107,7 +107,7 @@
 	return 0;
 }
 
-void handler_stop(void)
+void tipc_handler_stop(void)
 {
 	struct list_head *l, *n;
 	struct queue_item *item; 
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 7265f4b..511872a 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -148,12 +148,12 @@
 #define LINK_LOG_BUF_SIZE 0
 
 #define dbg_link(fmt, arg...)  do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0)
-#define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) msg_print(&l_ptr->print_buf, msg, txt); } while(0)
+#define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) tipc_msg_print(&l_ptr->print_buf, msg, txt); } while(0)
 #define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0)
 #define dbg_link_dump() do { \
 	if (LINK_LOG_BUF_SIZE) { \
 		tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \
-		printbuf_move(LOG, &l_ptr->print_buf); \
+		tipc_printbuf_move(LOG, &l_ptr->print_buf); \
 	} \
 } while (0)
 
@@ -252,14 +252,14 @@
  *  Simple non-inlined link routines (i.e. referenced outside this file)
  */
 
-int link_is_up(struct link *l_ptr)
+int tipc_link_is_up(struct link *l_ptr)
 {
 	if (!l_ptr)
 		return 0;
 	return (link_working_working(l_ptr) || link_working_unknown(l_ptr));
 }
 
-int link_is_active(struct link *l_ptr)
+int tipc_link_is_active(struct link *l_ptr)
 {
 	return ((l_ptr->owner->active_links[0] == l_ptr) ||
 		(l_ptr->owner->active_links[1] == l_ptr));
@@ -338,15 +338,15 @@
  * link_timeout - handle expiration of link timer
  * @l_ptr: pointer to link
  * 
- * This routine must not grab "net_lock" to avoid a potential deadlock conflict
- * with link_delete().  (There is no risk that the node will be deleted by
- * another thread because link_delete() always cancels the link timer before
- * node_delete() is called.)
+ * This routine must not grab "tipc_net_lock" to avoid a potential deadlock conflict
+ * with tipc_link_delete().  (There is no risk that the node will be deleted by
+ * another thread because tipc_link_delete() always cancels the link timer before
+ * tipc_node_delete() is called.)
  */
 
 static void link_timeout(struct link *l_ptr)
 {
-	node_lock(l_ptr->owner);
+	tipc_node_lock(l_ptr->owner);
 
 	/* update counters used in statistical profiling of send traffic */
 
@@ -391,9 +391,9 @@
 	link_state_event(l_ptr, TIMEOUT_EVT);
 
 	if (l_ptr->next_out)
-		link_push_queue(l_ptr);
+		tipc_link_push_queue(l_ptr);
 
-	node_unlock(l_ptr->owner);
+	tipc_node_unlock(l_ptr->owner);
 }
 
 static inline void link_set_timer(struct link *l_ptr, u32 time)
@@ -402,7 +402,7 @@
 }
 
 /**
- * link_create - create a new link
+ * tipc_link_create - create a new link
  * @b_ptr: pointer to associated bearer
  * @peer: network address of node at other end of link
  * @media_addr: media address to use when sending messages over link
@@ -410,8 +410,8 @@
  * Returns pointer to link.
  */
 
-struct link *link_create(struct bearer *b_ptr, const u32 peer,
-			 const struct tipc_media_addr *media_addr)
+struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
+			      const struct tipc_media_addr *media_addr)
 {
 	struct link *l_ptr;
 	struct tipc_msg *msg;
@@ -449,7 +449,7 @@
 	strcpy((char *)msg_data(msg), if_name);
 
 	l_ptr->priority = b_ptr->priority;
-	link_set_queue_limits(l_ptr, b_ptr->media->window);
+	tipc_link_set_queue_limits(l_ptr, b_ptr->media->window);
 
 	link_init_max_pkt(l_ptr);
 
@@ -458,7 +458,7 @@
 
 	link_reset_statistics(l_ptr);
 
-	l_ptr->owner = node_attach_link(l_ptr);
+	l_ptr->owner = tipc_node_attach_link(l_ptr);
 	if (!l_ptr->owner) {
 		kfree(l_ptr);
 		return NULL;
@@ -472,52 +472,52 @@
 			warn("Memory squeeze; Failed to create link\n");
 			return NULL;
 		}
-		printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE);
+		tipc_printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE);
 	}
 
-	k_signal((Handler)link_start, (unsigned long)l_ptr);
+	tipc_k_signal((Handler)tipc_link_start, (unsigned long)l_ptr);
 
-	dbg("link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n",
+	dbg("tipc_link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n",
 	    l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit);
 	
 	return l_ptr;
 }
 
 /** 
- * link_delete - delete a link
+ * tipc_link_delete - delete a link
  * @l_ptr: pointer to link
  * 
- * Note: 'net_lock' is write_locked, bearer is locked.
+ * Note: 'tipc_net_lock' is write_locked, bearer is locked.
  * This routine must not grab the node lock until after link timer cancellation
  * to avoid a potential deadlock situation.  
  */
 
-void link_delete(struct link *l_ptr)
+void tipc_link_delete(struct link *l_ptr)
 {
 	if (!l_ptr) {
 		err("Attempt to delete non-existent link\n");
 		return;
 	}
 
-	dbg("link_delete()\n");
+	dbg("tipc_link_delete()\n");
 
 	k_cancel_timer(&l_ptr->timer);
 	
-	node_lock(l_ptr->owner);
-	link_reset(l_ptr);
-	node_detach_link(l_ptr->owner, l_ptr);
-	link_stop(l_ptr);
+	tipc_node_lock(l_ptr->owner);
+	tipc_link_reset(l_ptr);
+	tipc_node_detach_link(l_ptr->owner, l_ptr);
+	tipc_link_stop(l_ptr);
 	list_del_init(&l_ptr->link_list);
 	if (LINK_LOG_BUF_SIZE)
 		kfree(l_ptr->print_buf.buf);
-	node_unlock(l_ptr->owner);
+	tipc_node_unlock(l_ptr->owner);
 	k_term_timer(&l_ptr->timer);
 	kfree(l_ptr);
 }
 
-void link_start(struct link *l_ptr)
+void tipc_link_start(struct link *l_ptr)
 {
-	dbg("link_start %x\n", l_ptr);
+	dbg("tipc_link_start %x\n", l_ptr);
 	link_state_event(l_ptr, STARTING_EVT);
 }
 
@@ -535,8 +535,8 @@
 {
 	struct port *p_ptr;
 
-	spin_lock_bh(&port_list_lock);
-	p_ptr = port_lock(origport);
+	spin_lock_bh(&tipc_port_list_lock);
+	p_ptr = tipc_port_lock(origport);
 	if (p_ptr) {
 		if (!p_ptr->wakeup)
 			goto exit;
@@ -548,13 +548,13 @@
 		list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports);
 		l_ptr->stats.link_congs++;
 exit:
-		port_unlock(p_ptr);
+		tipc_port_unlock(p_ptr);
 	}
-	spin_unlock_bh(&port_list_lock);
+	spin_unlock_bh(&tipc_port_list_lock);
 	return -ELINKCONG;
 }
 
-void link_wakeup_ports(struct link *l_ptr, int all)
+void tipc_link_wakeup_ports(struct link *l_ptr, int all)
 {
 	struct port *p_ptr;
 	struct port *temp_p_ptr;
@@ -564,7 +564,7 @@
 		win = 100000;
 	if (win <= 0)
 		return;
-	if (!spin_trylock_bh(&port_list_lock))
+	if (!spin_trylock_bh(&tipc_port_list_lock))
 		return;
 	if (link_congested(l_ptr))
 		goto exit;
@@ -583,7 +583,7 @@
 	}
 
 exit:
-	spin_unlock_bh(&port_list_lock);
+	spin_unlock_bh(&tipc_port_list_lock);
 }
 
 /** 
@@ -606,11 +606,11 @@
 }
 
 /**
- * link_reset_fragments - purge link's inbound message fragments queue
+ * tipc_link_reset_fragments - purge link's inbound message fragments queue
  * @l_ptr: pointer to link
  */
 
-void link_reset_fragments(struct link *l_ptr)
+void tipc_link_reset_fragments(struct link *l_ptr)
 {
 	struct sk_buff *buf = l_ptr->defragm_buf;
 	struct sk_buff *next;
@@ -624,11 +624,11 @@
 }
 
 /** 
- * link_stop - purge all inbound and outbound messages associated with link
+ * tipc_link_stop - purge all inbound and outbound messages associated with link
  * @l_ptr: pointer to link
  */
 
-void link_stop(struct link *l_ptr)
+void tipc_link_stop(struct link *l_ptr)
 {
 	struct sk_buff *buf;
 	struct sk_buff *next;
@@ -647,7 +647,7 @@
 		buf = next;
 	}
 
-	link_reset_fragments(l_ptr);
+	tipc_link_reset_fragments(l_ptr);
 
 	buf_discard(l_ptr->proto_msg_queue);
 	l_ptr->proto_msg_queue = NULL;
@@ -677,7 +677,7 @@
 	ev->up = up;
 	ev->fcn = fcn;
 	memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME);
-	k_signal((Handler)link_recv_event, (unsigned long)ev);
+	tipc_k_signal((Handler)link_recv_event, (unsigned long)ev);
 }
 
 #else
@@ -686,7 +686,7 @@
 
 #endif
 
-void link_reset(struct link *l_ptr)
+void tipc_link_reset(struct link *l_ptr)
 {
 	struct sk_buff *buf;
 	u32 prev_state = l_ptr->state;
@@ -706,13 +706,13 @@
 	if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET))
 		return;
 
-	node_link_down(l_ptr->owner, l_ptr);
-	bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
+	tipc_node_link_down(l_ptr->owner, l_ptr);
+	tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
 #if 0
-	tipc_printf(CONS, "\nReset link <%s>\n", l_ptr->name);
+	tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name);
 	dbg_link_dump();
 #endif
-	if (node_has_active_links(l_ptr->owner) &&
+	if (tipc_node_has_active_links(l_ptr->owner) &&
 	    l_ptr->owner->permit_changeover) {
 		l_ptr->reset_checkpoint = checkpoint;
 		l_ptr->exp_msg_count = START_CHANGEOVER;
@@ -730,7 +730,7 @@
 		buf = next;
 	}
 	if (!list_empty(&l_ptr->waiting_ports))
-		link_wakeup_ports(l_ptr, 1);
+		tipc_link_wakeup_ports(l_ptr, 1);
 
 	l_ptr->retransm_queue_head = 0;
 	l_ptr->retransm_queue_size = 0;
@@ -747,20 +747,20 @@
 	l_ptr->stale_count = 0;
 	link_reset_statistics(l_ptr);
 
-	link_send_event(cfg_link_event, l_ptr, 0);
+	link_send_event(tipc_cfg_link_event, l_ptr, 0);
 	if (!in_own_cluster(l_ptr->addr))
-		link_send_event(disc_link_event, l_ptr, 0);
+		link_send_event(tipc_disc_link_event, l_ptr, 0);
 }
 
 
 static void link_activate(struct link *l_ptr)
 {
 	l_ptr->next_in_no = 1;
-	node_link_up(l_ptr->owner, l_ptr);
-	bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);
-	link_send_event(cfg_link_event, l_ptr, 1);
+	tipc_node_link_up(l_ptr->owner, l_ptr);
+	tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);
+	link_send_event(tipc_cfg_link_event, l_ptr, 1);
 	if (!in_own_cluster(l_ptr->addr))
-		link_send_event(disc_link_event, l_ptr, 1);
+		link_send_event(tipc_disc_link_event, l_ptr, 1);
 }
 
 /**
@@ -799,13 +799,13 @@
 			dbg_link("TIM ");
 			if (l_ptr->next_in_no != l_ptr->checkpoint) {
 				l_ptr->checkpoint = l_ptr->next_in_no;
-				if (bclink_acks_missing(l_ptr->owner)) {
-					link_send_proto_msg(l_ptr, STATE_MSG, 
-							    0, 0, 0, 0, 0);
+				if (tipc_bclink_acks_missing(l_ptr->owner)) {
+					tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+								 0, 0, 0, 0, 0);
 					l_ptr->fsm_msg_cnt++;
 				} else if (l_ptr->max_pkt < l_ptr->max_pkt_target) {
-					link_send_proto_msg(l_ptr, STATE_MSG, 
-							    1, 0, 0, 0, 0);
+					tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+								 1, 0, 0, 0, 0);
 					l_ptr->fsm_msg_cnt++;
 				}
 				link_set_timer(l_ptr, cont_intv);
@@ -814,16 +814,16 @@
 			dbg_link(" -> WU\n");
 			l_ptr->state = WORKING_UNKNOWN;
 			l_ptr->fsm_msg_cnt = 0;
-			link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
 			l_ptr->fsm_msg_cnt++;
 			link_set_timer(l_ptr, cont_intv / 4);
 			break;
 		case RESET_MSG:
 			dbg_link("RES -> RR\n");
-			link_reset(l_ptr);
+			tipc_link_reset(l_ptr);
 			l_ptr->state = RESET_RESET;
 			l_ptr->fsm_msg_cnt = 0;
-			link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
 			l_ptr->fsm_msg_cnt++;
 			link_set_timer(l_ptr, cont_intv);
 			break;
@@ -844,10 +844,10 @@
 			break;
 		case RESET_MSG:
 			dbg_link("RES -> RR\n");
-			link_reset(l_ptr);
+			tipc_link_reset(l_ptr);
 			l_ptr->state = RESET_RESET;
 			l_ptr->fsm_msg_cnt = 0;
-			link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
 			l_ptr->fsm_msg_cnt++;
 			link_set_timer(l_ptr, cont_intv);
 			break;
@@ -858,9 +858,9 @@
 				l_ptr->state = WORKING_WORKING;
 				l_ptr->fsm_msg_cnt = 0;
 				l_ptr->checkpoint = l_ptr->next_in_no;
-				if (bclink_acks_missing(l_ptr->owner)) {
-					link_send_proto_msg(l_ptr, STATE_MSG,
-							    0, 0, 0, 0, 0);
+				if (tipc_bclink_acks_missing(l_ptr->owner)) {
+					tipc_link_send_proto_msg(l_ptr, STATE_MSG,
+								 0, 0, 0, 0, 0);
 					l_ptr->fsm_msg_cnt++;
 				}
 				link_set_timer(l_ptr, cont_intv);
@@ -868,18 +868,18 @@
 				dbg_link("Probing %u/%u,timer = %u ms)\n",
 					 l_ptr->fsm_msg_cnt, l_ptr->abort_limit,
 					 cont_intv / 4);
-				link_send_proto_msg(l_ptr, STATE_MSG, 
-						    1, 0, 0, 0, 0);
+				tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+							 1, 0, 0, 0, 0);
 				l_ptr->fsm_msg_cnt++;
 				link_set_timer(l_ptr, cont_intv / 4);
 			} else {	/* Link has failed */
 				dbg_link("-> RU (%u probes unanswered)\n",
 					 l_ptr->fsm_msg_cnt);
-				link_reset(l_ptr);
+				tipc_link_reset(l_ptr);
 				l_ptr->state = RESET_UNKNOWN;
 				l_ptr->fsm_msg_cnt = 0;
-				link_send_proto_msg(l_ptr, RESET_MSG,
-						    0, 0, 0, 0, 0);
+				tipc_link_send_proto_msg(l_ptr, RESET_MSG,
+							 0, 0, 0, 0, 0);
 				l_ptr->fsm_msg_cnt++;
 				link_set_timer(l_ptr, cont_intv);
 			}
@@ -904,7 +904,7 @@
 			l_ptr->state = WORKING_WORKING;
 			l_ptr->fsm_msg_cnt = 0;
 			link_activate(l_ptr);
-			link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
 			l_ptr->fsm_msg_cnt++;
 			link_set_timer(l_ptr, cont_intv);
 			break;
@@ -913,7 +913,7 @@
 			dbg_link(" -> RR\n");
 			l_ptr->state = RESET_RESET;
 			l_ptr->fsm_msg_cnt = 0;
-			link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0);
 			l_ptr->fsm_msg_cnt++;
 			link_set_timer(l_ptr, cont_intv);
 			break;
@@ -923,7 +923,7 @@
 			/* fall through */
 		case TIMEOUT_EVT:
 			dbg_link("TIM \n");
-			link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
 			l_ptr->fsm_msg_cnt++;
 			link_set_timer(l_ptr, cont_intv);
 			break;
@@ -947,7 +947,7 @@
 			l_ptr->state = WORKING_WORKING;
 			l_ptr->fsm_msg_cnt = 0;
 			link_activate(l_ptr);
-			link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
 			l_ptr->fsm_msg_cnt++;
 			link_set_timer(l_ptr, cont_intv);
 			break;
@@ -956,7 +956,7 @@
 			break;
 		case TIMEOUT_EVT:
 			dbg_link("TIM\n");
-			link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
 			l_ptr->fsm_msg_cnt++;
 			link_set_timer(l_ptr, cont_intv);
 			dbg_link("fsm_msg_cnt %u\n", l_ptr->fsm_msg_cnt);
@@ -1023,12 +1023,12 @@
 }
 
 /* 
- * link_send_buf() is the 'full path' for messages, called from 
+ * tipc_link_send_buf() is the 'full path' for messages, called from 
  * inside TIPC when the 'fast path' in tipc_send_buf
  * has failed, and from link_send()
  */
 
-int link_send_buf(struct link *l_ptr, struct sk_buff *buf)
+int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf)
 {
 	struct tipc_msg *msg = buf_msg(buf);
 	u32 size = msg_size(msg);
@@ -1051,7 +1051,7 @@
 		buf_discard(buf);
 		if (imp > CONN_MANAGER) {
 			warn("Resetting <%s>, send queue full", l_ptr->name);
-			link_reset(l_ptr);
+			tipc_link_reset(l_ptr);
 		}
 		return dsz;
 	}
@@ -1059,21 +1059,21 @@
 	/* Fragmentation needed ? */
 
 	if (size > max_packet)
-		return link_send_long_buf(l_ptr, buf);
+		return tipc_link_send_long_buf(l_ptr, buf);
 
 	/* Packet can be queued or sent: */
 
 	if (queue_size > l_ptr->stats.max_queue_sz)
 		l_ptr->stats.max_queue_sz = queue_size;
 
-	if (likely(!bearer_congested(l_ptr->b_ptr, l_ptr) && 
+	if (likely(!tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && 
 		   !link_congested(l_ptr))) {
 		link_add_to_outqueue(l_ptr, buf, msg);
 
-		if (likely(bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) {
+		if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) {
 			l_ptr->unacked_window = 0;
 		} else {
-			bearer_schedule(l_ptr->b_ptr, l_ptr);
+			tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
 			l_ptr->stats.bearer_congs++;
 			l_ptr->next_out = buf;
 		}
@@ -1088,7 +1088,7 @@
 
 		if (l_ptr->next_out && 
 		    link_bundle_buf(l_ptr, l_ptr->last_out, buf)) {
-			bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
+			tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
 			return dsz;
 		}
 
@@ -1114,38 +1114,38 @@
 	if (!l_ptr->next_out)
 		l_ptr->next_out = buf;
 	link_add_to_outqueue(l_ptr, buf, msg);
-	bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
+	tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
 	return dsz;
 }
 
 /* 
- * link_send(): same as link_send_buf(), but the link to use has 
+ * tipc_link_send(): same as tipc_link_send_buf(), but the link to use has 
  * not been selected yet, and the the owner node is not locked
  * Called by TIPC internal users, e.g. the name distributor
  */
 
-int link_send(struct sk_buff *buf, u32 dest, u32 selector)
+int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
 {
 	struct link *l_ptr;
 	struct node *n_ptr;
 	int res = -ELINKCONG;
 
-	read_lock_bh(&net_lock);
-	n_ptr = node_select(dest, selector);
+	read_lock_bh(&tipc_net_lock);
+	n_ptr = tipc_node_select(dest, selector);
 	if (n_ptr) {
-		node_lock(n_ptr);
+		tipc_node_lock(n_ptr);
 		l_ptr = n_ptr->active_links[selector & 1];
-		dbg("link_send: found link %x for dest %x\n", l_ptr, dest);
+		dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest);
 		if (l_ptr) {
-			res = link_send_buf(l_ptr, buf);
+			res = tipc_link_send_buf(l_ptr, buf);
 		}
-		node_unlock(n_ptr);
+		tipc_node_unlock(n_ptr);
 	} else {
 		dbg("Attempt to send msg to unknown node:\n");
 		msg_dbg(buf_msg(buf),">>>");
 		buf_discard(buf);
 	}
-	read_unlock_bh(&net_lock);
+	read_unlock_bh(&tipc_net_lock);
 	return res;
 }
 
@@ -1166,14 +1166,14 @@
 		if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) {
 			if (likely(list_empty(&l_ptr->b_ptr->cong_links))) {
 				link_add_to_outqueue(l_ptr, buf, msg);
-				if (likely(bearer_send(l_ptr->b_ptr, buf,
-						       &l_ptr->media_addr))) {
+				if (likely(tipc_bearer_send(l_ptr->b_ptr, buf,
+							    &l_ptr->media_addr))) {
 					l_ptr->unacked_window = 0;
 					msg_dbg(msg,"SENT_FAST:");
 					return res;
 				}
 				dbg("failed sent fast...\n");
-				bearer_schedule(l_ptr->b_ptr, l_ptr);
+				tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
 				l_ptr->stats.bearer_congs++;
 				l_ptr->next_out = buf;
 				return res;
@@ -1182,7 +1182,7 @@
 		else
 			*used_max_pkt = link_max_pkt(l_ptr);
 	}
-	return link_send_buf(l_ptr, buf);  /* All other cases */
+	return tipc_link_send_buf(l_ptr, buf);  /* All other cases */
 }
 
 /* 
@@ -1200,24 +1200,24 @@
 	u32 dummy;
 
 	if (destnode == tipc_own_addr)
-		return port_recv_msg(buf);
+		return tipc_port_recv_msg(buf);
 
-	read_lock_bh(&net_lock);
-	n_ptr = node_select(destnode, selector);
+	read_lock_bh(&tipc_net_lock);
+	n_ptr = tipc_node_select(destnode, selector);
 	if (likely(n_ptr)) {
-		node_lock(n_ptr);
+		tipc_node_lock(n_ptr);
 		l_ptr = n_ptr->active_links[selector];
 		dbg("send_fast: buf %x selected %x, destnode = %x\n",
 		    buf, l_ptr, destnode);
 		if (likely(l_ptr)) {
 			res = link_send_buf_fast(l_ptr, buf, &dummy);
-			node_unlock(n_ptr);
-			read_unlock_bh(&net_lock);
+			tipc_node_unlock(n_ptr);
+			read_unlock_bh(&tipc_net_lock);
 			return res;
 		}
-		node_unlock(n_ptr);
+		tipc_node_unlock(n_ptr);
 	}
-	read_unlock_bh(&net_lock);
+	read_unlock_bh(&tipc_net_lock);
 	res = msg_data_sz(buf_msg(buf));
 	tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
 	return res;
@@ -1225,15 +1225,15 @@
 
 
 /* 
- * link_send_sections_fast: Entry for messages where the 
+ * tipc_link_send_sections_fast: Entry for messages where the 
  * destination processor is known and the header is complete,
  * except for total message length. 
  * Returns user data length or errno.
  */
-int link_send_sections_fast(struct port *sender, 
-			    struct iovec const *msg_sect,
-			    const u32 num_sect, 
-			    u32 destaddr)
+int tipc_link_send_sections_fast(struct port *sender, 
+				 struct iovec const *msg_sect,
+				 const u32 num_sect, 
+				 u32 destaddr)
 {
 	struct tipc_msg *hdr = &sender->publ.phdr;
 	struct link *l_ptr;
@@ -1253,10 +1253,10 @@
 	res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
 			!sender->user_port, &buf);
 
-	read_lock_bh(&net_lock);
-	node = node_select(destaddr, selector);
+	read_lock_bh(&tipc_net_lock);
+	node = tipc_node_select(destaddr, selector);
 	if (likely(node)) {
-		node_lock(node);
+		tipc_node_lock(node);
 		l_ptr = node->active_links[selector];
 		if (likely(l_ptr)) {
 			if (likely(buf)) {
@@ -1265,8 +1265,8 @@
 				if (unlikely(res < 0))
 					buf_discard(buf);
 exit:
-				node_unlock(node);
-				read_unlock_bh(&net_lock);
+				tipc_node_unlock(node);
+				read_unlock_bh(&tipc_net_lock);
 				return res;
 			}
 
@@ -1290,8 +1290,8 @@
 			 */
 
 			sender->max_pkt = link_max_pkt(l_ptr);
-			node_unlock(node);
-			read_unlock_bh(&net_lock);
+			tipc_node_unlock(node);
+			read_unlock_bh(&tipc_net_lock);
 
 
 			if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
@@ -1300,17 +1300,17 @@
 			return link_send_sections_long(sender, msg_sect,
 						       num_sect, destaddr);
 		}
-		node_unlock(node);
+		tipc_node_unlock(node);
 	}
-	read_unlock_bh(&net_lock);
+	read_unlock_bh(&tipc_net_lock);
 
 	/* Couldn't find a link to the destination node */
 
 	if (buf)
 		return tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
 	if (res >= 0)
-		return port_reject_sections(sender, hdr, msg_sect, num_sect,
-					    TIPC_ERR_NO_NODE);
+		return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect,
+						 TIPC_ERR_NO_NODE);
 	return res;
 }
 
@@ -1444,17 +1444,17 @@
 	 * Now we have a buffer chain. Select a link and check
 	 * that packet size is still OK
 	 */
-	node = node_select(destaddr, sender->publ.ref & 1);
+	node = tipc_node_select(destaddr, sender->publ.ref & 1);
 	if (likely(node)) {
-		node_lock(node);
+		tipc_node_lock(node);
 		l_ptr = node->active_links[sender->publ.ref & 1];
 		if (!l_ptr) {
-			node_unlock(node);
+			tipc_node_unlock(node);
 			goto reject;
 		}
 		if (link_max_pkt(l_ptr) < max_pkt) {
 			sender->max_pkt = link_max_pkt(l_ptr);
-			node_unlock(node);
+			tipc_node_unlock(node);
 			for (; buf_chain; buf_chain = buf) {
 				buf = buf_chain->next;
 				buf_discard(buf_chain);
@@ -1467,8 +1467,8 @@
 			buf = buf_chain->next;
 			buf_discard(buf_chain);
 		}
-		return port_reject_sections(sender, hdr, msg_sect, num_sect,
-					    TIPC_ERR_NO_NODE);
+		return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect,
+						 TIPC_ERR_NO_NODE);
 	}
 
 	/* Append whole chain to send queue: */
@@ -1491,15 +1491,15 @@
 
 	/* Send it, if possible: */
 
-	link_push_queue(l_ptr);
-	node_unlock(node);
+	tipc_link_push_queue(l_ptr);
+	tipc_node_unlock(node);
 	return dsz;
 }
 
 /* 
- * link_push_packet: Push one unsent packet to the media
+ * tipc_link_push_packet: Push one unsent packet to the media
  */
-u32 link_push_packet(struct link *l_ptr)
+u32 tipc_link_push_packet(struct link *l_ptr)
 {
 	struct sk_buff *buf = l_ptr->first_out;
 	u32 r_q_size = l_ptr->retransm_queue_size;
@@ -1526,7 +1526,7 @@
 	if (r_q_size && buf && !skb_cloned(buf)) {
 		msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
 		msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); 
-		if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+		if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
 			msg_dbg(buf_msg(buf), ">DEF-RETR>");
 			l_ptr->retransm_queue_head = mod(++r_q_head);
 			l_ptr->retransm_queue_size = --r_q_size;
@@ -1545,7 +1545,7 @@
 	if (buf) {
 		msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
 		msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in); 
-		if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+		if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
 			msg_dbg(buf_msg(buf), ">DEF-PROT>");
 			l_ptr->unacked_window = 0;
 			buf_discard(buf);
@@ -1569,7 +1569,7 @@
 		if (mod(next - first) < l_ptr->queue_limit[0]) {
 			msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
 			msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 
-			if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+			if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
 				if (msg_user(msg) == MSG_BUNDLER)
 					msg_set_type(msg, CLOSED_MSG);
 				msg_dbg(msg, ">PUSH-DATA>");
@@ -1589,29 +1589,29 @@
  * push_queue(): push out the unsent messages of a link where
  *               congestion has abated. Node is locked
  */
-void link_push_queue(struct link *l_ptr)
+void tipc_link_push_queue(struct link *l_ptr)
 {
 	u32 res;
 
-	if (bearer_congested(l_ptr->b_ptr, l_ptr))
+	if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr))
 		return;
 
 	do {
-		res = link_push_packet(l_ptr);
+		res = tipc_link_push_packet(l_ptr);
 	}
 	while (res == TIPC_OK);
 	if (res == PUSH_FAILED)
-		bearer_schedule(l_ptr->b_ptr, l_ptr);
+		tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
 }
 
-void link_retransmit(struct link *l_ptr, struct sk_buff *buf, 
-		     u32 retransmits)
+void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, 
+			  u32 retransmits)
 {
 	struct tipc_msg *msg;
 
 	dbg("Retransmitting %u in link %x\n", retransmits, l_ptr);
 
-	if (bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) {
+	if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) {
 		msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>");
 		dbg_print_link(l_ptr, "   ");
 		l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf));
@@ -1622,15 +1622,15 @@
 		msg = buf_msg(buf);
 		msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
 		msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 
-		if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+		if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
                         /* Catch if retransmissions fail repeatedly: */
                         if (l_ptr->last_retransmitted == msg_seqno(msg)) {
                                 if (++l_ptr->stale_count > 100) {
-                                        msg_print(CONS, buf_msg(buf), ">RETR>");
+                                        tipc_msg_print(TIPC_CONS, buf_msg(buf), ">RETR>");
                                         info("...Retransmitted %u times\n",
 					     l_ptr->stale_count);
-                                        link_print(l_ptr, CONS, "Resetting Link\n");;
-                                        link_reset(l_ptr);
+                                        link_print(l_ptr, TIPC_CONS, "Resetting Link\n");;
+                                        tipc_link_reset(l_ptr);
                                         break;
                                 }
                         } else {
@@ -1643,7 +1643,7 @@
 			retransmits--;
 			l_ptr->stats.retransmitted++;
 		} else {
-			bearer_schedule(l_ptr->b_ptr, l_ptr);
+			tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
 			l_ptr->stats.bearer_congs++;
 			l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf));
 			l_ptr->retransm_queue_size = retransmits;
@@ -1663,9 +1663,9 @@
 	struct tipc_msg *msg = buf_msg(buf);
 
 	if (msg_user(msg) ==  LINK_CONFIG)
-		disc_recv_msg(buf);
+		tipc_disc_recv_msg(buf);
 	else
-		bclink_recv_pkt(buf);
+		tipc_bclink_recv_pkt(buf);
 }
 
 /** 
@@ -1692,7 +1692,7 @@
 
 void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
 {
-	read_lock_bh(&net_lock);
+	read_lock_bh(&tipc_net_lock);
 	while (head) {
 		struct bearer *b_ptr;
 		struct node *n_ptr;
@@ -1720,22 +1720,22 @@
 			link_recv_non_seq(buf);
 			continue;
 		}
-		n_ptr = node_find(msg_prevnode(msg));
+		n_ptr = tipc_node_find(msg_prevnode(msg));
 		if (unlikely(!n_ptr))
 			goto cont;
 
-		node_lock(n_ptr);
+		tipc_node_lock(n_ptr);
 		l_ptr = n_ptr->links[b_ptr->identity];
 		if (unlikely(!l_ptr)) {
-			node_unlock(n_ptr);
+			tipc_node_unlock(n_ptr);
 			goto cont;
 		}
 		/* 
 		 * Release acked messages 
 		 */
 		if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) {
-			if (node_is_up(n_ptr) && n_ptr->bclink.supported)
-				bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
+			if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported)
+				tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
 		}
 
 		crs = l_ptr->first_out;
@@ -1752,12 +1752,12 @@
 			l_ptr->out_queue_size -= released;
 		}
 		if (unlikely(l_ptr->next_out))
-			link_push_queue(l_ptr);
+			tipc_link_push_queue(l_ptr);
 		if (unlikely(!list_empty(&l_ptr->waiting_ports)))
-			link_wakeup_ports(l_ptr, 0);
+			tipc_link_wakeup_ports(l_ptr, 0);
 		if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) {
 			l_ptr->stats.sent_acks++;
-			link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
 		}
 
 protocol_check:
@@ -1770,8 +1770,8 @@
 				if (likely(msg_is_dest(msg, tipc_own_addr))) {
 deliver:
 					if (likely(msg_isdata(msg))) {
-						node_unlock(n_ptr);
-						port_recv_msg(buf);
+						tipc_node_unlock(n_ptr);
+						tipc_port_recv_msg(buf);
 						continue;
 					}
 					switch (msg_user(msg)) {
@@ -1779,34 +1779,32 @@
 						l_ptr->stats.recv_bundles++;
 						l_ptr->stats.recv_bundled += 
 							msg_msgcnt(msg);
-						node_unlock(n_ptr);
-						link_recv_bundle(buf);
+						tipc_node_unlock(n_ptr);
+						tipc_link_recv_bundle(buf);
 						continue;
 					case ROUTE_DISTRIBUTOR:
-						node_unlock(n_ptr);
-						cluster_recv_routing_table(buf);
+						tipc_node_unlock(n_ptr);
+						tipc_cltr_recv_routing_table(buf);
 						continue;
 					case NAME_DISTRIBUTOR:
-						node_unlock(n_ptr);
-						named_recv(buf);
+						tipc_node_unlock(n_ptr);
+						tipc_named_recv(buf);
 						continue;
 					case CONN_MANAGER:
-						node_unlock(n_ptr);
-						port_recv_proto_msg(buf);
+						tipc_node_unlock(n_ptr);
+						tipc_port_recv_proto_msg(buf);
 						continue;
 					case MSG_FRAGMENTER:
 						l_ptr->stats.recv_fragments++;
-						if (link_recv_fragment(
-							&l_ptr->defragm_buf, 
-							&buf, &msg)) {
+						if (tipc_link_recv_fragment(&l_ptr->defragm_buf, 
+									    &buf, &msg)) {
 							l_ptr->stats.recv_fragmented++;
 							goto deliver;
 						}
 						break;
 					case CHANGEOVER_PROTOCOL:
 						type = msg_type(msg);
-						if (link_recv_changeover_msg(
-							&l_ptr, &buf)) {
+						if (link_recv_changeover_msg(&l_ptr, &buf)) {
 							msg = buf_msg(buf);
 							seq_no = msg_seqno(msg);
 							TIPC_SKB_CB(buf)->handle 
@@ -1818,20 +1816,20 @@
 						break;
 					}
 				}
-				node_unlock(n_ptr);
-				net_route_msg(buf);
+				tipc_node_unlock(n_ptr);
+				tipc_net_route_msg(buf);
 				continue;
 			}
 			link_handle_out_of_seq_msg(l_ptr, buf);
 			head = link_insert_deferred_queue(l_ptr, head);
-			node_unlock(n_ptr);
+			tipc_node_unlock(n_ptr);
 			continue;
 		}
 
 		if (msg_user(msg) == LINK_PROTOCOL) {
 			link_recv_proto_msg(l_ptr, buf);
 			head = link_insert_deferred_queue(l_ptr, head);
-			node_unlock(n_ptr);
+			tipc_node_unlock(n_ptr);
 			continue;
 		}
 		msg_dbg(msg,"NSEQ<REC<");
@@ -1842,14 +1840,14 @@
 			msg_dbg(msg,"RECV-REINS:");
 			buf->next = head;
 			head = buf;
-			node_unlock(n_ptr);
+			tipc_node_unlock(n_ptr);
 			continue;
 		}
-		node_unlock(n_ptr);
+		tipc_node_unlock(n_ptr);
 cont:
 		buf_discard(buf);
 	}
-	read_unlock_bh(&net_lock);
+	read_unlock_bh(&tipc_net_lock);
 }
 
 /* 
@@ -1858,9 +1856,9 @@
  * Returns the increase of the queue length,i.e. 0 or 1
  */
 
-u32 link_defer_pkt(struct sk_buff **head,
-		   struct sk_buff **tail,
-		   struct sk_buff *buf)
+u32 tipc_link_defer_pkt(struct sk_buff **head,
+			struct sk_buff **tail,
+			struct sk_buff *buf)
 {
 	struct sk_buff *prev = 0;
 	struct sk_buff *crs = *head;
@@ -1939,12 +1937,12 @@
 		return;
 	}
 
-	if (link_defer_pkt(&l_ptr->oldest_deferred_in,
-			   &l_ptr->newest_deferred_in, buf)) {
+	if (tipc_link_defer_pkt(&l_ptr->oldest_deferred_in,
+				&l_ptr->newest_deferred_in, buf)) {
 		l_ptr->deferred_inqueue_sz++;
 		l_ptr->stats.deferred_recv++;
 		if ((l_ptr->deferred_inqueue_sz % 16) == 1)
-			link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
 	} else
 		l_ptr->stats.duplicates++;
 }
@@ -1952,8 +1950,8 @@
 /*
  * Send protocol message to the other endpoint.
  */
-void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
-			 u32 gap, u32 tolerance, u32 priority, u32 ack_mtu)
+void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
+			      u32 gap, u32 tolerance, u32 priority, u32 ack_mtu)
 {
 	struct sk_buff *buf = 0;
 	struct tipc_msg *msg = l_ptr->pmsg;
@@ -1964,12 +1962,12 @@
 	msg_set_type(msg, msg_typ);
 	msg_set_net_plane(msg, l_ptr->b_ptr->net_plane);
 	msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); 
-	msg_set_last_bcast(msg, bclink_get_last_sent());
+	msg_set_last_bcast(msg, tipc_bclink_get_last_sent());
 
 	if (msg_typ == STATE_MSG) {
 		u32 next_sent = mod(l_ptr->next_out_no);
 
-		if (!link_is_up(l_ptr))
+		if (!tipc_link_is_up(l_ptr))
 			return;
 		if (l_ptr->next_out)
 			next_sent = msg_seqno(buf_msg(l_ptr->next_out));
@@ -2013,7 +2011,7 @@
 		msg_set_max_pkt(msg, l_ptr->max_pkt_target);
 	}
 
-	if (node_has_redundant_links(l_ptr->owner)) {
+	if (tipc_node_has_redundant_links(l_ptr->owner)) {
 		msg_set_redundant_link(msg);
 	} else {
 		msg_clear_redundant_link(msg);
@@ -2026,7 +2024,7 @@
 
 	/* Congestion? */
 
-	if (bearer_congested(l_ptr->b_ptr, l_ptr)) {
+	if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
 		if (!l_ptr->proto_msg_queue) {
 			l_ptr->proto_msg_queue =
 				buf_acquire(sizeof(l_ptr->proto_msg));
@@ -2050,14 +2048,14 @@
 	memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg));
         msg_set_size(buf_msg(buf), msg_size);
 
-	if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+	if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
 		l_ptr->unacked_window = 0;
 		buf_discard(buf);
 		return;
 	}
 
 	/* New congestion */
-	bearer_schedule(l_ptr->b_ptr, l_ptr);
+	tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
 	l_ptr->proto_msg_queue = buf;
 	l_ptr->stats.bearer_congs++;
 }
@@ -2131,7 +2129,7 @@
 		l_ptr->peer_bearer_id = msg_bearer_id(msg);
 
 		/* Synchronize broadcast sequence numbers */
-		if (!node_has_redundant_links(l_ptr->owner)) {
+		if (!tipc_node_has_redundant_links(l_ptr->owner)) {
 			l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg));
 		}
 		break;
@@ -2145,7 +2143,7 @@
 			warn("Changing prio <%s>: %u->%u\n",
 			     l_ptr->name, l_ptr->priority, msg_linkprio(msg));
 			l_ptr->priority = msg_linkprio(msg);
-			link_reset(l_ptr); /* Enforce change to take effect */
+			tipc_link_reset(l_ptr); /* Enforce change to take effect */
 			break;
 		}
 		link_state_event(l_ptr, TRAFFIC_MSG_EVT);
@@ -2176,17 +2174,17 @@
 
 		/* Protocol message before retransmits, reduce loss risk */
 
-		bclink_check_gap(l_ptr->owner, msg_last_bcast(msg));
+		tipc_bclink_check_gap(l_ptr->owner, msg_last_bcast(msg));
 
 		if (rec_gap || (msg_probe(msg))) {
-			link_send_proto_msg(l_ptr, STATE_MSG,
-					    0, rec_gap, 0, 0, max_pkt_ack);
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG,
+						 0, rec_gap, 0, 0, max_pkt_ack);
 		}
 		if (msg_seq_gap(msg)) {
 			msg_dbg(msg, "With Gap:");
 			l_ptr->stats.recv_nacks++;
-			link_retransmit(l_ptr, l_ptr->first_out,
-					msg_seq_gap(msg));
+			tipc_link_retransmit(l_ptr, l_ptr->first_out,
+					     msg_seq_gap(msg));
 		}
 		break;
 	default:
@@ -2198,20 +2196,20 @@
 
 
 /*
- * link_tunnel(): Send one message via a link belonging to 
+ * tipc_link_tunnel(): Send one message via a link belonging to 
  * another bearer. Owner node is locked.
  */
-void link_tunnel(struct link *l_ptr, 
-	    struct tipc_msg *tunnel_hdr, 
-	    struct tipc_msg  *msg,
-	    u32 selector)
+void tipc_link_tunnel(struct link *l_ptr, 
+		      struct tipc_msg *tunnel_hdr, 
+		      struct tipc_msg  *msg,
+		      u32 selector)
 {
 	struct link *tunnel;
 	struct sk_buff *buf;
 	u32 length = msg_size(msg);
 
 	tunnel = l_ptr->owner->active_links[selector & 1];
-	if (!link_is_up(tunnel))
+	if (!tipc_link_is_up(tunnel))
 		return;
 	msg_set_size(tunnel_hdr, length + INT_H_SIZE);
 	buf = buf_acquire(length + INT_H_SIZE);
@@ -2222,7 +2220,7 @@
 	dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane);
 	msg_dbg(buf_msg(buf), ">SEND>");
 	assert(tunnel);
-	link_send_buf(tunnel, buf);
+	tipc_link_send_buf(tunnel, buf);
 }
 
 
@@ -2232,12 +2230,12 @@
  *               Owner node is locked.
  */
 
-void link_changeover(struct link *l_ptr)
+void tipc_link_changeover(struct link *l_ptr)
 {
 	u32 msgcount = l_ptr->out_queue_size;
 	struct sk_buff *crs = l_ptr->first_out;
 	struct link *tunnel = l_ptr->owner->active_links[0];
-	int split_bundles = node_has_redundant_links(l_ptr->owner);
+	int split_bundles = tipc_node_has_redundant_links(l_ptr->owner);
 	struct tipc_msg tunnel_hdr;
 
 	if (!tunnel)
@@ -2261,7 +2259,7 @@
 			dbg("%c->%c:", l_ptr->b_ptr->net_plane,
 			    tunnel->b_ptr->net_plane);
 			msg_dbg(&tunnel_hdr, "EMPTY>SEND>");
-			link_send_buf(tunnel, buf);
+			tipc_link_send_buf(tunnel, buf);
 		} else {
 			warn("Memory squeeze; link changeover failed\n");
 		}
@@ -2277,20 +2275,20 @@
 
 			while (msgcount--) {
 				msg_set_seqno(m,msg_seqno(msg));
-				link_tunnel(l_ptr, &tunnel_hdr, m,
-					    msg_link_selector(m));
+				tipc_link_tunnel(l_ptr, &tunnel_hdr, m,
+						 msg_link_selector(m));
 				pos += align(msg_size(m));
 				m = (struct tipc_msg *)pos;
 			}
 		} else {
-			link_tunnel(l_ptr, &tunnel_hdr, msg,
-				    msg_link_selector(msg));
+			tipc_link_tunnel(l_ptr, &tunnel_hdr, msg,
+					 msg_link_selector(msg));
 		}
 		crs = crs->next;
 	}
 }
 
-void link_send_duplicate(struct link *l_ptr, struct link *tunnel)
+void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel)
 {
 	struct sk_buff *iter;
 	struct tipc_msg tunnel_hdr;
@@ -2320,8 +2318,8 @@
 		dbg("%c->%c:", l_ptr->b_ptr->net_plane,
 		    tunnel->b_ptr->net_plane);
 		msg_dbg(buf_msg(outbuf), ">SEND>");
-		link_send_buf(tunnel, outbuf);
-		if (!link_is_up(l_ptr))
+		tipc_link_send_buf(tunnel, outbuf);
+		if (!tipc_link_is_up(l_ptr))
 			return;
 		iter = iter->next;
 	}
@@ -2393,9 +2391,9 @@
 
 	/* First original message ?: */
 
-	if (link_is_up(dest_link)) {
+	if (tipc_link_is_up(dest_link)) {
 		msg_dbg(tunnel_msg, "UP/FIRST/<REC<");
-		link_reset(dest_link);
+		tipc_link_reset(dest_link);
 		dest_link->exp_msg_count = msg_count;
 		if (!msg_count)
 			goto exit;
@@ -2436,7 +2434,7 @@
 /*
  *  Bundler functionality:
  */
-void link_recv_bundle(struct sk_buff *buf)
+void tipc_link_recv_bundle(struct sk_buff *buf)
 {
 	u32 msgcount = msg_msgcnt(buf_msg(buf));
 	u32 pos = INT_H_SIZE;
@@ -2456,7 +2454,7 @@
 		};
 		pos += align(msg_size(buf_msg(obuf)));
 		msg_dbg(buf_msg(obuf), "     /");
-		net_route_msg(obuf);
+		tipc_net_route_msg(obuf);
 	}
 	buf_discard(buf);
 }
@@ -2467,11 +2465,11 @@
 
 
 /* 
- * link_send_long_buf: Entry for buffers needing fragmentation.
+ * tipc_link_send_long_buf: Entry for buffers needing fragmentation.
  * The buffer is complete, inclusive total message length. 
  * Returns user data length.
  */
-int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
+int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
 {
 	struct tipc_msg *inmsg = buf_msg(buf);
 	struct tipc_msg fragm_hdr;
@@ -2521,8 +2519,8 @@
 		/*  Send queued messages first, if any: */
 
 		l_ptr->stats.sent_fragments++;
-		link_send_buf(l_ptr, fragm);
-		if (!link_is_up(l_ptr))
+		tipc_link_send_buf(l_ptr, fragm);
+		if (!tipc_link_is_up(l_ptr))
 			return dsz;
 		msg_set_fragm_no(&fragm_hdr, ++fragm_no);
 		rest -= fragm_sz;
@@ -2582,11 +2580,11 @@
 }
 
 /* 
- * link_recv_fragment(): Called with node lock on. Returns 
+ * tipc_link_recv_fragment(): Called with node lock on. Returns 
  * the reassembled buffer if message is complete.
  */
-int link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, 
-		       struct tipc_msg **m)
+int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, 
+			    struct tipc_msg **m)
 {
 	struct sk_buff *prev = 0;
 	struct sk_buff *fbuf = *fb;
@@ -2714,7 +2712,7 @@
 }
 
 
-void link_set_queue_limits(struct link *l_ptr, u32 window)
+void tipc_link_set_queue_limits(struct link *l_ptr, u32 window)
 {
 	/* Data messages from this node, inclusive FIRST_FRAGM */
 	l_ptr->queue_limit[DATA_LOW] = window;
@@ -2739,7 +2737,7 @@
  * @name - ptr to link name string
  * @node - ptr to area to be filled with ptr to associated node
  * 
- * Caller must hold 'net_lock' to ensure node and bearer are not deleted;
+ * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted;
  * this also prevents link deletion.
  * 
  * Returns pointer to link (or 0 if invalid link name).
@@ -2754,11 +2752,11 @@
 	if (!link_name_validate(name, &link_name_parts))
 		return 0;
 
-	b_ptr = bearer_find_interface(link_name_parts.if_local);
+	b_ptr = tipc_bearer_find_interface(link_name_parts.if_local);
 	if (!b_ptr)
 		return 0;
 
-	*node = node_find(link_name_parts.addr_peer); 
+	*node = tipc_node_find(link_name_parts.addr_peer); 
 	if (!*node)
 		return 0;
 
@@ -2769,8 +2767,8 @@
 	return l_ptr;
 }
 
-struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, 
-			        u16 cmd)
+struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, 
+				     u16 cmd)
 {
 	struct tipc_link_config *args;
         u32 new_value;
@@ -2779,61 +2777,62 @@
         int res;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	args = (struct tipc_link_config *)TLV_DATA(req_tlv_area);
 	new_value = ntohl(args->value);
 
-	if (!strcmp(args->name, bc_link_name)) {
+	if (!strcmp(args->name, tipc_bclink_name)) {
 		if ((cmd == TIPC_CMD_SET_LINK_WINDOW) &&
-		    (bclink_set_queue_limits(new_value) == 0))
-			return cfg_reply_none();
-	       	return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-					      " (cannot change setting on broadcast link)");
+		    (tipc_bclink_set_queue_limits(new_value) == 0))
+			return tipc_cfg_reply_none();
+	       	return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+						   " (cannot change setting on broadcast link)");
 	}
 
-	read_lock_bh(&net_lock);
+	read_lock_bh(&tipc_net_lock);
 	l_ptr = link_find_link(args->name, &node); 
 	if (!l_ptr) {
-		read_unlock_bh(&net_lock);
-	       	return cfg_reply_error_string("link not found");
+		read_unlock_bh(&tipc_net_lock);
+	       	return tipc_cfg_reply_error_string("link not found");
 	}
 
-	node_lock(node);
+	tipc_node_lock(node);
 	res = -EINVAL;
 	switch (cmd) {
 	case TIPC_CMD_SET_LINK_TOL: 
 		if ((new_value >= TIPC_MIN_LINK_TOL) && 
 		    (new_value <= TIPC_MAX_LINK_TOL)) {
 			link_set_supervision_props(l_ptr, new_value);
-			link_send_proto_msg(l_ptr, STATE_MSG, 
-					    0, 0, new_value, 0, 0);
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+						 0, 0, new_value, 0, 0);
 			res = TIPC_OK;
 		}
 		break;
 	case TIPC_CMD_SET_LINK_PRI: 
-		if (new_value < TIPC_NUM_LINK_PRI) {
+		if ((new_value >= TIPC_MIN_LINK_PRI) &&
+		    (new_value <= TIPC_MAX_LINK_PRI)) {
 			l_ptr->priority = new_value;
-			link_send_proto_msg(l_ptr, STATE_MSG, 
-					    0, 0, 0, new_value, 0);
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+						 0, 0, 0, new_value, 0);
 			res = TIPC_OK;
 		}
 		break;
 	case TIPC_CMD_SET_LINK_WINDOW: 
 		if ((new_value >= TIPC_MIN_LINK_WIN) && 
 		    (new_value <= TIPC_MAX_LINK_WIN)) {
-			link_set_queue_limits(l_ptr, new_value);
+			tipc_link_set_queue_limits(l_ptr, new_value);
 			res = TIPC_OK;
 		}
 		break;
 	}
-	node_unlock(node);
+	tipc_node_unlock(node);
 
-	read_unlock_bh(&net_lock);
+	read_unlock_bh(&tipc_net_lock);
 	if (res)
-	       	return cfg_reply_error_string("cannot change link setting");
+	       	return tipc_cfg_reply_error_string("cannot change link setting");
 
-	return cfg_reply_none();
+	return tipc_cfg_reply_none();
 }
 
 /**
@@ -2848,34 +2847,34 @@
 	l_ptr->stats.recv_info = l_ptr->next_in_no;
 }
 
-struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space)
+struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space)
 {
 	char *link_name;
 	struct link *l_ptr; 
 	struct node *node;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	link_name = (char *)TLV_DATA(req_tlv_area);
-	if (!strcmp(link_name, bc_link_name)) {
-		if (bclink_reset_stats())
-			return cfg_reply_error_string("link not found");
-		return cfg_reply_none();
+	if (!strcmp(link_name, tipc_bclink_name)) {
+		if (tipc_bclink_reset_stats())
+			return tipc_cfg_reply_error_string("link not found");
+		return tipc_cfg_reply_none();
 	}
 
-	read_lock_bh(&net_lock);
+	read_lock_bh(&tipc_net_lock);
 	l_ptr = link_find_link(link_name, &node); 
 	if (!l_ptr) {
-		read_unlock_bh(&net_lock);
-		return cfg_reply_error_string("link not found");
+		read_unlock_bh(&tipc_net_lock);
+		return tipc_cfg_reply_error_string("link not found");
 	}
 
-	node_lock(node);
+	tipc_node_lock(node);
 	link_reset_statistics(l_ptr);
-	node_unlock(node);
-	read_unlock_bh(&net_lock);
-	return cfg_reply_none();
+	tipc_node_unlock(node);
+	read_unlock_bh(&tipc_net_lock);
+	return tipc_cfg_reply_none();
 }
 
 /**
@@ -2888,7 +2887,7 @@
 }
 
 /**
- * link_stats - print link statistics
+ * tipc_link_stats - print link statistics
  * @name: link name
  * @buf: print buffer area
  * @buf_size: size of print buffer area
@@ -2896,7 +2895,7 @@
  * Returns length of print buffer data string (or 0 if error)
  */
 
-static int link_stats(const char *name, char *buf, const u32 buf_size)
+static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
 {
 	struct print_buf pb;
 	struct link *l_ptr; 
@@ -2904,22 +2903,22 @@
 	char *status;
 	u32 profile_total = 0;
 
-	if (!strcmp(name, bc_link_name))
-		return bclink_stats(buf, buf_size);
+	if (!strcmp(name, tipc_bclink_name))
+		return tipc_bclink_stats(buf, buf_size);
 
-	printbuf_init(&pb, buf, buf_size);
+	tipc_printbuf_init(&pb, buf, buf_size);
 
-	read_lock_bh(&net_lock);
+	read_lock_bh(&tipc_net_lock);
 	l_ptr = link_find_link(name, &node); 
 	if (!l_ptr) {
-		read_unlock_bh(&net_lock);
+		read_unlock_bh(&tipc_net_lock);
 		return 0;
 	}
-	node_lock(node);
+	tipc_node_lock(node);
 
-	if (link_is_active(l_ptr))
+	if (tipc_link_is_active(l_ptr))
 		status = "ACTIVE";
-	else if (link_is_up(l_ptr))
+	else if (tipc_link_is_up(l_ptr))
 		status = "STANDBY";
 	else
 		status = "DEFUNCT";
@@ -2975,33 +2974,33 @@
 		    ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts)
 		    : 0);
 
-	node_unlock(node);
-	read_unlock_bh(&net_lock);
-	return printbuf_validate(&pb);
+	tipc_node_unlock(node);
+	read_unlock_bh(&tipc_net_lock);
+	return tipc_printbuf_validate(&pb);
 }
 
 #define MAX_LINK_STATS_INFO 2000
 
-struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space)
+struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space)
 {
 	struct sk_buff *buf;
 	struct tlv_desc *rep_tlv;
 	int str_len;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
-	buf = cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO));
+	buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO));
 	if (!buf)
 		return NULL;
 
 	rep_tlv = (struct tlv_desc *)buf->data;
 
-	str_len = link_stats((char *)TLV_DATA(req_tlv_area),
-			     (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO);
+	str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area),
+				  (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO);
 	if (!str_len) {
 		buf_discard(buf);
-	       	return cfg_reply_error_string("link not found");
+	       	return tipc_cfg_reply_error_string("link not found");
 	}
 
 	skb_put(buf, TLV_SPACE(str_len));
@@ -3020,20 +3019,20 @@
 	u32 a;
 
 	a = link_name2addr(name, &bearer_id);
-	read_lock_bh(&net_lock);
-	node = node_find(a);
+	read_lock_bh(&tipc_net_lock);
+	node = tipc_node_find(a);
 	if (node) {
-		node_lock(node);
+		tipc_node_lock(node);
 		l_ptr = node->links[bearer_id];
 		if (l_ptr) {
 			if (op == TIPC_REMOVE_LINK) {
 				struct bearer *b_ptr = l_ptr->b_ptr;
 				spin_lock_bh(&b_ptr->publ.lock);
-				link_delete(l_ptr);
+				tipc_link_delete(l_ptr);
 				spin_unlock_bh(&b_ptr->publ.lock);
 			}
 			if (op == TIPC_CMD_BLOCK_LINK) {
-				link_reset(l_ptr);
+				tipc_link_reset(l_ptr);
 				l_ptr->blocked = 1;
 			}
 			if (op == TIPC_CMD_UNBLOCK_LINK) {
@@ -3041,22 +3040,22 @@
 			}
 			res = TIPC_OK;
 		}
-		node_unlock(node);
+		tipc_node_unlock(node);
 	}
-	read_unlock_bh(&net_lock);
+	read_unlock_bh(&tipc_net_lock);
 	return res;
 }
 #endif
 
 /**
- * link_get_max_pkt - get maximum packet size to use when sending to destination
+ * tipc_link_get_max_pkt - get maximum packet size to use when sending to destination
  * @dest: network address of destination node
  * @selector: used to select from set of active links
  * 
  * If no active link can be found, uses default maximum packet size.
  */
 
-u32 link_get_max_pkt(u32 dest, u32 selector)
+u32 tipc_link_get_max_pkt(u32 dest, u32 selector)
 {
 	struct node *n_ptr;
 	struct link *l_ptr;
@@ -3065,16 +3064,16 @@
 	if (dest == tipc_own_addr)
 		return MAX_MSG_SIZE;
 
-	read_lock_bh(&net_lock);        
-	n_ptr = node_select(dest, selector);
+	read_lock_bh(&tipc_net_lock);        
+	n_ptr = tipc_node_select(dest, selector);
 	if (n_ptr) {
-		node_lock(n_ptr);
+		tipc_node_lock(n_ptr);
 		l_ptr = n_ptr->active_links[selector & 1];
 		if (l_ptr)
 			res = link_max_pkt(l_ptr);
-		node_unlock(n_ptr);
+		tipc_node_unlock(n_ptr);
 	}
-	read_unlock_bh(&net_lock);       
+	read_unlock_bh(&tipc_net_lock);       
 	return res;
 }
 
diff --git a/net/tipc/link.h b/net/tipc/link.h
index c2553f0..2d3c157 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -221,44 +221,43 @@
 
 struct port;
 
-struct link *link_create(struct bearer *b_ptr, const u32 peer,
-			 const struct tipc_media_addr *media_addr);
-void link_delete(struct link *l_ptr);
-void link_changeover(struct link *l_ptr);
-void link_send_duplicate(struct link *l_ptr, struct link *dest);
-void link_reset_fragments(struct link *l_ptr);
-int link_is_up(struct link *l_ptr);
-int link_is_active(struct link *l_ptr);
-void link_start(struct link *l_ptr);
-u32 link_push_packet(struct link *l_ptr);
-void link_stop(struct link *l_ptr);
-struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd);
-struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space);
-struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space);
-void link_reset(struct link *l_ptr);
-int link_send(struct sk_buff *buf, u32 dest, u32 selector);
-int link_send_buf(struct link *l_ptr, struct sk_buff *buf);
-u32 link_get_max_pkt(u32 dest,u32 selector);
-int link_send_sections_fast(struct port* sender, 
-			    struct iovec const *msg_sect,
-			    const u32 num_sect, 
-			    u32 destnode);
-
-int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf);
-void link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr,
-		 struct tipc_msg *msg, u32 selector);
-void link_recv_bundle(struct sk_buff *buf);
-int  link_recv_fragment(struct sk_buff **pending,
-			struct sk_buff **fb,
-			struct tipc_msg **msg);
-void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap, 
-			 u32 tolerance, u32 priority, u32 acked_mtu);
-void link_push_queue(struct link *l_ptr);
-u32 link_defer_pkt(struct sk_buff **head, struct sk_buff **tail,
+struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
+			      const struct tipc_media_addr *media_addr);
+void tipc_link_delete(struct link *l_ptr);
+void tipc_link_changeover(struct link *l_ptr);
+void tipc_link_send_duplicate(struct link *l_ptr, struct link *dest);
+void tipc_link_reset_fragments(struct link *l_ptr);
+int tipc_link_is_up(struct link *l_ptr);
+int tipc_link_is_active(struct link *l_ptr);
+void tipc_link_start(struct link *l_ptr);
+u32 tipc_link_push_packet(struct link *l_ptr);
+void tipc_link_stop(struct link *l_ptr);
+struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd);
+struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space);
+struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space);
+void tipc_link_reset(struct link *l_ptr);
+int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector);
+int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf);
+u32 tipc_link_get_max_pkt(u32 dest,u32 selector);
+int tipc_link_send_sections_fast(struct port* sender, 
+				 struct iovec const *msg_sect,
+				 const u32 num_sect, 
+				 u32 destnode);
+int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf);
+void tipc_link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr,
+		      struct tipc_msg *msg, u32 selector);
+void tipc_link_recv_bundle(struct sk_buff *buf);
+int  tipc_link_recv_fragment(struct sk_buff **pending,
+			     struct sk_buff **fb,
+			     struct tipc_msg **msg);
+void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap, 
+			      u32 tolerance, u32 priority, u32 acked_mtu);
+void tipc_link_push_queue(struct link *l_ptr);
+u32 tipc_link_defer_pkt(struct sk_buff **head, struct sk_buff **tail,
 		   struct sk_buff *buf);
-void link_wakeup_ports(struct link *l_ptr, int all);
-void link_set_queue_limits(struct link *l_ptr, u32 window);
-void link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits);
+void tipc_link_wakeup_ports(struct link *l_ptr, int all);
+void tipc_link_set_queue_limits(struct link *l_ptr, u32 window);
+void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits);
 
 /*
  * Link sequence number manipulation routines (uses modulo 2**16 arithmetic)
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 03dbc55..3bd345a 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -41,18 +41,7 @@
 #include "bearer.h"
 
 
-void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
-{
-	memcpy(&((int *)m)[5], a, sizeof(*a));
-}
-
-void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
-{
-	memcpy(a, &((int*)m)[5], sizeof(*a));
-}
-
-
-void msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str)
+void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str)
 {
 	u32 usr = msg_user(msg);
 	tipc_printf(buf, str);
@@ -318,7 +307,7 @@
 		tipc_printf(buf, ":REQL(%u):", msg_req_links(msg));
 		tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg));
 		tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg));
-		media_addr_printf(buf, orig);
+		tipc_media_addr_printf(buf, orig);
 	}
 	if (msg_user(msg) == BCAST_PROTOCOL) {
 		tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg));
@@ -326,9 +315,9 @@
 	}
 	tipc_printf(buf, "\n");
 	if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) {
-		msg_print(buf,msg_get_wrapped(msg),"      /");
+		tipc_msg_print(buf,msg_get_wrapped(msg),"      /");
 	}
 	if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) {
-		msg_print(buf,msg_get_wrapped(msg),"      /");
+		tipc_msg_print(buf,msg_get_wrapped(msg),"      /");
 	}
 }
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 662c818..6699aaf 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -37,7 +37,7 @@
 #ifndef _TIPC_MSG_H
 #define _TIPC_MSG_H
 
-#include <net/tipc/tipc_msg.h>
+#include "core.h"
 
 #define TIPC_VERSION              2
 #define DATA_LOW                  TIPC_LOW_IMPORTANCE
@@ -805,14 +805,14 @@
 	return -EFAULT;
 }
 
+static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
+{
+	memcpy(&((int *)m)[5], a, sizeof(*a));
+}
 
-struct tipc_media_addr;
-
-extern void msg_set_media_addr(struct tipc_msg *m,
-			       struct tipc_media_addr *a);
-
-extern void msg_get_media_addr(struct tipc_msg *m,
-			       struct tipc_media_addr *a);
-
+static inline void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
+{
+	memcpy(a, &((int*)m)[5], sizeof(*a));
+}
 
 #endif
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 41cbaf1..830f909 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -114,10 +114,10 @@
 }
 
 /**
- * named_publish - tell other nodes about a new publication by this node
+ * tipc_named_publish - tell other nodes about a new publication by this node
  */
 
-void named_publish(struct publication *publ)
+void tipc_named_publish(struct publication *publ)
 {
 	struct sk_buff *buf;
 	struct distr_item *item;
@@ -133,15 +133,15 @@
 
 	item = (struct distr_item *)msg_data(buf_msg(buf));
 	publ_to_item(item, publ);
-	dbg("named_withdraw: broadcasting publish msg\n");
-	cluster_broadcast(buf);
+	dbg("tipc_named_withdraw: broadcasting publish msg\n");
+	tipc_cltr_broadcast(buf);
 }
 
 /**
- * named_withdraw - tell other nodes about a withdrawn publication by this node
+ * tipc_named_withdraw - tell other nodes about a withdrawn publication by this node
  */
 
-void named_withdraw(struct publication *publ)
+void tipc_named_withdraw(struct publication *publ)
 {
 	struct sk_buff *buf;
 	struct distr_item *item;
@@ -157,15 +157,15 @@
 
 	item = (struct distr_item *)msg_data(buf_msg(buf));
 	publ_to_item(item, publ);
-	dbg("named_withdraw: broadcasting withdraw msg\n");
-	cluster_broadcast(buf);
+	dbg("tipc_named_withdraw: broadcasting withdraw msg\n");
+	tipc_cltr_broadcast(buf);
 }
 
 /**
- * named_node_up - tell specified node about all publications by this node
+ * tipc_named_node_up - tell specified node about all publications by this node
  */
 
-void named_node_up(unsigned long node)
+void tipc_named_node_up(unsigned long node)
 {
 	struct publication *publ;
 	struct distr_item *item = 0;
@@ -175,7 +175,7 @@
 	u32 max_item_buf;
 
 	assert(in_own_cluster(node));
-	read_lock_bh(&nametbl_lock); 
+	read_lock_bh(&tipc_nametbl_lock); 
 	max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE;
 	max_item_buf *= ITEM_SIZE;
 	rest = publ_cnt * ITEM_SIZE;
@@ -196,15 +196,15 @@
 		left -= ITEM_SIZE;
 		if (!left) {
 			msg_set_link_selector(buf_msg(buf), node);
-			dbg("named_node_up: sending publish msg to "
+			dbg("tipc_named_node_up: sending publish msg to "
 			    "<%u.%u.%u>\n", tipc_zone(node), 
 			    tipc_cluster(node), tipc_node(node));
-			link_send(buf, node, node);
+			tipc_link_send(buf, node, node);
 			buf = 0;
 		}
 	}
 exit:
-	read_unlock_bh(&nametbl_lock); 
+	read_unlock_bh(&tipc_nametbl_lock); 
 }
 
 /**
@@ -221,73 +221,73 @@
 static void node_is_down(struct publication *publ)
 {
 	struct publication *p;
-        write_lock_bh(&nametbl_lock);
+        write_lock_bh(&tipc_nametbl_lock);
 	dbg("node_is_down: withdrawing %u, %u, %u\n", 
 	    publ->type, publ->lower, publ->upper);
         publ->key += 1222345;
-	p = nametbl_remove_publ(publ->type, publ->lower, 
-				publ->node, publ->ref, publ->key);
+	p = tipc_nametbl_remove_publ(publ->type, publ->lower, 
+				     publ->node, publ->ref, publ->key);
         assert(p == publ);
-	write_unlock_bh(&nametbl_lock);
+	write_unlock_bh(&tipc_nametbl_lock);
 	if (publ)
 		kfree(publ);
 }
 
 /**
- * named_recv - process name table update message sent by another node
+ * tipc_named_recv - process name table update message sent by another node
  */
 
-void named_recv(struct sk_buff *buf)
+void tipc_named_recv(struct sk_buff *buf)
 {
 	struct publication *publ;
 	struct tipc_msg *msg = buf_msg(buf);
 	struct distr_item *item = (struct distr_item *)msg_data(msg);
 	u32 count = msg_data_sz(msg) / ITEM_SIZE;
 
-	write_lock_bh(&nametbl_lock); 
+	write_lock_bh(&tipc_nametbl_lock); 
 	while (count--) {
 		if (msg_type(msg) == PUBLICATION) {
-			dbg("named_recv: got publication for %u, %u, %u\n", 
+			dbg("tipc_named_recv: got publication for %u, %u, %u\n", 
 			    ntohl(item->type), ntohl(item->lower),
 			    ntohl(item->upper));
-			publ = nametbl_insert_publ(ntohl(item->type), 
-						   ntohl(item->lower),
-						   ntohl(item->upper),
-						   TIPC_CLUSTER_SCOPE,
-						   msg_orignode(msg), 
-						   ntohl(item->ref),
-						   ntohl(item->key));
+			publ = tipc_nametbl_insert_publ(ntohl(item->type), 
+							ntohl(item->lower),
+							ntohl(item->upper),
+							TIPC_CLUSTER_SCOPE,
+							msg_orignode(msg), 
+							ntohl(item->ref),
+							ntohl(item->key));
 			if (publ) {
-				nodesub_subscribe(&publ->subscr, 
-						  msg_orignode(msg), 
-						  publ,
-						  (net_ev_handler)node_is_down);
+				tipc_nodesub_subscribe(&publ->subscr, 
+						       msg_orignode(msg), 
+						       publ,
+						       (net_ev_handler)node_is_down);
 			}
 		} else if (msg_type(msg) == WITHDRAWAL) {
-			dbg("named_recv: got withdrawl for %u, %u, %u\n", 
+			dbg("tipc_named_recv: got withdrawl for %u, %u, %u\n", 
 			    ntohl(item->type), ntohl(item->lower),
 			    ntohl(item->upper));
-			publ = nametbl_remove_publ(ntohl(item->type),
-						   ntohl(item->lower),
-						   msg_orignode(msg),
-						   ntohl(item->ref),
-						   ntohl(item->key));
+			publ = tipc_nametbl_remove_publ(ntohl(item->type),
+							ntohl(item->lower),
+							msg_orignode(msg),
+							ntohl(item->ref),
+							ntohl(item->key));
 
 			if (publ) {
-				nodesub_unsubscribe(&publ->subscr);
+				tipc_nodesub_unsubscribe(&publ->subscr);
         			kfree(publ);
 			}
 		} else {
-			warn("named_recv: unknown msg\n");
+			warn("tipc_named_recv: unknown msg\n");
 		}
 		item++;
 	}
-	write_unlock_bh(&nametbl_lock); 
+	write_unlock_bh(&tipc_nametbl_lock); 
 	buf_discard(buf);
 }
 
 /**
- * named_reinit - re-initialize local publication list
+ * tipc_named_reinit - re-initialize local publication list
  * 
  * This routine is called whenever TIPC networking is (re)enabled.
  * All existing publications by this node that have "cluster" or "zone" scope
@@ -295,15 +295,15 @@
  * (If the node's address is unchanged, the update loop terminates immediately.)
  */
 
-void named_reinit(void)
+void tipc_named_reinit(void)
 {
 	struct publication *publ;
 
-	write_lock_bh(&nametbl_lock); 
+	write_lock_bh(&tipc_nametbl_lock); 
 	list_for_each_entry(publ, &publ_root, local_list) {
 		if (publ->node == tipc_own_addr)
 			break;
 		publ->node = tipc_own_addr;
 	}
-	write_unlock_bh(&nametbl_lock); 
+	write_unlock_bh(&tipc_nametbl_lock); 
 }
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h
index a04bdea..843da01 100644
--- a/net/tipc/name_distr.h
+++ b/net/tipc/name_distr.h
@@ -39,10 +39,10 @@
 
 #include "name_table.h"
 
-void named_publish(struct publication *publ);
-void named_withdraw(struct publication *publ);
-void named_node_up(unsigned long node);
-void named_recv(struct sk_buff *buf);
-void named_reinit(void);
+void tipc_named_publish(struct publication *publ);
+void tipc_named_withdraw(struct publication *publ);
+void tipc_named_node_up(unsigned long node);
+void tipc_named_recv(struct sk_buff *buf);
+void tipc_named_reinit(void);
 
 #endif
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 972c83e..3f4b23b 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -99,9 +99,9 @@
 	u32 local_publ_count;
 };
 
-struct name_table table = { NULL } ;
+static struct name_table table = { NULL } ;
 static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
-rwlock_t nametbl_lock = RW_LOCK_UNLOCKED;
+rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED;
 
 
 static inline int hash(int x)
@@ -139,10 +139,10 @@
 }
 
 /**
- * subseq_alloc - allocate a specified number of sub-sequence structures
+ * tipc_subseq_alloc - allocate a specified number of sub-sequence structures
  */
 
-struct sub_seq *subseq_alloc(u32 cnt)
+struct sub_seq *tipc_subseq_alloc(u32 cnt)
 {
 	u32 sz = cnt * sizeof(struct sub_seq);
 	struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC);
@@ -153,16 +153,16 @@
 }
 
 /**
- * nameseq_create - create a name sequence structure for the specified 'type'
+ * tipc_nameseq_create - create a name sequence structure for the specified 'type'
  * 
  * Allocates a single sub-sequence structure and sets it to all 0's.
  */
 
-struct name_seq *nameseq_create(u32 type, struct hlist_head *seq_head)
+struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head)
 {
 	struct name_seq *nseq = 
 		(struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC);
-	struct sub_seq *sseq = subseq_alloc(1);
+	struct sub_seq *sseq = tipc_subseq_alloc(1);
 
 	if (!nseq || !sseq) {
 		warn("Memory squeeze; failed to create name sequence\n");
@@ -175,7 +175,7 @@
 	nseq->lock = SPIN_LOCK_UNLOCKED;
 	nseq->type = type;
 	nseq->sseqs = sseq;
-	dbg("nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n",
+	dbg("tipc_nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n",
 	    nseq, type, nseq->sseqs, nseq->first_free);
 	nseq->alloc = 1;
 	INIT_HLIST_NODE(&nseq->ns_list);
@@ -240,10 +240,10 @@
 }
 
 /**
- * nameseq_insert_publ - 
+ * tipc_nameseq_insert_publ - 
  */
 
-struct publication *nameseq_insert_publ(struct name_seq *nseq,
+struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
 					u32 type, u32 lower, u32 upper,
 					u32 scope, u32 node, u32 port, u32 key)
 {
@@ -285,7 +285,7 @@
 
 		if (nseq->first_free == nseq->alloc) {
 			struct sub_seq *sseqs = nseq->sseqs;
-			nseq->sseqs = subseq_alloc(nseq->alloc * 2);
+			nseq->sseqs = tipc_subseq_alloc(nseq->alloc * 2);
 			if (nseq->sseqs != NULL) {
 				memcpy(nseq->sseqs, sseqs,
 				       nseq->alloc * sizeof (struct sub_seq));
@@ -354,23 +354,23 @@
 	 */
 	list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
 		dbg("calling report_overlap()\n");
-		subscr_report_overlap(s,
-				      publ->lower,
-				      publ->upper,
-				      TIPC_PUBLISHED,
-				      publ->ref, 
-				      publ->node,
-				      created_subseq);
+		tipc_subscr_report_overlap(s,
+					   publ->lower,
+					   publ->upper,
+					   TIPC_PUBLISHED,
+					   publ->ref, 
+					   publ->node,
+					   created_subseq);
 	}
 	return publ;
 }
 
 /**
- * nameseq_remove_publ -
+ * tipc_nameseq_remove_publ -
  */
 
-struct publication *nameseq_remove_publ(struct name_seq *nseq, u32 inst,
-					u32 node, u32 ref, u32 key)
+struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
+					     u32 node, u32 ref, u32 key)
 {
 	struct publication *publ;
 	struct publication *prev;
@@ -470,24 +470,24 @@
 	 * Any subscriptions waiting ? 
 	 */
 	list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
-		subscr_report_overlap(s,
-				      publ->lower,
-				      publ->upper,
-				      TIPC_WITHDRAWN, 
-				      publ->ref, 
-				      publ->node,
-				      removed_subseq);
+		tipc_subscr_report_overlap(s,
+					   publ->lower,
+					   publ->upper,
+					   TIPC_WITHDRAWN, 
+					   publ->ref, 
+					   publ->node,
+					   removed_subseq);
 	}
 	return publ;
 }
 
 /**
- * nameseq_subscribe: attach a subscription, and issue
+ * tipc_nameseq_subscribe: attach a subscription, and issue
  * the prescribed number of events if there is any sub-
  * sequence overlapping with the requested sequence
  */
 
-void nameseq_subscribe(struct name_seq *nseq, struct subscription *s)
+void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s)
 {
 	struct sub_seq *sseq = nseq->sseqs;
 
@@ -498,18 +498,18 @@
 
 	while (sseq != &nseq->sseqs[nseq->first_free]) {
 		struct publication *zl = sseq->zone_list;
-		if (zl && subscr_overlap(s,sseq->lower,sseq->upper)) {
+		if (zl && tipc_subscr_overlap(s,sseq->lower,sseq->upper)) {
 			struct publication *crs = zl;
 			int must_report = 1;
 
 			do {
-				subscr_report_overlap(s, 
-						       sseq->lower, 
-						       sseq->upper,
-						       TIPC_PUBLISHED,
-						       crs->ref,
-						       crs->node,
-						       must_report);
+				tipc_subscr_report_overlap(s, 
+							   sseq->lower, 
+							   sseq->upper,
+							   TIPC_PUBLISHED,
+							   crs->ref,
+							   crs->node,
+							   must_report);
 				must_report = 0;
 				crs = crs->zone_list_next;
 			} while (crs != zl);
@@ -538,8 +538,8 @@
 	return 0;
 };
 
-struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper,
-		    u32 scope, u32 node, u32 port, u32 key)
+struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
+					     u32 scope, u32 node, u32 port, u32 key)
 {
 	struct name_seq *seq = nametbl_find_seq(type);
 
@@ -552,19 +552,19 @@
 
 	dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node);
 	if (!seq) {
-		seq = nameseq_create(type, &table.types[hash(type)]);
-		dbg("nametbl_insert_publ: created %x\n", seq);
+		seq = tipc_nameseq_create(type, &table.types[hash(type)]);
+		dbg("tipc_nametbl_insert_publ: created %x\n", seq);
 	}
 	if (!seq)
 		return 0;
 
 	assert(seq->type == type);
-	return nameseq_insert_publ(seq, type, lower, upper,
-				   scope, node, port, key);
+	return tipc_nameseq_insert_publ(seq, type, lower, upper,
+					scope, node, port, key);
 }
 
-struct publication *nametbl_remove_publ(u32 type, u32 lower, 
-					u32 node, u32 ref, u32 key)
+struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, 
+					     u32 node, u32 ref, u32 key)
 {
 	struct publication *publ;
 	struct name_seq *seq = nametbl_find_seq(type);
@@ -573,7 +573,7 @@
 		return 0;
 
 	dbg("Withdrawing <%u,%u> from %x\n", type, lower, node);
-	publ = nameseq_remove_publ(seq, lower, node, ref, key);
+	publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
 
 	if (!seq->first_free && list_empty(&seq->subscriptions)) {
 		hlist_del_init(&seq->ns_list);
@@ -584,14 +584,14 @@
 }
 
 /*
- * nametbl_translate(): Translate tipc_name -> tipc_portid.
+ * tipc_nametbl_translate(): Translate tipc_name -> tipc_portid.
  *                      Very time-critical.
  *
  * Note: on entry 'destnode' is the search domain used during translation;
  *       on exit it passes back the node address of the matching port (if any)
  */
 
-u32 nametbl_translate(u32 type, u32 instance, u32 *destnode)
+u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
 {
 	struct sub_seq *sseq;
 	struct publication *publ = 0;
@@ -601,7 +601,7 @@
 	if (!in_scope(*destnode, tipc_own_addr))
 		return 0;
 
-	read_lock_bh(&nametbl_lock);
+	read_lock_bh(&tipc_nametbl_lock);
 	seq = nametbl_find_seq(type);
 	if (unlikely(!seq))
 		goto not_found;
@@ -619,7 +619,7 @@
 			ref = publ->ref;
 			*destnode = publ->node;
 			spin_unlock_bh(&seq->lock);
-			read_unlock_bh(&nametbl_lock);
+			read_unlock_bh(&tipc_nametbl_lock);
 			return ref;
 		}
 		publ = sseq->cluster_list;
@@ -657,12 +657,12 @@
 	spin_unlock_bh(&seq->lock);
 not_found:
 	*destnode = 0;
-	read_unlock_bh(&nametbl_lock);
+	read_unlock_bh(&tipc_nametbl_lock);
 	return 0;
 }
 
 /**
- * nametbl_mc_translate - find multicast destinations
+ * tipc_nametbl_mc_translate - find multicast destinations
  * 
  * Creates list of all local ports that overlap the given multicast address;
  * also determines if any off-node ports overlap.
@@ -674,15 +674,15 @@
  * Returns non-zero if any off-node ports overlap
  */
 
-int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
-			 struct port_list *dports)
+int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
+			      struct port_list *dports)
 {
 	struct name_seq *seq;
 	struct sub_seq *sseq;
 	struct sub_seq *sseq_stop;
 	int res = 0;
 
-	read_lock_bh(&nametbl_lock);
+	read_lock_bh(&tipc_nametbl_lock);
 	seq = nametbl_find_seq(type);
 	if (!seq)
 		goto exit;
@@ -700,7 +700,7 @@
 		if (publ && (publ->scope <= limit))
 			do {
 				if (publ->node == tipc_own_addr)
-					port_list_add(dports, publ->ref);
+					tipc_port_list_add(dports, publ->ref);
 				else
 					res = 1;
 				publ = publ->cluster_list_next;
@@ -709,15 +709,15 @@
 
 	spin_unlock_bh(&seq->lock);
 exit:
-	read_unlock_bh(&nametbl_lock);
+	read_unlock_bh(&tipc_nametbl_lock);
 	return res;
 }
 
 /**
- * nametbl_publish_rsv - publish port name using a reserved name type
+ * tipc_nametbl_publish_rsv - publish port name using a reserved name type
  */
 
-int nametbl_publish_rsv(u32 ref, unsigned int scope, 
+int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope, 
 			struct tipc_name_seq const *seq)
 {
 	int res;
@@ -729,10 +729,10 @@
 }
 
 /**
- * nametbl_publish - add name publication to network name tables
+ * tipc_nametbl_publish - add name publication to network name tables
  */
 
-struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, 
+struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, 
 				    u32 scope, u32 port_ref, u32 key)
 {
 	struct publication *publ;
@@ -748,77 +748,77 @@
 		return 0;
 	}
 
-	write_lock_bh(&nametbl_lock);
+	write_lock_bh(&tipc_nametbl_lock);
 	table.local_publ_count++;
-	publ = nametbl_insert_publ(type, lower, upper, scope,
+	publ = tipc_nametbl_insert_publ(type, lower, upper, scope,
 				   tipc_own_addr, port_ref, key);
 	if (publ && (scope != TIPC_NODE_SCOPE)) {
-		named_publish(publ);
+		tipc_named_publish(publ);
 	}
-	write_unlock_bh(&nametbl_lock);
+	write_unlock_bh(&tipc_nametbl_lock);
 	return publ;
 }
 
 /**
- * nametbl_withdraw - withdraw name publication from network name tables
+ * tipc_nametbl_withdraw - withdraw name publication from network name tables
  */
 
-int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
+int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
 {
 	struct publication *publ;
 
-	dbg("nametbl_withdraw:<%d,%d,%d>\n", type, lower, key);
-	write_lock_bh(&nametbl_lock);
-	publ = nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);
+	dbg("tipc_nametbl_withdraw:<%d,%d,%d>\n", type, lower, key);
+	write_lock_bh(&tipc_nametbl_lock);
+	publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);
 	if (publ) {
 		table.local_publ_count--;
 		if (publ->scope != TIPC_NODE_SCOPE)
-			named_withdraw(publ);
-		write_unlock_bh(&nametbl_lock);
+			tipc_named_withdraw(publ);
+		write_unlock_bh(&tipc_nametbl_lock);
 		list_del_init(&publ->pport_list);
 		kfree(publ);
 		return 1;
 	}
-	write_unlock_bh(&nametbl_lock);
+	write_unlock_bh(&tipc_nametbl_lock);
 	return 0;
 }
 
 /**
- * nametbl_subscribe - add a subscription object to the name table
+ * tipc_nametbl_subscribe - add a subscription object to the name table
  */
 
 void
-nametbl_subscribe(struct subscription *s)
+tipc_nametbl_subscribe(struct subscription *s)
 {
 	u32 type = s->seq.type;
 	struct name_seq *seq;
 
-        write_lock_bh(&nametbl_lock);
+        write_lock_bh(&tipc_nametbl_lock);
 	seq = nametbl_find_seq(type);
 	if (!seq) {
-		seq = nameseq_create(type, &table.types[hash(type)]);
+		seq = tipc_nameseq_create(type, &table.types[hash(type)]);
 	}
         if (seq){
                 spin_lock_bh(&seq->lock);
-                dbg("nametbl_subscribe:found %x for <%u,%u,%u>\n",
+                dbg("tipc_nametbl_subscribe:found %x for <%u,%u,%u>\n",
                     seq, type, s->seq.lower, s->seq.upper);
                 assert(seq->type == type);
-                nameseq_subscribe(seq, s);
+                tipc_nameseq_subscribe(seq, s);
                 spin_unlock_bh(&seq->lock);
         }
-        write_unlock_bh(&nametbl_lock);
+        write_unlock_bh(&tipc_nametbl_lock);
 }
 
 /**
- * nametbl_unsubscribe - remove a subscription object from name table
+ * tipc_nametbl_unsubscribe - remove a subscription object from name table
  */
 
 void
-nametbl_unsubscribe(struct subscription *s)
+tipc_nametbl_unsubscribe(struct subscription *s)
 {
 	struct name_seq *seq;
 
-        write_lock_bh(&nametbl_lock);
+        write_lock_bh(&tipc_nametbl_lock);
         seq = nametbl_find_seq(s->seq.type);
 	if (seq != NULL){
                 spin_lock_bh(&seq->lock);
@@ -830,7 +830,7 @@
                         kfree(seq);
                 }
         }
-        write_unlock_bh(&nametbl_lock);
+        write_unlock_bh(&tipc_nametbl_lock);
 }
 
 
@@ -983,17 +983,17 @@
 	}
 }
 
-void nametbl_print(struct print_buf *buf, const char *str)
+void tipc_nametbl_print(struct print_buf *buf, const char *str)
 {
 	tipc_printf(buf, str);
-	read_lock_bh(&nametbl_lock);
+	read_lock_bh(&tipc_nametbl_lock);
 	nametbl_list(buf, 0, 0, 0, 0);
-	read_unlock_bh(&nametbl_lock);
+	read_unlock_bh(&tipc_nametbl_lock);
 }
 
 #define MAX_NAME_TBL_QUERY 32768
 
-struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space)
+struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
 {
 	struct sk_buff *buf;
 	struct tipc_name_table_query *argv;
@@ -1002,20 +1002,20 @@
 	int str_len;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
-	buf = cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY));
+	buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY));
 	if (!buf)
 		return NULL;
 
 	rep_tlv = (struct tlv_desc *)buf->data;
-	printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY);
+	tipc_printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY);
 	argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
-	read_lock_bh(&nametbl_lock);
+	read_lock_bh(&tipc_nametbl_lock);
 	nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), 
 		     ntohl(argv->lowbound), ntohl(argv->upbound));
-	read_unlock_bh(&nametbl_lock);
-	str_len = printbuf_validate(&b);
+	read_unlock_bh(&tipc_nametbl_lock);
+	str_len = tipc_printbuf_validate(&b);
 
 	skb_put(buf, TLV_SPACE(str_len));
 	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
@@ -1023,12 +1023,12 @@
 	return buf;
 }
 
-void nametbl_dump(void)
+void tipc_nametbl_dump(void)
 {
-	nametbl_list(CONS, 0, 0, 0, 0);
+	nametbl_list(TIPC_CONS, 0, 0, 0, 0);
 }
 
-int nametbl_init(void)
+int tipc_nametbl_init(void)
 {
 	int array_size = sizeof(struct hlist_head) * tipc_nametbl_size;
 
@@ -1036,14 +1036,14 @@
 	if (!table.types)
 		return -ENOMEM;
 
-	write_lock_bh(&nametbl_lock);
+	write_lock_bh(&tipc_nametbl_lock);
 	memset(table.types, 0, array_size);
 	table.local_publ_count = 0;
-	write_unlock_bh(&nametbl_lock);
+	write_unlock_bh(&tipc_nametbl_lock);
 	return 0;
 }
 
-void nametbl_stop(void)
+void tipc_nametbl_stop(void)
 {
 	struct hlist_head *seq_head;
 	struct hlist_node *seq_node;
@@ -1054,7 +1054,7 @@
 	if (!table.types)
 		return;
 
-	write_lock_bh(&nametbl_lock);
+	write_lock_bh(&tipc_nametbl_lock);
 	for (i = 0; i < tipc_nametbl_size; i++) {
 		seq_head = &table.types[i];
 		hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) {
@@ -1075,5 +1075,5 @@
 	}
 	kfree(table.types);
 	table.types = NULL;
-	write_unlock_bh(&nametbl_lock);
+	write_unlock_bh(&tipc_nametbl_lock);
 }
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index f826933..e8a3d71 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -85,24 +85,24 @@
 };
 
 
-extern rwlock_t nametbl_lock;
+extern rwlock_t tipc_nametbl_lock;
 
-struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space);
-u32 nametbl_translate(u32 type, u32 instance, u32 *node);
-int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, 
+struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space);
+u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node);
+int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, 
 			 struct port_list *dports);
-int nametbl_publish_rsv(u32 ref, unsigned int scope, 
+int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope, 
 			struct tipc_name_seq const *seq);
-struct publication *nametbl_publish(u32 type, u32 lower, u32 upper,
+struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
 				    u32 scope, u32 port_ref, u32 key);
-int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key);
-struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper,
+int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key);
+struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
 					u32 scope, u32 node, u32 ref, u32 key);
-struct publication *nametbl_remove_publ(u32 type, u32 lower, 
+struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, 
 					u32 node, u32 ref, u32 key);
-void nametbl_subscribe(struct subscription *s);
-void nametbl_unsubscribe(struct subscription *s);
-int nametbl_init(void);
-void nametbl_stop(void);
+void tipc_nametbl_subscribe(struct subscription *s);
+void tipc_nametbl_unsubscribe(struct subscription *s);
+int tipc_nametbl_init(void);
+void tipc_nametbl_stop(void);
 
 #endif
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 6826b49..074891a 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -58,25 +58,25 @@
  * 1: The routing hierarchy.
  *    Comprises the structures 'zone', 'cluster', 'node', 'link' 
  *    and 'bearer'. The whole hierarchy is protected by a big 
- *    read/write lock, net_lock, to enssure that nothing is added 
+ *    read/write lock, tipc_net_lock, to enssure that nothing is added 
  *    or removed while code is accessing any of these structures. 
  *    This layer must not be called from the two others while they 
  *    hold any of their own locks.
  *    Neither must it itself do any upcalls to the other two before
- *    it has released net_lock and other protective locks.
+ *    it has released tipc_net_lock and other protective locks.
  *
- *   Within the net_lock domain there are two sub-domains;'node' and 
+ *   Within the tipc_net_lock domain there are two sub-domains;'node' and 
  *   'bearer', where local write operations are permitted,
  *   provided that those are protected by individual spin_locks
- *   per instance. Code holding net_lock(read) and a node spin_lock 
+ *   per instance. Code holding tipc_net_lock(read) and a node spin_lock 
  *   is permitted to poke around in both the node itself and its
  *   subordinate links. I.e, it can update link counters and queues, 
  *   change link state, send protocol messages, and alter the 
  *   "active_links" array in the node; but it can _not_ remove a link 
  *   or a node from the overall structure.
  *   Correspondingly, individual bearers may change status within a 
- *   net_lock(read), protected by an individual spin_lock ber bearer 
- *   instance, but it needs net_lock(write) to remove/add any bearers.
+ *   tipc_net_lock(read), protected by an individual spin_lock ber bearer 
+ *   instance, but it needs tipc_net_lock(write) to remove/add any bearers.
  *     
  *
  *  2: The transport level of the protocol. 
@@ -97,91 +97,91 @@
  *       (Nobody is using read-only access to this, so it can just as 
  *       well be changed to a spin_lock)
  *     - A spin lock to protect the registry of kernel/driver users (reg.c)
- *     - A global spin_lock (port_lock), which only task is to ensure 
+ *     - A global spin_lock (tipc_port_lock), which only task is to ensure 
  *       consistency where more than one port is involved in an operation,
  *       i.e., whe a port is part of a linked list of ports.
  *       There are two such lists; 'port_list', which is used for management,
  *       and 'wait_list', which is used to queue ports during congestion.
  *     
  *  3: The name table (name_table.c, name_distr.c, subscription.c)
- *     - There is one big read/write-lock (nametbl_lock) protecting the 
+ *     - There is one big read/write-lock (tipc_nametbl_lock) protecting the 
  *       overall name table structure. Nothing must be added/removed to 
  *       this structure without holding write access to it.
  *     - There is one local spin_lock per sub_sequence, which can be seen
- *       as a sub-domain to the nametbl_lock domain. It is used only
+ *       as a sub-domain to the tipc_nametbl_lock domain. It is used only
  *       for translation operations, and is needed because a translation
  *       steps the root of the 'publication' linked list between each lookup.
- *       This is always used within the scope of a nametbl_lock(read).
+ *       This is always used within the scope of a tipc_nametbl_lock(read).
  *     - A local spin_lock protecting the queue of subscriber events.
 */
 
-rwlock_t net_lock = RW_LOCK_UNLOCKED;
-struct network net = { 0 };
+rwlock_t tipc_net_lock = RW_LOCK_UNLOCKED;
+struct network tipc_net = { 0 };
 
-struct node *net_select_remote_node(u32 addr, u32 ref) 
+struct node *tipc_net_select_remote_node(u32 addr, u32 ref) 
 {
-	return zone_select_remote_node(net.zones[tipc_zone(addr)], addr, ref);
+	return tipc_zone_select_remote_node(tipc_net.zones[tipc_zone(addr)], addr, ref);
 }
 
-u32 net_select_router(u32 addr, u32 ref)
+u32 tipc_net_select_router(u32 addr, u32 ref)
 {
-	return zone_select_router(net.zones[tipc_zone(addr)], addr, ref);
+	return tipc_zone_select_router(tipc_net.zones[tipc_zone(addr)], addr, ref);
 }
 
 
-u32 net_next_node(u32 a)
+u32 tipc_net_next_node(u32 a)
 {
-	if (net.zones[tipc_zone(a)])
-		return zone_next_node(a);
+	if (tipc_net.zones[tipc_zone(a)])
+		return tipc_zone_next_node(a);
 	return 0;
 }
 
-void net_remove_as_router(u32 router)
+void tipc_net_remove_as_router(u32 router)
 {
 	u32 z_num;
 
 	for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
-		if (!net.zones[z_num])
+		if (!tipc_net.zones[z_num])
 			continue;
-		zone_remove_as_router(net.zones[z_num], router);
+		tipc_zone_remove_as_router(tipc_net.zones[z_num], router);
 	}
 }
 
-void net_send_external_routes(u32 dest)
+void tipc_net_send_external_routes(u32 dest)
 {
 	u32 z_num;
 
 	for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
-		if (net.zones[z_num])
-			zone_send_external_routes(net.zones[z_num], dest);
+		if (tipc_net.zones[z_num])
+			tipc_zone_send_external_routes(tipc_net.zones[z_num], dest);
 	}
 }
 
-int net_init(void)
+static int net_init(void)
 {
 	u32 sz = sizeof(struct _zone *) * (tipc_max_zones + 1);
 
-	memset(&net, 0, sizeof(net));
-	net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC);
-	if (!net.zones) {
+	memset(&tipc_net, 0, sizeof(tipc_net));
+	tipc_net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC);
+	if (!tipc_net.zones) {
 		return -ENOMEM;
 	}
-	memset(net.zones, 0, sz);
+	memset(tipc_net.zones, 0, sz);
 	return TIPC_OK;
 }
 
-void net_stop(void)
+static void net_stop(void)
 {
 	u32 z_num;
 
-	if (!net.zones)
+	if (!tipc_net.zones)
 		return;
 
 	for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
-		zone_delete(net.zones[z_num]);
+		tipc_zone_delete(tipc_net.zones[z_num]);
 	}
-	kfree(net.zones);
-	net.zones = 0;
+	kfree(tipc_net.zones);
+	tipc_net.zones = 0;
 }
 
 static void net_route_named_msg(struct sk_buff *buf)
@@ -191,26 +191,26 @@
 	u32 dport;
 
 	if (!msg_named(msg)) {
-		msg_dbg(msg, "net->drop_nam:");
+		msg_dbg(msg, "tipc_net->drop_nam:");
 		buf_discard(buf);
 		return;
 	}
 
 	dnode = addr_domain(msg_lookup_scope(msg));
-	dport = nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode);
-	dbg("net->lookup<%u,%u>-><%u,%x>\n",
+	dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode);
+	dbg("tipc_net->lookup<%u,%u>-><%u,%x>\n",
 	    msg_nametype(msg), msg_nameinst(msg), dport, dnode);
 	if (dport) {
 		msg_set_destnode(msg, dnode);
 		msg_set_destport(msg, dport);
-		net_route_msg(buf);
+		tipc_net_route_msg(buf);
 		return;
 	}
-	msg_dbg(msg, "net->rej:NO NAME: ");
+	msg_dbg(msg, "tipc_net->rej:NO NAME: ");
 	tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
 }
 
-void net_route_msg(struct sk_buff *buf)
+void tipc_net_route_msg(struct sk_buff *buf)
 {
 	struct tipc_msg *msg;
 	u32 dnode;
@@ -232,29 +232,29 @@
 		return;
 	}
 
-	msg_dbg(msg, "net->rout: ");
+	msg_dbg(msg, "tipc_net->rout: ");
 
 	/* Handle message for this node */
 	dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg);
 	if (in_scope(dnode, tipc_own_addr)) {
 		if (msg_isdata(msg)) {
 			if (msg_mcast(msg)) 
-				port_recv_mcast(buf, NULL);
+				tipc_port_recv_mcast(buf, NULL);
 			else if (msg_destport(msg))
-				port_recv_msg(buf);
+				tipc_port_recv_msg(buf);
 			else
 				net_route_named_msg(buf);
 			return;
 		}
 		switch (msg_user(msg)) {
 		case ROUTE_DISTRIBUTOR:
-			cluster_recv_routing_table(buf);
+			tipc_cltr_recv_routing_table(buf);
 			break;
 		case NAME_DISTRIBUTOR:
-			named_recv(buf);
+			tipc_named_recv(buf);
 			break;
 		case CONN_MANAGER:
-			port_recv_proto_msg(buf);
+			tipc_port_recv_proto_msg(buf);
 			break;
 		default:
 			msg_dbg(msg,"DROP/NET/<REC<");
@@ -265,10 +265,10 @@
 
 	/* Handle message for another node */
 	msg_dbg(msg, "NET>SEND>: ");
-	link_send(buf, dnode, msg_link_selector(msg));
+	tipc_link_send(buf, dnode, msg_link_selector(msg));
 }
 
-int tipc_start_net(void)
+int tipc_net_start(void)
 {
 	char addr_string[16];
 	int res;
@@ -277,35 +277,35 @@
 		return -ENOPROTOOPT;
 
 	tipc_mode = TIPC_NET_MODE;
-	named_reinit();
-	port_reinit();
+	tipc_named_reinit();
+	tipc_port_reinit();
 
-	if ((res = bearer_init()) ||
+	if ((res = tipc_bearer_init()) ||
 	    (res = net_init()) ||
-	    (res = cluster_init()) ||
-	    (res = bclink_init())) {
+	    (res = tipc_cltr_init()) ||
+	    (res = tipc_bclink_init())) {
 		return res;
 	}
-        subscr_stop();
-	cfg_stop();
-	k_signal((Handler)subscr_start, 0);
-	k_signal((Handler)cfg_init, 0);
+        tipc_subscr_stop();
+	tipc_cfg_stop();
+	tipc_k_signal((Handler)tipc_subscr_start, 0);
+	tipc_k_signal((Handler)tipc_cfg_init, 0);
 	info("Started in network mode\n");
 	info("Own node address %s, network identity %u\n",
 	     addr_string_fill(addr_string, tipc_own_addr), tipc_net_id);
 	return TIPC_OK;
 }
 
-void tipc_stop_net(void)
+void tipc_net_stop(void)
 {
 	if (tipc_mode != TIPC_NET_MODE)
 		return;
-        write_lock_bh(&net_lock);
-	bearer_stop();
+        write_lock_bh(&tipc_net_lock);
+	tipc_bearer_stop();
 	tipc_mode = TIPC_NODE_MODE;
-	bclink_stop();
+	tipc_bclink_stop();
 	net_stop();
-        write_unlock_bh(&net_lock);
+        write_unlock_bh(&tipc_net_lock);
 	info("Left network mode \n");
 }
 
diff --git a/net/tipc/net.h b/net/tipc/net.h
index 948c6d42..f3e0b85 100644
--- a/net/tipc/net.h
+++ b/net/tipc/net.h
@@ -49,18 +49,16 @@
 };
 
 
-extern struct network net;
-extern rwlock_t net_lock;
+extern struct network tipc_net;
+extern rwlock_t tipc_net_lock;
 
-int net_init(void);
-void net_stop(void);
-void net_remove_as_router(u32 router);
-void net_send_external_routes(u32 dest);
-void net_route_msg(struct sk_buff *buf);
-struct node *net_select_remote_node(u32 addr, u32 ref);
-u32 net_select_router(u32 addr, u32 ref);
+void tipc_net_remove_as_router(u32 router);
+void tipc_net_send_external_routes(u32 dest);
+void tipc_net_route_msg(struct sk_buff *buf);
+struct node *tipc_net_select_remote_node(u32 addr, u32 ref);
+u32 tipc_net_select_router(u32 addr, u32 ref);
 
-int tipc_start_net(void);
-void tipc_stop_net(void);
+int tipc_net_start(void);
+void tipc_net_stop(void);
 
 #endif
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 19b3f40..eb1bb4d 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -47,13 +47,13 @@
 	int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN);
 
 	if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN)))
-		rep_buf = cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
+		rep_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
 	else
-		rep_buf = cfg_do_cmd(req_userhdr->dest,
-				     req_userhdr->cmd,
-				     NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
-				     NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
-				     hdr_space);
+		rep_buf = tipc_cfg_do_cmd(req_userhdr->dest,
+					  req_userhdr->cmd,
+					  NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
+					  NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
+					  hdr_space);
 
 	if (rep_buf) {
 		skb_push(rep_buf, hdr_space);
@@ -81,7 +81,7 @@
 
 static int family_registered = 0;
 
-int netlink_start(void)
+int tipc_netlink_start(void)
 {
 
 
@@ -103,7 +103,7 @@
 	return -EFAULT;
 }
 
-void netlink_stop(void)
+void tipc_netlink_stop(void)
 {
 	if (family_registered) {
 		genl_unregister_family(&family);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 05688d0..6d65010 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -45,17 +45,16 @@
 #include "port.h"
 #include "bearer.h"
 #include "name_distr.h"
-#include "net.h"
 
 void node_print(struct print_buf *buf, struct node *n_ptr, char *str);
 static void node_lost_contact(struct node *n_ptr);
 static void node_established_contact(struct node *n_ptr);
 
-struct node *nodes = NULL;	/* sorted list of nodes within cluster */
+struct node *tipc_nodes = NULL;	/* sorted list of nodes within cluster */
 
 u32 tipc_own_tag = 0;
 
-struct node *node_create(u32 addr)
+struct node *tipc_node_create(u32 addr)
 {
 	struct cluster *c_ptr;
 	struct node *n_ptr;
@@ -68,16 +67,16 @@
                 n_ptr->lock =  SPIN_LOCK_UNLOCKED;	
                 INIT_LIST_HEAD(&n_ptr->nsub);
 	
-		c_ptr = cluster_find(addr);
+		c_ptr = tipc_cltr_find(addr);
                 if (c_ptr == NULL)
-                        c_ptr = cluster_create(addr);
+                        c_ptr = tipc_cltr_create(addr);
                 if (c_ptr != NULL) {
                         n_ptr->owner = c_ptr;
-                        cluster_attach_node(c_ptr, n_ptr);
+                        tipc_cltr_attach_node(c_ptr, n_ptr);
                         n_ptr->last_router = -1;
 
                         /* Insert node into ordered list */
-                        for (curr_node = &nodes; *curr_node; 
+                        for (curr_node = &tipc_nodes; *curr_node; 
 			     curr_node = &(*curr_node)->next) {
                                 if (addr < (*curr_node)->addr) {
                                         n_ptr->next = *curr_node;
@@ -93,13 +92,13 @@
 	return n_ptr;
 }
 
-void node_delete(struct node *n_ptr)
+void tipc_node_delete(struct node *n_ptr)
 {
 	if (!n_ptr)
 		return;
 
 #if 0
-	/* Not needed because links are already deleted via bearer_stop() */
+	/* Not needed because links are already deleted via tipc_bearer_stop() */
 
 	u32 l_num;
 
@@ -114,12 +113,12 @@
 
 
 /**
- * node_link_up - handle addition of link
+ * tipc_node_link_up - handle addition of link
  * 
  * Link becomes active (alone or shared) or standby, depending on its priority.
  */
 
-void node_link_up(struct node *n_ptr, struct link *l_ptr)
+void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
 {
 	struct link **active = &n_ptr->active_links[0];
 
@@ -136,7 +135,7 @@
 		info("Link is standby\n");
 		return;
 	}
-	link_send_duplicate(active[0], l_ptr);
+	tipc_link_send_duplicate(active[0], l_ptr);
 	if (l_ptr->priority == active[0]->priority) { 
 		active[0] = l_ptr;
 		return;
@@ -161,7 +160,7 @@
 	for (i = 0; i < MAX_BEARERS; i++) {
                 struct link *l_ptr = n_ptr->links[i];
 
-		if (!l_ptr || !link_is_up(l_ptr) ||
+		if (!l_ptr || !tipc_link_is_up(l_ptr) ||
 		    (l_ptr->priority < highest_prio))
 			continue;
 
@@ -175,14 +174,14 @@
 }
 
 /**
- * node_link_down - handle loss of link
+ * tipc_node_link_down - handle loss of link
  */
 
-void node_link_down(struct node *n_ptr, struct link *l_ptr)
+void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr)
 {
 	struct link **active;
 
-	if (!link_is_active(l_ptr)) {
+	if (!tipc_link_is_active(l_ptr)) {
 		info("Lost standby link <%s> on network plane %c\n",
 		     l_ptr->name, l_ptr->b_ptr->net_plane);
 		return;
@@ -197,40 +196,40 @@
 		active[1] = active[0];
 	if (active[0] == l_ptr)
 		node_select_active_links(n_ptr);
-	if (node_is_up(n_ptr)) 
-		link_changeover(l_ptr);
+	if (tipc_node_is_up(n_ptr)) 
+		tipc_link_changeover(l_ptr);
 	else 
 		node_lost_contact(n_ptr);
 }
 
-int node_has_active_links(struct node *n_ptr)
+int tipc_node_has_active_links(struct node *n_ptr)
 {
 	return (n_ptr && 
 		((n_ptr->active_links[0]) || (n_ptr->active_links[1])));
 }
 
-int node_has_redundant_links(struct node *n_ptr)
+int tipc_node_has_redundant_links(struct node *n_ptr)
 {
-	return (node_has_active_links(n_ptr) &&
+	return (tipc_node_has_active_links(n_ptr) &&
 		(n_ptr->active_links[0] != n_ptr->active_links[1]));
 }
 
-int node_has_active_routes(struct node *n_ptr)
+int tipc_node_has_active_routes(struct node *n_ptr)
 {
 	return (n_ptr && (n_ptr->last_router >= 0));
 }
 
-int node_is_up(struct node *n_ptr)
+int tipc_node_is_up(struct node *n_ptr)
 {
-	return (node_has_active_links(n_ptr) || node_has_active_routes(n_ptr));
+	return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr));
 }
 
-struct node *node_attach_link(struct link *l_ptr)
+struct node *tipc_node_attach_link(struct link *l_ptr)
 {
-	struct node *n_ptr = node_find(l_ptr->addr);
+	struct node *n_ptr = tipc_node_find(l_ptr->addr);
 
 	if (!n_ptr)
-		n_ptr = node_create(l_ptr->addr);
+		n_ptr = tipc_node_create(l_ptr->addr);
         if (n_ptr) {
 		u32 bearer_id = l_ptr->b_ptr->identity;
 		char addr_string[16];
@@ -246,7 +245,7 @@
 
                 if (!n_ptr->links[bearer_id]) {
                         n_ptr->links[bearer_id] = l_ptr;
-                        net.zones[tipc_zone(l_ptr->addr)]->links++;
+                        tipc_net.zones[tipc_zone(l_ptr->addr)]->links++;
                         n_ptr->link_cnt++;
                         return n_ptr;
                 }
@@ -257,10 +256,10 @@
 	return 0;
 }
 
-void node_detach_link(struct node *n_ptr, struct link *l_ptr)
+void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr)
 {
 	n_ptr->links[l_ptr->b_ptr->identity] = 0;
-	net.zones[tipc_zone(l_ptr->addr)]->links--;
+	tipc_net.zones[tipc_zone(l_ptr->addr)]->links--;
 	n_ptr->link_cnt--;
 }
 
@@ -315,45 +314,45 @@
 	struct cluster *c_ptr;
 
 	dbg("node_established_contact:-> %x\n", n_ptr->addr);
-	if (!node_has_active_routes(n_ptr)) { 
-		k_signal((Handler)named_node_up, n_ptr->addr);
+	if (!tipc_node_has_active_routes(n_ptr)) { 
+		tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
 	}
 
         /* Syncronize broadcast acks */
-        n_ptr->bclink.acked = bclink_get_last_sent();
+        n_ptr->bclink.acked = tipc_bclink_get_last_sent();
 
 	if (is_slave(tipc_own_addr))
 		return;
 	if (!in_own_cluster(n_ptr->addr)) {
 		/* Usage case 1 (see above) */
-		c_ptr = cluster_find(tipc_own_addr);
+		c_ptr = tipc_cltr_find(tipc_own_addr);
 		if (!c_ptr)
-			c_ptr = cluster_create(tipc_own_addr);
+			c_ptr = tipc_cltr_create(tipc_own_addr);
                 if (c_ptr)
-                        cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, 
-						tipc_max_nodes);
+                        tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, 
+						  tipc_max_nodes);
 		return;
 	} 
 
 	c_ptr = n_ptr->owner;
 	if (is_slave(n_ptr->addr)) {
 		/* Usage case 2 (see above) */
-		cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes);
-		cluster_send_local_routes(c_ptr, n_ptr->addr);
+		tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes);
+		tipc_cltr_send_local_routes(c_ptr, n_ptr->addr);
 		return;
 	}
 
 	if (n_ptr->bclink.supported) {
-		nmap_add(&cluster_bcast_nodes, n_ptr->addr);
+		tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr);
 		if (n_ptr->addr < tipc_own_addr)
 			tipc_own_tag++;
 	}
 
 	/* Case 3 (see above) */
-	net_send_external_routes(n_ptr->addr);
-	cluster_send_slave_routes(c_ptr, n_ptr->addr);
-	cluster_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE,
-				highest_allowed_slave);
+	tipc_net_send_external_routes(n_ptr->addr);
+	tipc_cltr_send_slave_routes(c_ptr, n_ptr->addr);
+	tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE,
+				  tipc_highest_allowed_slave);
 }
 
 static void node_lost_contact(struct node *n_ptr)
@@ -375,39 +374,39 @@
                 n_ptr->bclink.defragm = NULL;
         }            
         if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { 
-                bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000));
+                tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000));
         }
 
         /* Update routing tables */
 	if (is_slave(tipc_own_addr)) {
-		net_remove_as_router(n_ptr->addr);
+		tipc_net_remove_as_router(n_ptr->addr);
 	} else {
 		if (!in_own_cluster(n_ptr->addr)) { 
 			/* Case 4 (see above) */
-			c_ptr = cluster_find(tipc_own_addr);
-			cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1,
-						 tipc_max_nodes);
+			c_ptr = tipc_cltr_find(tipc_own_addr);
+			tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1,
+						   tipc_max_nodes);
 		} else {
 			/* Case 5 (see above) */
-			c_ptr = cluster_find(n_ptr->addr);
+			c_ptr = tipc_cltr_find(n_ptr->addr);
 			if (is_slave(n_ptr->addr)) {
-				cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1,
-							 tipc_max_nodes);
+				tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1,
+							   tipc_max_nodes);
 			} else {
 				if (n_ptr->bclink.supported) {
-					nmap_remove(&cluster_bcast_nodes, 
-						    n_ptr->addr);
+					tipc_nmap_remove(&tipc_cltr_bcast_nodes, 
+							 n_ptr->addr);
 					if (n_ptr->addr < tipc_own_addr)
 						tipc_own_tag--;
 				}
-				net_remove_as_router(n_ptr->addr);
-				cluster_bcast_lost_route(c_ptr, n_ptr->addr,
-							 LOWEST_SLAVE,
-							 highest_allowed_slave);
+				tipc_net_remove_as_router(n_ptr->addr);
+				tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr,
+							   LOWEST_SLAVE,
+							   tipc_highest_allowed_slave);
 			}
 		}
 	}
-	if (node_has_active_routes(n_ptr))
+	if (tipc_node_has_active_routes(n_ptr))
 		return;
 
 	info("Lost contact with %s\n", 
@@ -420,35 +419,35 @@
 			continue;
 		l_ptr->reset_checkpoint = l_ptr->next_in_no;
 		l_ptr->exp_msg_count = 0;
-		link_reset_fragments(l_ptr);
+		tipc_link_reset_fragments(l_ptr);
 	}
 
 	/* Notify subscribers */
 	list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {
                 ns->node = 0;
 		list_del_init(&ns->nodesub_list);
-		k_signal((Handler)ns->handle_node_down,
-			 (unsigned long)ns->usr_handle);
+		tipc_k_signal((Handler)ns->handle_node_down,
+			      (unsigned long)ns->usr_handle);
 	}
 }
 
 /**
- * node_select_next_hop - find the next-hop node for a message
+ * tipc_node_select_next_hop - find the next-hop node for a message
  * 
  * Called by when cluster local lookup has failed.
  */
 
-struct node *node_select_next_hop(u32 addr, u32 selector)
+struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
 {
 	struct node *n_ptr;
 	u32 router_addr;
 
-        if (!addr_domain_valid(addr))
+        if (!tipc_addr_domain_valid(addr))
                 return 0;
 
 	/* Look for direct link to destination processsor */
-	n_ptr = node_find(addr);
-	if (n_ptr && node_has_active_links(n_ptr))
+	n_ptr = tipc_node_find(addr);
+	if (n_ptr && tipc_node_has_active_links(n_ptr))
                 return n_ptr;
 
 	/* Cluster local system nodes *must* have direct links */
@@ -456,9 +455,9 @@
 		return 0;
 
 	/* Look for cluster local router with direct link to node */
-	router_addr = node_select_router(n_ptr, selector);
+	router_addr = tipc_node_select_router(n_ptr, selector);
 	if (router_addr) 
-                return node_select(router_addr, selector);
+                return tipc_node_select(router_addr, selector);
 
 	/* Slave nodes can only be accessed within own cluster via a 
 	   known router with direct link -- if no router was found,give up */
@@ -467,25 +466,25 @@
 
 	/* Inter zone/cluster -- find any direct link to remote cluster */
 	addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
-	n_ptr = net_select_remote_node(addr, selector);
-	if (n_ptr && node_has_active_links(n_ptr))
+	n_ptr = tipc_net_select_remote_node(addr, selector);
+	if (n_ptr && tipc_node_has_active_links(n_ptr))
                 return n_ptr;
 
 	/* Last resort -- look for any router to anywhere in remote zone */
-	router_addr =  net_select_router(addr, selector);
+	router_addr =  tipc_net_select_router(addr, selector);
 	if (router_addr) 
-                return node_select(router_addr, selector);
+                return tipc_node_select(router_addr, selector);
 
         return 0;
 }
 
 /**
- * node_select_router - select router to reach specified node
+ * tipc_node_select_router - select router to reach specified node
  * 
  * Uses a deterministic and fair algorithm for selecting router node. 
  */
 
-u32 node_select_router(struct node *n_ptr, u32 ref)
+u32 tipc_node_select_router(struct node *n_ptr, u32 ref)
 {
 	u32 ulim;
 	u32 mask;
@@ -523,7 +522,7 @@
 	return tipc_addr(own_zone(), own_cluster(), r);
 }
 
-void node_add_router(struct node *n_ptr, u32 router)
+void tipc_node_add_router(struct node *n_ptr, u32 router)
 {
 	u32 r_num = tipc_node(router);
 
@@ -534,7 +533,7 @@
 	       !n_ptr->routers[n_ptr->last_router]);
 }
 
-void node_remove_router(struct node *n_ptr, u32 router)
+void tipc_node_remove_router(struct node *n_ptr, u32 router)
 {
 	u32 r_num = tipc_node(router);
 
@@ -547,7 +546,7 @@
 	while ((--n_ptr->last_router >= 0) && 
 	       !n_ptr->routers[n_ptr->last_router]);
 
-	if (!node_is_up(n_ptr))
+	if (!tipc_node_is_up(n_ptr))
 		node_lost_contact(n_ptr);
 }
 
@@ -572,16 +571,16 @@
 	struct node *n_ptr;
 	u32 cnt = 0;
 
-	for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) {
+	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
 		if (!in_scope(domain, n_ptr->addr))
 			continue;
-		if (node_is_up(n_ptr))
+		if (tipc_node_is_up(n_ptr))
 			cnt++;
 	}
 	return cnt;
 }
 
-struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space)
+struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
 {
 	u32 domain;
 	struct sk_buff *buf;
@@ -589,40 +588,40 @@
         struct tipc_node_info node_info;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	domain = *(u32 *)TLV_DATA(req_tlv_area);
 	domain = ntohl(domain);
-	if (!addr_domain_valid(domain))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (network address)");
+	if (!tipc_addr_domain_valid(domain))
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (network address)");
 
-        if (!nodes)
-                return cfg_reply_none();
+        if (!tipc_nodes)
+                return tipc_cfg_reply_none();
 
 	/* For now, get space for all other nodes 
 	   (will need to modify this when slave nodes are supported */
 
-	buf = cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) *
-			    (tipc_max_nodes - 1));
+	buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) *
+				   (tipc_max_nodes - 1));
 	if (!buf)
 		return NULL;
 
 	/* Add TLVs for all nodes in scope */
 
-	for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) {
+	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
 		if (!in_scope(domain, n_ptr->addr))
 			continue;
                 node_info.addr = htonl(n_ptr->addr);
-                node_info.up = htonl(node_is_up(n_ptr));
-		cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, 
-			       &node_info, sizeof(node_info));
+                node_info.up = htonl(tipc_node_is_up(n_ptr));
+		tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, 
+				    &node_info, sizeof(node_info));
 	}
 
 	return buf;
 }
 
-struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space)
+struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
 {
 	u32 domain;
 	struct sk_buff *buf;
@@ -630,22 +629,22 @@
         struct tipc_link_info link_info;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
 	domain = *(u32 *)TLV_DATA(req_tlv_area);
 	domain = ntohl(domain);
-	if (!addr_domain_valid(domain))
-		return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-					      " (network address)");
+	if (!tipc_addr_domain_valid(domain))
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+						   " (network address)");
 
-        if (!nodes)
-                return cfg_reply_none();
+        if (!tipc_nodes)
+                return tipc_cfg_reply_none();
 
 	/* For now, get space for 2 links to all other nodes + bcast link 
 	   (will need to modify this when slave nodes are supported */
 
-	buf = cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) *
-			    (2 * (tipc_max_nodes - 1) + 1));
+	buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) *
+				   (2 * (tipc_max_nodes - 1) + 1));
 	if (!buf)
 		return NULL;
 
@@ -654,12 +653,12 @@
         link_info.dest = tipc_own_addr & 0xfffff00;
 	link_info.dest = htonl(link_info.dest);
         link_info.up = htonl(1);
-        sprintf(link_info.str, bc_link_name);
-	cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
+        sprintf(link_info.str, tipc_bclink_name);
+	tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
 
 	/* Add TLVs for any other links in scope */
 
-	for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) {
+	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
                 u32 i;
 
 		if (!in_scope(domain, n_ptr->addr))
@@ -668,10 +667,10 @@
                         if (!n_ptr->links[i]) 
                                 continue;
                         link_info.dest = htonl(n_ptr->addr);
-                        link_info.up = htonl(link_is_up(n_ptr->links[i]));
+                        link_info.up = htonl(tipc_link_is_up(n_ptr->links[i]));
                         strcpy(link_info.str, n_ptr->links[i]->name);
-			cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, 
-				       &link_info, sizeof(link_info));
+			tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, 
+					    &link_info, sizeof(link_info));
                 }
 	}
 
diff --git a/net/tipc/node.h b/net/tipc/node.h
index b39442b..29f7ae6 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -92,31 +92,31 @@
 	} bclink;
 };
 
-extern struct node *nodes;
+extern struct node *tipc_nodes;
 extern u32 tipc_own_tag;
 
-struct node *node_create(u32 addr);
-void node_delete(struct node *n_ptr);
-struct node *node_attach_link(struct link *l_ptr);
-void node_detach_link(struct node *n_ptr, struct link *l_ptr);
-void node_link_down(struct node *n_ptr, struct link *l_ptr);
-void node_link_up(struct node *n_ptr, struct link *l_ptr);
-int node_has_active_links(struct node *n_ptr);
-int node_has_redundant_links(struct node *n_ptr);
-u32 node_select_router(struct node *n_ptr, u32 ref);
-struct node *node_select_next_hop(u32 addr, u32 selector);
-int node_is_up(struct node *n_ptr);
-void node_add_router(struct node *n_ptr, u32 router);
-void node_remove_router(struct node *n_ptr, u32 router);
-struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space);
-struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space);
+struct node *tipc_node_create(u32 addr);
+void tipc_node_delete(struct node *n_ptr);
+struct node *tipc_node_attach_link(struct link *l_ptr);
+void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr);
+void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr);
+void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr);
+int tipc_node_has_active_links(struct node *n_ptr);
+int tipc_node_has_redundant_links(struct node *n_ptr);
+u32 tipc_node_select_router(struct node *n_ptr, u32 ref);
+struct node *tipc_node_select_next_hop(u32 addr, u32 selector);
+int tipc_node_is_up(struct node *n_ptr);
+void tipc_node_add_router(struct node *n_ptr, u32 router);
+void tipc_node_remove_router(struct node *n_ptr, u32 router);
+struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
+struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
 
-static inline struct node *node_find(u32 addr)
+static inline struct node *tipc_node_find(u32 addr)
 {
 	if (likely(in_own_cluster(addr)))
-		return local_nodes[tipc_node(addr)];
-	else if (addr_domain_valid(addr)) {
-		struct cluster *c_ptr = cluster_find(addr);
+		return tipc_local_nodes[tipc_node(addr)];
+	else if (tipc_addr_domain_valid(addr)) {
+		struct cluster *c_ptr = tipc_cltr_find(addr);
 
 		if (c_ptr)
 			return c_ptr->nodes[tipc_node(addr)];
@@ -124,19 +124,19 @@
 	return 0;
 }
 
-static inline struct node *node_select(u32 addr, u32 selector)
+static inline struct node *tipc_node_select(u32 addr, u32 selector)
 {
 	if (likely(in_own_cluster(addr)))
-		return local_nodes[tipc_node(addr)];
-	return node_select_next_hop(addr, selector);
+		return tipc_local_nodes[tipc_node(addr)];
+	return tipc_node_select_next_hop(addr, selector);
 }
 
-static inline void node_lock(struct node *n_ptr)
+static inline void tipc_node_lock(struct node *n_ptr)
 {
 	spin_lock_bh(&n_ptr->lock);
 }
 
-static inline void node_unlock(struct node *n_ptr)
+static inline void tipc_node_unlock(struct node *n_ptr)
 {
 	spin_unlock_bh(&n_ptr->lock);
 }
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
index 7937592..afeea12 100644
--- a/net/tipc/node_subscr.c
+++ b/net/tipc/node_subscr.c
@@ -41,39 +41,39 @@
 #include "addr.h"
 
 /**
- * nodesub_subscribe - create "node down" subscription for specified node
+ * tipc_nodesub_subscribe - create "node down" subscription for specified node
  */
 
-void nodesub_subscribe(struct node_subscr *node_sub, u32 addr, 
+void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr, 
 		       void *usr_handle, net_ev_handler handle_down)
 {
 	node_sub->node = 0;
 	if (addr == tipc_own_addr)
 		return;
-	if (!addr_node_valid(addr)) {
+	if (!tipc_addr_node_valid(addr)) {
 		warn("node_subscr with illegal %x\n", addr);
 		return;
 	}
 
 	node_sub->handle_node_down = handle_down;
 	node_sub->usr_handle = usr_handle;
-	node_sub->node = node_find(addr);
+	node_sub->node = tipc_node_find(addr);
 	assert(node_sub->node);
-	node_lock(node_sub->node);
+	tipc_node_lock(node_sub->node);
 	list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub);
-	node_unlock(node_sub->node);
+	tipc_node_unlock(node_sub->node);
 }
 
 /**
- * nodesub_unsubscribe - cancel "node down" subscription (if any)
+ * tipc_nodesub_unsubscribe - cancel "node down" subscription (if any)
  */
 
-void nodesub_unsubscribe(struct node_subscr *node_sub)
+void tipc_nodesub_unsubscribe(struct node_subscr *node_sub)
 {
 	if (!node_sub->node)
 		return;
 
-	node_lock(node_sub->node);
+	tipc_node_lock(node_sub->node);
 	list_del_init(&node_sub->nodesub_list);
-	node_unlock(node_sub->node);
+	tipc_node_unlock(node_sub->node);
 }
diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h
index a3b87ac..01751c4 100644
--- a/net/tipc/node_subscr.h
+++ b/net/tipc/node_subscr.h
@@ -56,8 +56,8 @@
 	struct list_head nodesub_list;
 };
 
-void nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
-		       void *usr_handle, net_ev_handler handle_down);
-void nodesub_unsubscribe(struct node_subscr *node_sub);
+void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
+			    void *usr_handle, net_ev_handler handle_down);
+void tipc_nodesub_unsubscribe(struct node_subscr *node_sub);
 
 #endif
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 66caca7..72aae52 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -57,10 +57,10 @@
 static struct sk_buff *msg_queue_head = 0;
 static struct sk_buff *msg_queue_tail = 0;
 
-spinlock_t port_list_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t tipc_port_list_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED;
 
-LIST_HEAD(ports);
+static LIST_HEAD(ports);
 static void port_handle_node_down(unsigned long ref);
 static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err);
 static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err);
@@ -107,7 +107,7 @@
 	struct sk_buff *buf;
 	struct sk_buff *ibuf = NULL;
 	struct port_list dports = {0, NULL, };
-	struct port *oport = port_deref(ref);
+	struct port *oport = tipc_port_deref(ref);
 	int ext_targets;
 	int res;
 
@@ -129,8 +129,8 @@
 
 	/* Figure out where to send multicast message */
 
-	ext_targets = nametbl_mc_translate(seq->type, seq->lower, seq->upper,
-					   TIPC_NODE_SCOPE, &dports);
+	ext_targets = tipc_nametbl_mc_translate(seq->type, seq->lower, seq->upper,
+						TIPC_NODE_SCOPE, &dports);
 	
 	/* Send message to destinations (duplicate it only if necessary) */ 
 
@@ -138,12 +138,12 @@
 		if (dports.count != 0) {
 			ibuf = skb_copy(buf, GFP_ATOMIC);
 			if (ibuf == NULL) {
-				port_list_free(&dports);
+				tipc_port_list_free(&dports);
 				buf_discard(buf);
 				return -ENOMEM;
 			}
 		}
-		res = bclink_send_msg(buf);
+		res = tipc_bclink_send_msg(buf);
 		if ((res < 0) && (dports.count != 0)) {
 			buf_discard(ibuf);
 		}
@@ -153,20 +153,20 @@
 
 	if (res >= 0) {
 		if (ibuf)
-			port_recv_mcast(ibuf, &dports);
+			tipc_port_recv_mcast(ibuf, &dports);
 	} else {
-		port_list_free(&dports);
+		tipc_port_list_free(&dports);
 	}
 	return res;
 }
 
 /**
- * port_recv_mcast - deliver multicast message to all destination ports
+ * tipc_port_recv_mcast - deliver multicast message to all destination ports
  * 
  * If there is no port list, perform a lookup to create one
  */
 
-void port_recv_mcast(struct sk_buff *buf, struct port_list *dp)
+void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp)
 {
 	struct tipc_msg* msg;
 	struct port_list dports = {0, NULL, };
@@ -179,7 +179,7 @@
 	/* Create destination port list, if one wasn't supplied */
 
 	if (dp == NULL) {
-		nametbl_mc_translate(msg_nametype(msg),
+		tipc_nametbl_mc_translate(msg_nametype(msg),
 				     msg_namelower(msg),
 				     msg_nameupper(msg),
 				     TIPC_CLUSTER_SCOPE,
@@ -192,8 +192,8 @@
 	if (dp->count != 0) {
 		if (dp->count == 1) {
 			msg_set_destport(msg, dp->ports[0]);
-			port_recv_msg(buf);
-			port_list_free(dp);
+			tipc_port_recv_msg(buf);
+			tipc_port_list_free(dp);
 			return;
 		}
 		for (; cnt < dp->count; cnt++) {
@@ -209,12 +209,12 @@
 				item = item->next;
 			}
 			msg_set_destport(buf_msg(b),item->ports[index]);
-			port_recv_msg(b);
+			tipc_port_recv_msg(b);
 		}
 	}
 exit:
 	buf_discard(buf);
-	port_list_free(dp);
+	tipc_port_list_free(dp);
 }
 
 /**
@@ -238,14 +238,14 @@
 		return 0;
 	}
 	memset(p_ptr, 0, sizeof(*p_ptr));
-	ref = ref_acquire(p_ptr, &p_ptr->publ.lock);
+	ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock);
 	if (!ref) {
 		warn("Reference Table Exhausted\n");
 		kfree(p_ptr);
 		return 0;
 	}
 
-	port_lock(ref);
+	tipc_port_lock(ref);
 	p_ptr->publ.ref = ref;
 	msg = &p_ptr->publ.phdr;
 	msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0);
@@ -264,12 +264,12 @@
 	p_ptr->wakeup = wakeup;
 	p_ptr->user_port = 0;
 	k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref);
-	spin_lock_bh(&port_list_lock);
+	spin_lock_bh(&tipc_port_list_lock);
 	INIT_LIST_HEAD(&p_ptr->publications);
 	INIT_LIST_HEAD(&p_ptr->port_list);
 	list_add_tail(&p_ptr->port_list, &ports);
-	spin_unlock_bh(&port_list_lock);
-	port_unlock(p_ptr);
+	spin_unlock_bh(&tipc_port_list_lock);
+	tipc_port_unlock(p_ptr);
 	return ref;
 }
 
@@ -279,31 +279,31 @@
 	struct sk_buff *buf = 0;
 
 	tipc_withdraw(ref, 0, 0);
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr) 
 		return -EINVAL;
 
-	ref_discard(ref);
-	port_unlock(p_ptr);
+	tipc_ref_discard(ref);
+	tipc_port_unlock(p_ptr);
 
 	k_cancel_timer(&p_ptr->timer);
 	if (p_ptr->publ.connected) {
 		buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
-		nodesub_unsubscribe(&p_ptr->subscription);
+		tipc_nodesub_unsubscribe(&p_ptr->subscription);
 	}
 	if (p_ptr->user_port) {
-		reg_remove_port(p_ptr->user_port);
+		tipc_reg_remove_port(p_ptr->user_port);
 		kfree(p_ptr->user_port);
 	}
 
-	spin_lock_bh(&port_list_lock);
+	spin_lock_bh(&tipc_port_list_lock);
 	list_del(&p_ptr->port_list);
 	list_del(&p_ptr->wait_list);
-	spin_unlock_bh(&port_list_lock);
+	spin_unlock_bh(&tipc_port_list_lock);
 	k_term_timer(&p_ptr->timer);
 	kfree(p_ptr);
 	dbg("Deleted port %u\n", ref);
-	net_route_msg(buf);
+	tipc_net_route_msg(buf);
 	return TIPC_OK;
 }
 
@@ -315,7 +315,7 @@
 
 struct tipc_port *tipc_get_port(const u32 ref)
 {
-	return (struct tipc_port *)ref_deref(ref);
+	return (struct tipc_port *)tipc_ref_deref(ref);
 }
 
 /**
@@ -327,11 +327,11 @@
 	struct port *p_ptr;
 	void * handle;
 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return 0;
 	handle = p_ptr->publ.usr_handle;
-	port_unlock(p_ptr);
+	tipc_port_unlock(p_ptr);
 	return handle;
 }
 
@@ -344,7 +344,7 @@
 {
 	struct port *p_ptr;
 	
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	*isunreliable = port_unreliable(p_ptr);
@@ -356,11 +356,11 @@
 {
 	struct port *p_ptr;
 	
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0));
-	port_unlock(p_ptr);
+	tipc_port_unlock(p_ptr);
 	return TIPC_OK;
 }
 
@@ -373,7 +373,7 @@
 {
 	struct port *p_ptr;
 	
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	*isunrejectable = port_unreturnable(p_ptr);
@@ -385,11 +385,11 @@
 {
 	struct port *p_ptr;
 	
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0));
-	port_unlock(p_ptr);
+	tipc_port_unlock(p_ptr);
 	return TIPC_OK;
 }
 
@@ -476,25 +476,25 @@
 	/* send self-abort message when rejecting on a connected port */
 	if (msg_connected(msg)) {
 		struct sk_buff *abuf = 0;
-		struct port *p_ptr = port_lock(msg_destport(msg));
+		struct port *p_ptr = tipc_port_lock(msg_destport(msg));
 
 		if (p_ptr) {
 			if (p_ptr->publ.connected)
 				abuf = port_build_self_abort_msg(p_ptr, err);
-			port_unlock(p_ptr);
+			tipc_port_unlock(p_ptr);
 		}
-		net_route_msg(abuf);
+		tipc_net_route_msg(abuf);
 	}
 
 	/* send rejected message */
 	buf_discard(buf);
-	net_route_msg(rbuf);
+	tipc_net_route_msg(rbuf);
 	return data_sz;
 }
 
-int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
-			 struct iovec const *msg_sect, u32 num_sect,
-			 int err)
+int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
+			      struct iovec const *msg_sect, u32 num_sect,
+			      int err)
 {
 	struct sk_buff *buf;
 	int res;
@@ -509,7 +509,7 @@
 
 static void port_timeout(unsigned long ref)
 {
-	struct port *p_ptr = port_lock(ref);
+	struct port *p_ptr = tipc_port_lock(ref);
 	struct sk_buff *buf = 0;
 
 	if (!p_ptr || !p_ptr->publ.connected)
@@ -532,21 +532,21 @@
 		p_ptr->probing_state = PROBING;
 		k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
 	}
-	port_unlock(p_ptr);
-	net_route_msg(buf);
+	tipc_port_unlock(p_ptr);
+	tipc_net_route_msg(buf);
 }
 
 
 static void port_handle_node_down(unsigned long ref)
 {
-	struct port *p_ptr = port_lock(ref);
+	struct port *p_ptr = tipc_port_lock(ref);
 	struct sk_buff* buf = 0;
 
 	if (!p_ptr)
 		return;
 	buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE);
-	port_unlock(p_ptr);
-	net_route_msg(buf);
+	tipc_port_unlock(p_ptr);
+	tipc_net_route_msg(buf);
 }
 
 
@@ -589,10 +589,10 @@
 				    0);
 }
 
-void port_recv_proto_msg(struct sk_buff *buf)
+void tipc_port_recv_proto_msg(struct sk_buff *buf)
 {
 	struct tipc_msg *msg = buf_msg(buf);
-	struct port *p_ptr = port_lock(msg_destport(msg));
+	struct port *p_ptr = tipc_port_lock(msg_destport(msg));
 	u32 err = TIPC_OK;
 	struct sk_buff *r_buf = 0;
 	struct sk_buff *abort_buf = 0;
@@ -615,11 +615,11 @@
 			}
 		}
 		if (msg_type(msg) == CONN_ACK) {
-			int wakeup = port_congested(p_ptr) && 
+			int wakeup = tipc_port_congested(p_ptr) && 
 				     p_ptr->publ.congested &&
 				     p_ptr->wakeup;
 			p_ptr->acked += msg_msgcnt(msg);
-			if (port_congested(p_ptr))
+			if (tipc_port_congested(p_ptr))
 				goto exit;
 			p_ptr->publ.congested = 0;
 			if (!wakeup)
@@ -659,9 +659,9 @@
 	port_incr_out_seqno(p_ptr);
 exit:
 	if (p_ptr)
-		port_unlock(p_ptr);
-	net_route_msg(r_buf);
-	net_route_msg(abort_buf);
+		tipc_port_unlock(p_ptr);
+	tipc_net_route_msg(r_buf);
+	tipc_net_route_msg(abort_buf);
 	buf_discard(buf);
 }
 
@@ -704,7 +704,7 @@
 
 #define MAX_PORT_QUERY 32768
 
-struct sk_buff *port_get_ports(void)
+struct sk_buff *tipc_port_get_ports(void)
 {
 	struct sk_buff *buf;
 	struct tlv_desc *rep_tlv;
@@ -712,20 +712,20 @@
 	struct port *p_ptr;
 	int str_len;
 
-	buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY));
+	buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY));
 	if (!buf)
 		return NULL;
 	rep_tlv = (struct tlv_desc *)buf->data;
 
-	printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY);
-	spin_lock_bh(&port_list_lock);
+	tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY);
+	spin_lock_bh(&tipc_port_list_lock);
 	list_for_each_entry(p_ptr, &ports, port_list) {
 		spin_lock_bh(p_ptr->publ.lock);
 		port_print(p_ptr, &pb, 0);
 		spin_unlock_bh(p_ptr->publ.lock);
 	}
-	spin_unlock_bh(&port_list_lock);
-	str_len = printbuf_validate(&pb);
+	spin_unlock_bh(&tipc_port_list_lock);
+	str_len = tipc_printbuf_validate(&pb);
 
 	skb_put(buf, TLV_SPACE(str_len));
 	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
@@ -752,22 +752,22 @@
 	ref = *(u32 *)TLV_DATA(req_tlv_area);
 	ref = ntohl(ref);
 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return cfg_reply_error_string("port not found");
 
-	buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS));
+	buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS));
 	if (!buf) {
-		port_unlock(p_ptr);
+		tipc_port_unlock(p_ptr);
 		return NULL;
 	}
 	rep_tlv = (struct tlv_desc *)buf->data;
 
-	printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS);
+	tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS);
 	port_print(p_ptr, &pb, 1);
 	/* NEED TO FILL IN ADDITIONAL PORT STATISTICS HERE */
-	port_unlock(p_ptr);
-	str_len = printbuf_validate(&pb);
+	tipc_port_unlock(p_ptr);
+	str_len = tipc_printbuf_validate(&pb);
 
 	skb_put(buf, TLV_SPACE(str_len));
 	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
@@ -777,19 +777,19 @@
 
 #endif
 
-void port_reinit(void)
+void tipc_port_reinit(void)
 {
 	struct port *p_ptr;
 	struct tipc_msg *msg;
 
-	spin_lock_bh(&port_list_lock);
+	spin_lock_bh(&tipc_port_list_lock);
 	list_for_each_entry(p_ptr, &ports, port_list) {
 		msg = &p_ptr->publ.phdr;
 		if (msg_orignode(msg) == tipc_own_addr)
 			break;
 		msg_set_orignode(msg, tipc_own_addr);
 	}
-	spin_unlock_bh(&port_list_lock);
+	spin_unlock_bh(&tipc_port_list_lock);
 }
 
 
@@ -820,7 +820,7 @@
 		struct tipc_msg *msg = buf_msg(buf);
 		u32 dref = msg_destport(msg);
 		
-		p_ptr = port_lock(dref);
+		p_ptr = tipc_port_lock(dref);
 		if (!p_ptr) {
 			/* Port deleted while msg in queue */
 			tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
@@ -976,7 +976,7 @@
 		msg_queue_tail = buf;
 	} else {
 		msg_queue_tail = msg_queue_head = buf;
-		k_signal((Handler)port_dispatcher_sigh, 0);
+		tipc_k_signal((Handler)port_dispatcher_sigh, 0);
 	}
 	spin_unlock_bh(&queue_lock);
 	return TIPC_OK;
@@ -994,14 +994,14 @@
 	tipc_continue_event cb = 0;
 	void *uh = 0;
 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (p_ptr) {
 		up_ptr = p_ptr->user_port;
 		if (up_ptr) {
 			cb = up_ptr->continue_event_cb;
 			uh = up_ptr->usr_handle;
 		}
-		port_unlock(p_ptr);
+		tipc_port_unlock(p_ptr);
 	}
 	if (cb)
 		cb(uh, ref);
@@ -1010,7 +1010,7 @@
 
 static void port_wakeup(struct tipc_port *p_ptr)
 {
-	k_signal((Handler)port_wakeup_sh, p_ptr->ref);
+	tipc_k_signal((Handler)port_wakeup_sh, p_ptr->ref);
 }
 
 void tipc_acknowledge(u32 ref, u32 ack)
@@ -1018,7 +1018,7 @@
 	struct port *p_ptr;
 	struct sk_buff *buf = 0;
 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return;
 	if (p_ptr->publ.connected) {
@@ -1033,8 +1033,8 @@
 					   port_out_seqno(p_ptr),
 					   ack);
 	}
-	port_unlock(p_ptr);
-	net_route_msg(buf);
+	tipc_port_unlock(p_ptr);
+	tipc_net_route_msg(buf);
 }
 
 /*
@@ -1063,7 +1063,7 @@
 		return -ENOMEM;
 	}
 	ref = tipc_createport_raw(0, port_dispatcher, port_wakeup, importance);
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr) {
 		kfree(up_ptr);
 		return -ENOMEM;
@@ -1081,10 +1081,10 @@
 	up_ptr->conn_msg_cb = conn_msg_cb;
 	up_ptr->continue_event_cb = continue_event_cb;
 	INIT_LIST_HEAD(&up_ptr->uport_list);
-	reg_add_port(up_ptr);
+	tipc_reg_add_port(up_ptr);
 	*portref = p_ptr->publ.ref;
 	dbg(" tipc_createport: %x with ref %u\n", p_ptr, p_ptr->publ.ref);        
-	port_unlock(p_ptr);
+	tipc_port_unlock(p_ptr);
 	return TIPC_OK;
 }
 
@@ -1099,7 +1099,7 @@
 {
 	struct port *p_ptr;
 	
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	*importance = (unsigned int)msg_importance(&p_ptr->publ.phdr);
@@ -1114,7 +1114,7 @@
 	if (imp > TIPC_CRITICAL_IMPORTANCE)
 		return -EINVAL;
 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	msg_set_importance(&p_ptr->publ.phdr, (u32)imp);
@@ -1130,7 +1130,7 @@
 	u32 key;
 	int res = -EINVAL;
 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, "
 	    "lower = %u, upper = %u\n",
 	    ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper);
@@ -1147,8 +1147,8 @@
 		res = -EADDRINUSE;
 		goto exit;
 	}
-	publ = nametbl_publish(seq->type, seq->lower, seq->upper,
-			       scope, p_ptr->publ.ref, key);
+	publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
+				    scope, p_ptr->publ.ref, key);
 	if (publ) {
 		list_add(&publ->pport_list, &p_ptr->publications);
 		p_ptr->pub_count++;
@@ -1156,7 +1156,7 @@
 		res = TIPC_OK;
 	}
 exit:
-	port_unlock(p_ptr);
+	tipc_port_unlock(p_ptr);
 	return res;
 }
 
@@ -1167,7 +1167,7 @@
 	struct publication *tpubl;
 	int res = -EINVAL;
 	
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	if (!p_ptr->publ.published)
@@ -1175,8 +1175,8 @@
 	if (!seq) {
 		list_for_each_entry_safe(publ, tpubl, 
 					 &p_ptr->publications, pport_list) {
-			nametbl_withdraw(publ->type, publ->lower, 
-					 publ->ref, publ->key);
+			tipc_nametbl_withdraw(publ->type, publ->lower, 
+					      publ->ref, publ->key);
 		}
 		res = TIPC_OK;
 	} else {
@@ -1190,8 +1190,8 @@
 				continue;
 			if (publ->upper != seq->upper)
 				break;
-			nametbl_withdraw(publ->type, publ->lower, 
-					 publ->ref, publ->key);
+			tipc_nametbl_withdraw(publ->type, publ->lower, 
+					      publ->ref, publ->key);
 			res = TIPC_OK;
 			break;
 		}
@@ -1199,7 +1199,7 @@
 	if (list_empty(&p_ptr->publications))
 		p_ptr->publ.published = 0;
 exit:
-	port_unlock(p_ptr);
+	tipc_port_unlock(p_ptr);
 	return res;
 }
 
@@ -1209,7 +1209,7 @@
 	struct tipc_msg *msg;
 	int res = -EINVAL;
 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	if (p_ptr->publ.published || p_ptr->publ.connected)
@@ -1234,13 +1234,13 @@
 	p_ptr->publ.connected = 1;
 	k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
 
-	nodesub_subscribe(&p_ptr->subscription,peer->node,
+	tipc_nodesub_subscribe(&p_ptr->subscription,peer->node,
 			  (void *)(unsigned long)ref,
 			  (net_ev_handler)port_handle_node_down);
 	res = TIPC_OK;
 exit:
-	port_unlock(p_ptr);
-	p_ptr->max_pkt = link_get_max_pkt(peer->node, ref);
+	tipc_port_unlock(p_ptr);
+	p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
 	return res;
 }
 
@@ -1254,16 +1254,16 @@
 	struct port *p_ptr;
 	int res = -ENOTCONN;
 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	if (p_ptr->publ.connected) {
 		p_ptr->publ.connected = 0;
 		/* let timer expire on it's own to avoid deadlock! */
-		nodesub_unsubscribe(&p_ptr->subscription);
+		tipc_nodesub_unsubscribe(&p_ptr->subscription);
 		res = TIPC_OK;
 	}
-	port_unlock(p_ptr);
+	tipc_port_unlock(p_ptr);
 	return res;
 }
 
@@ -1275,7 +1275,7 @@
 	struct port *p_ptr;
 	struct sk_buff *buf = 0;
 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 
@@ -1293,8 +1293,8 @@
 					   port_out_seqno(p_ptr),
 					   0);
 	}
-	port_unlock(p_ptr);
-	net_route_msg(buf);
+	tipc_port_unlock(p_ptr);
+	tipc_net_route_msg(buf);
 	return tipc_disconnect(ref);
 }
 
@@ -1302,11 +1302,11 @@
 {
 	struct port *p_ptr;
 	
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	*isconnected = p_ptr->publ.connected;
-	port_unlock(p_ptr);
+	tipc_port_unlock(p_ptr);
 	return TIPC_OK;
 }
 
@@ -1315,7 +1315,7 @@
 	struct port *p_ptr;
 	int res;
 	 
-	p_ptr = port_lock(ref);
+	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	if (p_ptr->publ.connected) {
@@ -1324,23 +1324,23 @@
 		res = TIPC_OK;
 	} else
 		res = -ENOTCONN;
-	port_unlock(p_ptr);
+	tipc_port_unlock(p_ptr);
 	return res;
 }
 
 int tipc_ref_valid(u32 ref)
 {
 	/* Works irrespective of type */
-	return !!ref_deref(ref);
+	return !!tipc_ref_deref(ref);
 }
 
 
 /*
- *  port_recv_sections(): Concatenate and deliver sectioned
+ *  tipc_port_recv_sections(): Concatenate and deliver sectioned
  *                        message for this node.
  */
 
-int port_recv_sections(struct port *sender, unsigned int num_sect,
+int tipc_port_recv_sections(struct port *sender, unsigned int num_sect,
 		       struct iovec const *msg_sect)
 {
 	struct sk_buff *buf;
@@ -1349,7 +1349,7 @@
 	res = msg_build(&sender->publ.phdr, msg_sect, num_sect,
 			MAX_MSG_SIZE, !sender->user_port, &buf);
 	if (likely(buf))
-		port_recv_msg(buf);
+		tipc_port_recv_msg(buf);
 	return res;
 }
 
@@ -1363,18 +1363,18 @@
 	u32 destnode;
 	int res;
 
-	p_ptr = port_deref(ref);
+	p_ptr = tipc_port_deref(ref);
 	if (!p_ptr || !p_ptr->publ.connected)
 		return -EINVAL;
 
 	p_ptr->publ.congested = 1;
-	if (!port_congested(p_ptr)) {
+	if (!tipc_port_congested(p_ptr)) {
 		destnode = port_peernode(p_ptr);
 		if (likely(destnode != tipc_own_addr))
-			res = link_send_sections_fast(p_ptr, msg_sect, num_sect,
-						      destnode);
+			res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
+							   destnode);
 		else
-			res = port_recv_sections(p_ptr, num_sect, msg_sect);
+			res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
 
 		if (likely(res != -ELINKCONG)) {
 			port_incr_out_seqno(p_ptr);
@@ -1404,7 +1404,7 @@
 	u32 sz;
 	u32 res;
 	 
-	p_ptr = port_deref(ref);
+	p_ptr = tipc_port_deref(ref);
 	if (!p_ptr || !p_ptr->publ.connected)
 		return -EINVAL;
 
@@ -1419,11 +1419,11 @@
 	memcpy(buf->data, (unchar *)msg, hsz);
 	destnode = msg_destnode(msg);
 	p_ptr->publ.congested = 1;
-	if (!port_congested(p_ptr)) {
+	if (!tipc_port_congested(p_ptr)) {
 		if (likely(destnode != tipc_own_addr))
 			res = tipc_send_buf_fast(buf, destnode);
 		else {
-			port_recv_msg(buf);
+			tipc_port_recv_msg(buf);
 			res = sz;
 		}
 		if (likely(res != -ELINKCONG)) {
@@ -1458,7 +1458,7 @@
 	u32 destport = 0;
 	int res;
 
-	p_ptr = port_deref(ref);
+	p_ptr = tipc_port_deref(ref);
 	if (!p_ptr || p_ptr->publ.connected)
 		return -EINVAL;
 
@@ -1472,16 +1472,16 @@
 	msg_set_lookup_scope(msg, addr_scope(domain));
 	if (importance <= TIPC_CRITICAL_IMPORTANCE)
 		msg_set_importance(msg,importance);
-	destport = nametbl_translate(name->type, name->instance, &destnode);
+	destport = tipc_nametbl_translate(name->type, name->instance, &destnode);
 	msg_set_destnode(msg, destnode);
 	msg_set_destport(msg, destport);
 
 	if (likely(destport || destnode)) {
 		p_ptr->sent++;
 		if (likely(destnode == tipc_own_addr))
-			return port_recv_sections(p_ptr, num_sect, msg_sect);
-		res = link_send_sections_fast(p_ptr, msg_sect, num_sect, 
-					      destnode);
+			return tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
+		res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, 
+						   destnode);
 		if (likely(res != -ELINKCONG))
 			return res;
 		if (port_unreliable(p_ptr)) {
@@ -1490,8 +1490,8 @@
 		}
 		return -ELINKCONG;
 	}
-	return port_reject_sections(p_ptr, msg, msg_sect, num_sect, 
-				    TIPC_ERR_NO_NAME);
+	return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, 
+					 TIPC_ERR_NO_NAME);
 }
 
 /**
@@ -1530,7 +1530,7 @@
 	u32 destport = 0;
 	int res;
 
-	p_ptr = (struct port *)ref_deref(ref);
+	p_ptr = (struct port *)tipc_ref_deref(ref);
 	if (!p_ptr || p_ptr->publ.connected)
 		return -EINVAL;
 
@@ -1545,7 +1545,7 @@
 	msg_set_lookup_scope(msg, addr_scope(domain));
 	msg_set_hdr_sz(msg, LONG_H_SIZE);
 	msg_set_size(msg, LONG_H_SIZE + dsz);
-	destport = nametbl_translate(name->type, name->instance, &destnode);
+	destport = tipc_nametbl_translate(name->type, name->instance, &destnode);
 	msg_set_destnode(msg, destnode);
 	msg_set_destport(msg, destport);
 	msg_dbg(msg, "forw2name ==> ");
@@ -1557,7 +1557,7 @@
 	if (likely(destport || destnode)) {
 		p_ptr->sent++;
 		if (destnode == tipc_own_addr)
-			return port_recv_msg(buf);
+			return tipc_port_recv_msg(buf);
 		res = tipc_send_buf_fast(buf, destnode);
 		if (likely(res != -ELINKCONG))
 			return res;
@@ -1601,7 +1601,7 @@
 	struct tipc_msg *msg;
 	int res;
 
-	p_ptr = port_deref(ref);
+	p_ptr = tipc_port_deref(ref);
 	if (!p_ptr || p_ptr->publ.connected)
 		return -EINVAL;
 
@@ -1616,8 +1616,8 @@
 		msg_set_importance(msg, importance);
 	p_ptr->sent++;
 	if (dest->node == tipc_own_addr)
-		return port_recv_sections(p_ptr, num_sect, msg_sect);
-	res = link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node);
+		return tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
+	res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node);
 	if (likely(res != -ELINKCONG))
 		return res;
 	if (port_unreliable(p_ptr)) {
@@ -1658,7 +1658,7 @@
 	struct tipc_msg *msg;
 	int res;
 
-	p_ptr = (struct port *)ref_deref(ref);
+	p_ptr = (struct port *)tipc_ref_deref(ref);
 	if (!p_ptr || p_ptr->publ.connected)
 		return -EINVAL;
 
@@ -1680,7 +1680,7 @@
 	msg_dbg(msg, "buf2port: ");
 	p_ptr->sent++;
 	if (dest->node == tipc_own_addr)
-		return port_recv_msg(buf);
+		return tipc_port_recv_msg(buf);
 	res = tipc_send_buf_fast(buf, dest->node);
 	if (likely(res != -ELINKCONG))
 		return res;
diff --git a/net/tipc/port.h b/net/tipc/port.h
index e829a99..839f100 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -37,7 +37,7 @@
 #ifndef _TIPC_PORT_H
 #define _TIPC_PORT_H
 
-#include <net/tipc/tipc_port.h>
+#include "core.h"
 #include "ref.h"
 #include "net.h"
 #include "msg.h"
@@ -110,65 +110,65 @@
 	struct node_subscr subscription;
 };
 
-extern spinlock_t port_list_lock;
+extern spinlock_t tipc_port_list_lock;
 struct port_list;
 
-int port_recv_sections(struct port *p_ptr, u32 num_sect, 
-		       struct iovec const *msg_sect);
-int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
-			 struct iovec const *msg_sect, u32 num_sect,
-			 int err);
-struct sk_buff *port_get_ports(void);
+int tipc_port_recv_sections(struct port *p_ptr, u32 num_sect, 
+			    struct iovec const *msg_sect);
+int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
+			      struct iovec const *msg_sect, u32 num_sect,
+			      int err);
+struct sk_buff *tipc_port_get_ports(void);
 struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space);
-void port_recv_proto_msg(struct sk_buff *buf);
-void port_recv_mcast(struct sk_buff *buf, struct port_list *dp);
-void port_reinit(void);
+void tipc_port_recv_proto_msg(struct sk_buff *buf);
+void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp);
+void tipc_port_reinit(void);
 
 /**
- * port_lock - lock port instance referred to and return its pointer
+ * tipc_port_lock - lock port instance referred to and return its pointer
  */
 
-static inline struct port *port_lock(u32 ref)
+static inline struct port *tipc_port_lock(u32 ref)
 {
-	return (struct port *)ref_lock(ref);
+	return (struct port *)tipc_ref_lock(ref);
 }
 
 /** 
- * port_unlock - unlock a port instance
+ * tipc_port_unlock - unlock a port instance
  * 
- * Can use pointer instead of ref_unlock() since port is already locked.
+ * Can use pointer instead of tipc_ref_unlock() since port is already locked.
  */
 
-static inline void port_unlock(struct port *p_ptr)
+static inline void tipc_port_unlock(struct port *p_ptr)
 {
 	spin_unlock_bh(p_ptr->publ.lock);
 }
 
-static inline struct port* port_deref(u32 ref)
+static inline struct port* tipc_port_deref(u32 ref)
 {
-	return (struct port *)ref_deref(ref);
+	return (struct port *)tipc_ref_deref(ref);
 }
 
-static inline u32 peer_port(struct port *p_ptr)
+static inline u32 tipc_peer_port(struct port *p_ptr)
 {
 	return msg_destport(&p_ptr->publ.phdr);
 }
 
-static inline u32 peer_node(struct port *p_ptr)
+static inline u32 tipc_peer_node(struct port *p_ptr)
 {
 	return msg_destnode(&p_ptr->publ.phdr);
 }
 
-static inline int port_congested(struct port *p_ptr)
+static inline int tipc_port_congested(struct port *p_ptr)
 {
 	return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2));
 }
 
 /** 
- * port_recv_msg - receive message from lower layer and deliver to port user
+ * tipc_port_recv_msg - receive message from lower layer and deliver to port user
  */
 
-static inline int port_recv_msg(struct sk_buff *buf)
+static inline int tipc_port_recv_msg(struct sk_buff *buf)
 {
 	struct port *p_ptr;
 	struct tipc_msg *msg = buf_msg(buf);
@@ -178,24 +178,24 @@
 	
 	/* forward unresolved named message */
 	if (unlikely(!destport)) {
-		net_route_msg(buf);
+		tipc_net_route_msg(buf);
 		return dsz;
 	}
 
 	/* validate destination & pass to port, otherwise reject message */
-	p_ptr = port_lock(destport);
+	p_ptr = tipc_port_lock(destport);
 	if (likely(p_ptr)) {
 		if (likely(p_ptr->publ.connected)) {
-			if ((unlikely(msg_origport(msg) != peer_port(p_ptr))) ||
-			    (unlikely(msg_orignode(msg) != peer_node(p_ptr))) ||
+			if ((unlikely(msg_origport(msg) != tipc_peer_port(p_ptr))) ||
+			    (unlikely(msg_orignode(msg) != tipc_peer_node(p_ptr))) ||
 			    (unlikely(!msg_connected(msg)))) {
 				err = TIPC_ERR_NO_PORT;
-				port_unlock(p_ptr);
+				tipc_port_unlock(p_ptr);
 				goto reject;
 			}
 		}
 		err = p_ptr->dispatcher(&p_ptr->publ, buf);
-		port_unlock(p_ptr);
+		tipc_port_unlock(p_ptr);
 		if (likely(!err))
 			return dsz;
 	} else {
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
index 944093f..5a13c2d 100644
--- a/net/tipc/ref.c
+++ b/net/tipc/ref.c
@@ -61,15 +61,15 @@
  * because entry 0's reference field has the form XXXX|1--1.
  */
 
-struct ref_table ref_table = { 0 };
+struct ref_table tipc_ref_table = { 0 };
 
-rwlock_t reftbl_lock = RW_LOCK_UNLOCKED;
+static rwlock_t ref_table_lock = RW_LOCK_UNLOCKED;
 
 /**
- * ref_table_init - create reference table for objects
+ * tipc_ref_table_init - create reference table for objects
  */
 
-int ref_table_init(u32 requested_size, u32 start)
+int tipc_ref_table_init(u32 requested_size, u32 start)
 {
 	struct reference *table;
 	u32 sz = 1 << 4;
@@ -83,43 +83,43 @@
 	if (table == NULL)
 		return -ENOMEM;
 
-	write_lock_bh(&reftbl_lock);
+	write_lock_bh(&ref_table_lock);
 	index_mask = sz - 1;
 	for (i = sz - 1; i >= 0; i--) {
 		table[i].object = 0;
 		table[i].lock = SPIN_LOCK_UNLOCKED;
 		table[i].data.next_plus_upper = (start & ~index_mask) + i - 1;
 	}
-	ref_table.entries = table;
-	ref_table.index_mask = index_mask;
-	ref_table.first_free = sz - 1;
-	ref_table.last_free = 1;
-	write_unlock_bh(&reftbl_lock);
+	tipc_ref_table.entries = table;
+	tipc_ref_table.index_mask = index_mask;
+	tipc_ref_table.first_free = sz - 1;
+	tipc_ref_table.last_free = 1;
+	write_unlock_bh(&ref_table_lock);
 	return TIPC_OK;
 }
 
 /**
- * ref_table_stop - destroy reference table for objects
+ * tipc_ref_table_stop - destroy reference table for objects
  */
 
-void ref_table_stop(void)
+void tipc_ref_table_stop(void)
 {
-	if (!ref_table.entries)
+	if (!tipc_ref_table.entries)
 		return;
 
-	vfree(ref_table.entries);
-	ref_table.entries = 0;
+	vfree(tipc_ref_table.entries);
+	tipc_ref_table.entries = 0;
 }
 
 /**
- * ref_acquire - create reference to an object
+ * tipc_ref_acquire - create reference to an object
  * 
  * Return a unique reference value which can be translated back to the pointer
  * 'object' at a later time.  Also, pass back a pointer to the lock protecting 
  * the object, but without locking it.
  */
 
-u32 ref_acquire(void *object, spinlock_t **lock)
+u32 tipc_ref_acquire(void *object, spinlock_t **lock)
 {
 	struct reference *entry;
 	u32 index;
@@ -127,17 +127,17 @@
 	u32 next_plus_upper;
 	u32 reference = 0;
 
-	assert(ref_table.entries && object);
+	assert(tipc_ref_table.entries && object);
 
-	write_lock_bh(&reftbl_lock);
-	if (ref_table.first_free) {
-		index = ref_table.first_free;
-		entry = &(ref_table.entries[index]);
-		index_mask = ref_table.index_mask;
+	write_lock_bh(&ref_table_lock);
+	if (tipc_ref_table.first_free) {
+		index = tipc_ref_table.first_free;
+		entry = &(tipc_ref_table.entries[index]);
+		index_mask = tipc_ref_table.index_mask;
 		/* take lock in case a previous user of entry still holds it */ 
 		spin_lock_bh(&entry->lock);  
 		next_plus_upper = entry->data.next_plus_upper;
-		ref_table.first_free = next_plus_upper & index_mask;
+		tipc_ref_table.first_free = next_plus_upper & index_mask;
 		reference = (next_plus_upper & ~index_mask) + index;
 		entry->data.reference = reference;
 		entry->object = object;
@@ -145,45 +145,45 @@
                         *lock = &entry->lock;
 		spin_unlock_bh(&entry->lock);
 	}
-	write_unlock_bh(&reftbl_lock);
+	write_unlock_bh(&ref_table_lock);
 	return reference;
 }
 
 /**
- * ref_discard - invalidate references to an object
+ * tipc_ref_discard - invalidate references to an object
  * 
  * Disallow future references to an object and free up the entry for re-use.
  * Note: The entry's spin_lock may still be busy after discard
  */
 
-void ref_discard(u32 ref)
+void tipc_ref_discard(u32 ref)
 {
 	struct reference *entry;
 	u32 index; 
 	u32 index_mask;
 
-	assert(ref_table.entries);
+	assert(tipc_ref_table.entries);
 	assert(ref != 0);
 
-	write_lock_bh(&reftbl_lock);
-	index_mask = ref_table.index_mask;
+	write_lock_bh(&ref_table_lock);
+	index_mask = tipc_ref_table.index_mask;
 	index = ref & index_mask;
-	entry = &(ref_table.entries[index]);
+	entry = &(tipc_ref_table.entries[index]);
 	assert(entry->object != 0);
 	assert(entry->data.reference == ref);
 
 	/* mark entry as unused */
 	entry->object = 0;
-	if (ref_table.first_free == 0)
-		ref_table.first_free = index;
+	if (tipc_ref_table.first_free == 0)
+		tipc_ref_table.first_free = index;
 	else
 		/* next_plus_upper is always XXXX|0--0 for last free entry */
-		ref_table.entries[ref_table.last_free].data.next_plus_upper 
+		tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper 
 			|= index;
-	ref_table.last_free = index;
+	tipc_ref_table.last_free = index;
 
 	/* increment upper bits of entry to invalidate subsequent references */
 	entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
-	write_unlock_bh(&reftbl_lock);
+	write_unlock_bh(&ref_table_lock);
 }
 
diff --git a/net/tipc/ref.h b/net/tipc/ref.h
index 429cde5..4f8f9f4 100644
--- a/net/tipc/ref.h
+++ b/net/tipc/ref.h
@@ -54,7 +54,7 @@
 };
 
 /**
- * struct ref_table - table of TIPC object reference entries
+ * struct tipc_ref_table - table of TIPC object reference entries
  * @entries: pointer to array of reference entries
  * @index_mask: bitmask for array index portion of reference values
  * @first_free: array index of first unused object reference entry
@@ -68,24 +68,24 @@
 	u32 last_free;
 };
 
-extern struct ref_table ref_table;
+extern struct ref_table tipc_ref_table;
 
-int ref_table_init(u32 requested_size, u32 start);
-void ref_table_stop(void);
+int tipc_ref_table_init(u32 requested_size, u32 start);
+void tipc_ref_table_stop(void);
 
-u32 ref_acquire(void *object, spinlock_t **lock);
-void ref_discard(u32 ref);
+u32 tipc_ref_acquire(void *object, spinlock_t **lock);
+void tipc_ref_discard(u32 ref);
 
 
 /**
- * ref_lock - lock referenced object and return pointer to it
+ * tipc_ref_lock - lock referenced object and return pointer to it
  */
 
-static inline void *ref_lock(u32 ref)
+static inline void *tipc_ref_lock(u32 ref)
 {
-	if (likely(ref_table.entries)) {
+	if (likely(tipc_ref_table.entries)) {
 		struct reference *r =
-			&ref_table.entries[ref & ref_table.index_mask];
+			&tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
 
 		spin_lock_bh(&r->lock);
 		if (likely(r->data.reference == ref))
@@ -96,31 +96,31 @@
 }
 
 /**
- * ref_unlock - unlock referenced object 
+ * tipc_ref_unlock - unlock referenced object 
  */
 
-static inline void ref_unlock(u32 ref)
+static inline void tipc_ref_unlock(u32 ref)
 {
-	if (likely(ref_table.entries)) {
+	if (likely(tipc_ref_table.entries)) {
 		struct reference *r =
-			&ref_table.entries[ref & ref_table.index_mask];
+			&tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
 
 		if (likely(r->data.reference == ref))
 			spin_unlock_bh(&r->lock);
 		else
-			err("ref_unlock() invoked using obsolete reference\n");
+			err("tipc_ref_unlock() invoked using obsolete reference\n");
 	}
 }
 
 /**
- * ref_deref - return pointer referenced object (without locking it)
+ * tipc_ref_deref - return pointer referenced object (without locking it)
  */
 
-static inline void *ref_deref(u32 ref)
+static inline void *tipc_ref_deref(u32 ref)
 {
-	if (likely(ref_table.entries)) {
+	if (likely(tipc_ref_table.entries)) {
 		struct reference *r = 
-			&ref_table.entries[ref & ref_table.index_mask];
+			&tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
 
 		if (likely(r->data.reference == ref))
 			return r->object;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index d21f8c0..67253bf 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -42,9 +42,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
-#include <linux/version.h>
 #include <linux/fcntl.h>
-#include <linux/version.h>
 #include <asm/semaphore.h>
 #include <asm/string.h>
 #include <asm/atomic.h>
@@ -1185,7 +1183,7 @@
 	if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
 		sock->state = SS_DISCONNECTING;
 		/* Note: Use signal since port lock is already taken! */
-		k_signal((Handler)async_disconnect, tport->ref);
+		tipc_k_signal((Handler)async_disconnect, tport->ref);
 	}
 
 	/* Enqueue message (finally!) */
@@ -1685,11 +1683,11 @@
 };
 
 /**
- * socket_init - initialize TIPC socket interface
+ * tipc_socket_init - initialize TIPC socket interface
  * 
  * Returns 0 on success, errno otherwise
  */
-int socket_init(void)
+int tipc_socket_init(void)
 {
 	int res;
 
@@ -1712,9 +1710,9 @@
 }
 
 /**
- * sock_stop - stop TIPC socket interface
+ * tipc_socket_stop - stop TIPC socket interface
  */
-void socket_stop(void)
+void tipc_socket_stop(void)
 {
 	if (!sockets_enabled)
 		return;
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 80e219b..5ff38b9 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -118,14 +118,14 @@
 }
 
 /**
- * subscr_overlap - test for subscription overlap with the given values
+ * tipc_subscr_overlap - test for subscription overlap with the given values
  *
  * Returns 1 if there is overlap, otherwise 0.
  */
 
-int subscr_overlap(struct subscription *sub, 
-		   u32 found_lower, 
-		   u32 found_upper)
+int tipc_subscr_overlap(struct subscription *sub, 
+			u32 found_lower, 
+			u32 found_upper)
 
 {
 	if (found_lower < sub->seq.lower)
@@ -138,22 +138,22 @@
 }
 
 /**
- * subscr_report_overlap - issue event if there is subscription overlap
+ * tipc_subscr_report_overlap - issue event if there is subscription overlap
  * 
  * Protected by nameseq.lock in name_table.c
  */
 
-void subscr_report_overlap(struct subscription *sub, 
-			   u32 found_lower, 
-			   u32 found_upper,
-			   u32 event, 
-			   u32 port_ref, 
-			   u32 node,
-			   int must)
+void tipc_subscr_report_overlap(struct subscription *sub, 
+				u32 found_lower, 
+				u32 found_upper,
+				u32 event, 
+				u32 port_ref, 
+				u32 node,
+				int must)
 {
 	dbg("Rep overlap %u:%u,%u<->%u,%u\n", sub->seq.type, sub->seq.lower,
 	    sub->seq.upper, found_lower, found_upper);
-	if (!subscr_overlap(sub, found_lower, found_upper))
+	if (!tipc_subscr_overlap(sub, found_lower, found_upper))
 		return;
 	if (!must && (sub->filter != TIPC_SUB_PORTS))
 		return;
@@ -172,13 +172,13 @@
 	/* Validate subscriber reference (in case subscriber is terminating) */
 
 	subscriber_ref = sub->owner->ref;
-	subscriber = (struct subscriber *)ref_lock(subscriber_ref);
+	subscriber = (struct subscriber *)tipc_ref_lock(subscriber_ref);
 	if (subscriber == NULL)
 		return;
 
 	/* Unlink subscription from name table */
 
-	nametbl_unsubscribe(sub);
+	tipc_nametbl_unsubscribe(sub);
 
 	/* Notify subscriber of timeout, then unlink subscription */
 
@@ -192,7 +192,7 @@
 
 	/* Now destroy subscription */
 
-	ref_unlock(subscriber_ref);
+	tipc_ref_unlock(subscriber_ref);
 	k_term_timer(&sub->timer);
 	kfree(sub);
 	atomic_dec(&topsrv.subscription_count);
@@ -216,7 +216,7 @@
 
 	/* Invalidate subscriber reference */
 
-	ref_discard(subscriber->ref);
+	tipc_ref_discard(subscriber->ref);
 	spin_unlock_bh(subscriber->lock);
 
 	/* Destroy any existing subscriptions for subscriber */
@@ -227,7 +227,7 @@
 			k_cancel_timer(&sub->timer);
 			k_term_timer(&sub->timer);
 		}
-		nametbl_unsubscribe(sub);
+		tipc_nametbl_unsubscribe(sub);
 		list_del(&sub->subscription_list);
 		dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n",
 		    sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
@@ -315,7 +315,7 @@
 		k_start_timer(&sub->timer, sub->timeout);
 	}
 	sub->owner = subscriber;
-	nametbl_subscribe(sub);
+	tipc_nametbl_subscribe(sub);
 }
 
 /**
@@ -332,7 +332,7 @@
 	struct subscriber *subscriber;
 	spinlock_t *subscriber_lock;
 
-	subscriber = ref_lock((u32)(unsigned long)usr_handle);
+	subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle);
 	if (subscriber == NULL)
 		return;
 
@@ -354,7 +354,7 @@
 	struct subscriber *subscriber;
 	spinlock_t *subscriber_lock;
 
-	subscriber = ref_lock((u32)(unsigned long)usr_handle);
+	subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle);
 	if (subscriber == NULL)
 		return;
 
@@ -401,7 +401,7 @@
 	memset(subscriber, 0, sizeof(struct subscriber));
 	INIT_LIST_HEAD(&subscriber->subscription_list);
 	INIT_LIST_HEAD(&subscriber->subscriber_list);
-	subscriber->ref = ref_acquire(subscriber, &subscriber->lock);
+	subscriber->ref = tipc_ref_acquire(subscriber, &subscriber->lock);
 	if (subscriber->ref == 0) {
 		warn("Failed to acquire subscriber reference\n");
 		kfree(subscriber);
@@ -423,7 +423,7 @@
 			&subscriber->port_ref);
 	if (subscriber->port_ref == 0) {
 		warn("Memory squeeze; failed to create subscription port\n");
-		ref_discard(subscriber->ref);
+		tipc_ref_discard(subscriber->ref);
 		kfree(subscriber);
 		return;
 	}
@@ -432,7 +432,7 @@
 
 	/* Add subscriber to topology server's subscriber list */
 
-	ref_lock(subscriber->ref);
+	tipc_ref_lock(subscriber->ref);
 	spin_lock_bh(&topsrv.lock);
 	list_add(&subscriber->subscriber_list, &topsrv.subscriber_list);
 	spin_unlock_bh(&topsrv.lock);
@@ -451,7 +451,7 @@
 	spin_unlock_bh(subscriber_lock);
 }
 
-int subscr_start(void)
+int tipc_subscr_start(void)
 {
 	struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV};
 	int res = -1;
@@ -481,7 +481,7 @@
  	if (res)
 		goto failed;
 
- 	res = nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq);
+ 	res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq);
  	if (res)
 		goto failed;
 
@@ -496,7 +496,7 @@
 	return res;
 }
 
-void subscr_stop(void)
+void tipc_subscr_stop(void)
 {
 	struct subscriber *subscriber;
 	struct subscriber *subscriber_temp;
@@ -507,7 +507,7 @@
 		list_for_each_entry_safe(subscriber, subscriber_temp, 
 					 &topsrv.subscriber_list,
 					 subscriber_list) {
-			ref_lock(subscriber->ref);
+			tipc_ref_lock(subscriber->ref);
 			subscriber_lock = subscriber->lock;
 			subscr_terminate(subscriber);
 			spin_unlock_bh(subscriber_lock);
@@ -522,6 +522,6 @@
 {
 	u32 domain = 0;
 
-	return(nametbl_translate(name->type, name->instance,&domain) != 0);
+	return(tipc_nametbl_translate(name->type, name->instance,&domain) != 0);
 }
 
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
index ccff4ef..1e50904 100644
--- a/net/tipc/subscr.h
+++ b/net/tipc/subscr.h
@@ -60,21 +60,21 @@
 	struct subscriber *owner;
 };
 
-int subscr_overlap(struct subscription * sub, 
-		   u32 found_lower, 
-		   u32 found_upper);
+int tipc_subscr_overlap(struct subscription * sub, 
+			u32 found_lower, 
+			u32 found_upper);
 
-void subscr_report_overlap(struct subscription * sub, 
-			   u32 found_lower, 
-			   u32 found_upper,
-			   u32 event, 
-			   u32 port_ref, 
-			   u32 node,
-			   int must_report);
+void tipc_subscr_report_overlap(struct subscription * sub, 
+				u32 found_lower, 
+				u32 found_upper,
+				u32 event, 
+				u32 port_ref, 
+				u32 node,
+				int must_report);
 
-int subscr_start(void);
+int tipc_subscr_start(void);
 
-void subscr_stop(void);
+void tipc_subscr_stop(void);
 
 
 #endif
diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c
index 35ec7dc..106200d 100644
--- a/net/tipc/user_reg.c
+++ b/net/tipc/user_reg.c
@@ -114,10 +114,10 @@
 }
 
 /**
- * reg_start - activate TIPC user registry
+ * tipc_reg_start - activate TIPC user registry
  */
 
-int reg_start(void)
+int tipc_reg_start(void)
 {
 	u32 u;
 	int res;
@@ -127,17 +127,17 @@
 
 	for (u = 1; u <= MAX_USERID; u++) {
 		if (users[u].callback)
-			k_signal((Handler)reg_callback,
-				 (unsigned long)&users[u]);
+			tipc_k_signal((Handler)reg_callback,
+				      (unsigned long)&users[u]);
 	}
 	return TIPC_OK;
 }
 
 /**
- * reg_stop - shut down & delete TIPC user registry
+ * tipc_reg_stop - shut down & delete TIPC user registry
  */
 
-void reg_stop(void)
+void tipc_reg_stop(void)
 {               
 	int id;
 
@@ -184,7 +184,7 @@
 	atomic_inc(&tipc_user_count);
 	
 	if (cb && (tipc_mode != TIPC_NOT_RUNNING))
-		k_signal((Handler)reg_callback, (unsigned long)user_ptr);
+		tipc_k_signal((Handler)reg_callback, (unsigned long)user_ptr);
 	return TIPC_OK;
 }
 
@@ -223,10 +223,10 @@
 }
 
 /**
- * reg_add_port - register a user's driver port
+ * tipc_reg_add_port - register a user's driver port
  */
 
-int reg_add_port(struct user_port *up_ptr)
+int tipc_reg_add_port(struct user_port *up_ptr)
 {
 	struct tipc_user *user_ptr;
 
@@ -245,10 +245,10 @@
 }
 
 /**
- * reg_remove_port - deregister a user's driver port
+ * tipc_reg_remove_port - deregister a user's driver port
  */
 
-int reg_remove_port(struct user_port *up_ptr)
+int tipc_reg_remove_port(struct user_port *up_ptr)
 {
 	if (up_ptr->user_ref == 0)
 		return TIPC_OK;
diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h
index 122ca9b..d0e8879 100644
--- a/net/tipc/user_reg.h
+++ b/net/tipc/user_reg.h
@@ -39,10 +39,10 @@
 
 #include "port.h"
 
-int reg_start(void);
-void reg_stop(void);
+int tipc_reg_start(void);
+void tipc_reg_stop(void);
 
-int reg_add_port(struct user_port *up_ptr);
-int reg_remove_port(struct user_port *up_ptr);
+int tipc_reg_add_port(struct user_port *up_ptr);
+int tipc_reg_remove_port(struct user_port *up_ptr);
 
 #endif
diff --git a/net/tipc/zone.c b/net/tipc/zone.c
index 4eaef66..7c11f7f 100644
--- a/net/tipc/zone.c
+++ b/net/tipc/zone.c
@@ -42,12 +42,12 @@
 #include "cluster.h"
 #include "node.h"
 
-struct _zone *zone_create(u32 addr)
+struct _zone *tipc_zone_create(u32 addr)
 {
 	struct _zone *z_ptr = 0;
 	u32 z_num;
 
-	if (!addr_domain_valid(addr))
+	if (!tipc_addr_domain_valid(addr))
 		return 0;
 
 	z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC);
@@ -55,24 +55,24 @@
 		memset(z_ptr, 0, sizeof(*z_ptr));
 		z_num = tipc_zone(addr);
 		z_ptr->addr = tipc_addr(z_num, 0, 0);
-		net.zones[z_num] = z_ptr;
+		tipc_net.zones[z_num] = z_ptr;
 	}
 	return z_ptr;
 }
 
-void zone_delete(struct _zone *z_ptr)
+void tipc_zone_delete(struct _zone *z_ptr)
 {
 	u32 c_num;
 
 	if (!z_ptr)
 		return;
 	for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
-		cluster_delete(z_ptr->clusters[c_num]);
+		tipc_cltr_delete(z_ptr->clusters[c_num]);
 	}
 	kfree(z_ptr);
 }
 
-void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr)
+void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr)
 {
 	u32 c_num = tipc_cluster(c_ptr->addr);
 
@@ -82,19 +82,19 @@
 	z_ptr->clusters[c_num] = c_ptr;
 }
 
-void zone_remove_as_router(struct _zone *z_ptr, u32 router)
+void tipc_zone_remove_as_router(struct _zone *z_ptr, u32 router)
 {
 	u32 c_num;
 
 	for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
 		if (z_ptr->clusters[c_num]) {
-			cluster_remove_as_router(z_ptr->clusters[c_num], 
-						 router);
+			tipc_cltr_remove_as_router(z_ptr->clusters[c_num], 
+						   router);
 		}
 	}
 }
 
-void zone_send_external_routes(struct _zone *z_ptr, u32 dest)
+void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest)
 {
 	u32 c_num;
 
@@ -102,12 +102,12 @@
 		if (z_ptr->clusters[c_num]) {
 			if (in_own_cluster(z_ptr->addr))
 				continue;
-			cluster_send_ext_routes(z_ptr->clusters[c_num], dest);
+			tipc_cltr_send_ext_routes(z_ptr->clusters[c_num], dest);
 		}
 	}
 }
 
-struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref)
+struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref)
 {
 	struct cluster *c_ptr;
 	struct node *n_ptr;
@@ -118,7 +118,7 @@
 	c_ptr = z_ptr->clusters[tipc_cluster(addr)];
 	if (!c_ptr)
 		return 0;
-	n_ptr = cluster_select_node(c_ptr, ref);
+	n_ptr = tipc_cltr_select_node(c_ptr, ref);
 	if (n_ptr)
 		return n_ptr;
 
@@ -127,14 +127,14 @@
 		c_ptr = z_ptr->clusters[c_num];
 		if (!c_ptr)
 			return 0;
-		n_ptr = cluster_select_node(c_ptr, ref);
+		n_ptr = tipc_cltr_select_node(c_ptr, ref);
 		if (n_ptr)
 			return n_ptr;
 	}
 	return 0;
 }
 
-u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref)
+u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref)
 {
 	struct cluster *c_ptr;
 	u32 c_num;
@@ -143,14 +143,14 @@
 	if (!z_ptr)
 		return 0;
 	c_ptr = z_ptr->clusters[tipc_cluster(addr)];
-	router = c_ptr ? cluster_select_router(c_ptr, ref) : 0;
+	router = c_ptr ? tipc_cltr_select_router(c_ptr, ref) : 0;
 	if (router)
 		return router;
 
 	/* Links to any other clusters within the zone? */
 	for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
 		c_ptr = z_ptr->clusters[c_num];
-		router = c_ptr ? cluster_select_router(c_ptr, ref) : 0;
+		router = c_ptr ? tipc_cltr_select_router(c_ptr, ref) : 0;
 		if (router)
 			return router;
 	}
@@ -158,12 +158,12 @@
 }
 
 
-u32 zone_next_node(u32 addr)
+u32 tipc_zone_next_node(u32 addr)
 {
-	struct cluster *c_ptr = cluster_find(addr);
+	struct cluster *c_ptr = tipc_cltr_find(addr);
 
 	if (c_ptr)
-		return cluster_next_node(c_ptr, addr);
+		return tipc_cltr_next_node(c_ptr, addr);
 	return 0;
 }
 
diff --git a/net/tipc/zone.h b/net/tipc/zone.h
index 4326f78..267999c 100644
--- a/net/tipc/zone.h
+++ b/net/tipc/zone.h
@@ -54,18 +54,18 @@
 	u32 links;
 };
 
-struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref);
-u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref);
-void zone_remove_as_router(struct _zone *z_ptr, u32 router);
-void zone_send_external_routes(struct _zone *z_ptr, u32 dest);
-struct _zone *zone_create(u32 addr);
-void zone_delete(struct _zone *z_ptr);
-void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr);
-u32 zone_next_node(u32 addr);
+struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref);
+u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref);
+void tipc_zone_remove_as_router(struct _zone *z_ptr, u32 router);
+void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest);
+struct _zone *tipc_zone_create(u32 addr);
+void tipc_zone_delete(struct _zone *z_ptr);
+void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr);
+u32 tipc_zone_next_node(u32 addr);
 
-static inline struct _zone *zone_find(u32 addr)
+static inline struct _zone *tipc_zone_find(u32 addr)
 {
-	return net.zones[tipc_zone(addr)];
+	return tipc_net.zones[tipc_zone(addr)];
 }
 
 #endif
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 077bbf9..98ec53b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -13,7 +13,6 @@
  *
  */
 
-#include <asm/bug.h>
 #include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/kmod.h>
@@ -890,7 +889,9 @@
 			xfrm_pol_put(policy);
 			if (dst)
 				dst_free(dst);
-			goto restart;
+
+			err = -EHOSTUNREACH;
+			goto error;
 		}
 		dst->next = policy->bundles;
 		policy->bundles = dst;
diff --git a/scripts/kconfig/lxdialog/Makefile b/scripts/kconfig/lxdialog/Makefile
index fae3e29..bbf4887 100644
--- a/scripts/kconfig/lxdialog/Makefile
+++ b/scripts/kconfig/lxdialog/Makefile
@@ -2,8 +2,11 @@
 #
 
 check-lxdialog  := $(srctree)/$(src)/check-lxdialog.sh
-HOST_EXTRACFLAGS:= $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
-HOST_LOADLIBES  := $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
+
+# Use reursively expanded variables so we do not call gcc unless
+# we really need to do so. (Do not call gcc as part of make mrproper)
+HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
+HOST_LOADLIBES   = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
  
 HOST_EXTRACFLAGS += -DLOCALE 
 
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
index 448e353..120d624 100644
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -4,17 +4,17 @@
 # What library to link
 ldflags()
 {
-	echo "main() {}" | $cc -lncursesw -xc - -o /dev/null 2> /dev/null
+	$cc -print-file-name=libncursesw.so | grep -q /
 	if [ $? -eq 0 ]; then
 		echo '-lncursesw'
 		exit
 	fi
-	echo "main() {}" | $cc -lncurses -xc - -o /dev/null 2> /dev/null
+	$cc -print-file-name=libncurses.so | grep -q /
 	if [ $? -eq 0 ]; then
 		echo '-lncurses'
 		exit
 	fi
-	echo "main() {}" | $cc -lcurses -xc - -o /dev/null 2> /dev/null
+	$cc -print-file-name=libcurses.so | grep -q /
 	if [ $? -eq 0 ]; then
 		echo '-lcurses'
 		exit
@@ -36,10 +36,13 @@
 	fi
 }
 
-compiler=""
+# Temp file, try to clean up after us
+tmp=.lxdialog.tmp
+trap "rm -f $tmp" 0 1 2 3 15
+
 # Check if we can link to ncurses
 check() {
-	echo "main() {}" | $cc -xc - -o /dev/null 2> /dev/null
+	echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null
 	if [ $? != 0 ]; then
 		echo " *** Unable to find the ncurses libraries."          1>&2
 		echo " *** make menuconfig require the ncurses libraries"  1>&2
@@ -59,6 +62,7 @@
 	exit 1
 fi
 
+cc=""
 case "$1" in
 	"-check")
 		shift
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 9fd5f5b..99fe4b7 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -45,7 +45,7 @@
 # Note: This only supports 'c'.
 
 # usage:
-# kerneldoc [ -docbook | -html | -text | -man ]
+# kernel-doc [ -docbook | -html | -text | -man ]
 #           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
 # or
 #           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
@@ -59,7 +59,7 @@
 #  -nofunction funcname
 #	If set, then only generate documentation for the other function(s).  All
 #	other functions are ignored. Cannot be used with -function together
-#	(yes thats a bug - perl hackers can fix it 8))
+#	(yes, that's a bug -- perl hackers can fix it 8))
 #
 #  c files - list of 'c' files to process
 #
@@ -90,28 +90,28 @@
 #  * my_function - does my stuff
 #  * @my_arg: its mine damnit
 #  *
-#  * Does my stuff explained. 
+#  * Does my stuff explained.
 #  */
 #
 #  or, could also use:
 # /**
 #  * my_function - does my stuff
 #  * @my_arg: its mine damnit
-#  * Description: Does my stuff explained. 
+#  * Description: Does my stuff explained.
 #  */
 # etc.
 #
-# Beside functions you can also write documentation for structs, unions, 
-# enums and typedefs. Instead of the function name you must write the name 
-# of the declaration;  the struct/union/enum/typedef must always precede 
-# the name. Nesting of declarations is not supported. 
+# Beside functions you can also write documentation for structs, unions,
+# enums and typedefs. Instead of the function name you must write the name
+# of the declaration;  the struct/union/enum/typedef must always precede
+# the name. Nesting of declarations is not supported.
 # Use the argument mechanism to document members or constants.
 # e.g.
 # /**
 #  * struct my_struct - short description
 #  * @a: first member
 #  * @b: second member
-#  * 
+#  *
 #  * Longer description
 #  */
 # struct my_struct {
@@ -122,12 +122,12 @@
 # };
 #
 # All descriptions can be multiline, except the short function description.
-# 
-# You can also add additional sections. When documenting kernel functions you 
-# should document the "Context:" of the function, e.g. whether the functions 
+#
+# You can also add additional sections. When documenting kernel functions you
+# should document the "Context:" of the function, e.g. whether the functions
 # can be called form interrupts. Unlike other sections you can end it with an
-# empty line. 
-# Example-sections should contain the string EXAMPLE so that they are marked 
+# empty line.
+# Example-sections should contain the string EXAMPLE so that they are marked
 # appropriately in DocBook.
 #
 # Example:
@@ -135,7 +135,7 @@
 #  * user_function - function that can only be called in user context
 #  * @a: some argument
 #  * Context: !in_interrupt()
-#  * 
+#  *
 #  * Some description
 #  * Example:
 #  *    user_function(22);
@@ -223,9 +223,9 @@
 my $blankline = $blankline_man;
 my $modulename = "Kernel API";
 my $function_only = 0;
-my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', 
-		'July', 'August', 'September', 'October', 
-		'November', 'December')[(localtime)[4]] . 
+my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
+		'July', 'August', 'September', 'October',
+		'November', 'December')[(localtime)[4]] .
   " " . ((localtime)[5]+1900);
 
 # Essentially these are globals
@@ -236,7 +236,7 @@
 my ($type,$declaration_name,$return_type);
 my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map);
 
-# Generated docbook code is inserted in a template at a point where 
+# Generated docbook code is inserted in a template at a point where
 # docbook v3.1 requires a non-zero sequence of RefEntry's; see:
 # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
 # We keep track of number of generated entries and generate a dummy
@@ -365,7 +365,7 @@
 #  parameterdescs => %parameter descriptions
 #  sectionlist => @list of sections
 #  sections => %descriont descriptions
-#  
+#
 
 sub output_highlight {
     my $contents = join "\n",@_;
@@ -400,7 +400,7 @@
 	print "<blockquote>\n";
 	output_highlight($args{'sections'}{$section});
 	print "</blockquote>\n";
-    }  
+    }
 }
 
 # output enum in html
@@ -434,7 +434,7 @@
     print "<hr>\n";
 }
 
-# output tyepdef in html
+# output typedef in html
 sub output_typedef_html(%) {
     my %args = %{$_[0]};
     my ($parameter);
@@ -551,7 +551,7 @@
 
 sub output_section_xml(%) {
     my %args = %{$_[0]};
-    my $section;    
+    my $section;
     # print out each section
     $lineprefix="   ";
     foreach $section (@{$args{'sectionlist'}}) {
@@ -778,7 +778,7 @@
     print "</refsynopsisdiv>\n";
 
     print "<refsect1>\n";
-    print " <title>Constants</title>\n";    
+    print " <title>Constants</title>\n";
     print "  <variablelist>\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
       my $parameter_name = $parameter;
@@ -1157,7 +1157,7 @@
     foreach $section (@{$args{'sectionlist'}}) {
 	print "$section:\n\n";
 	output_highlight($args{'sections'}{$section});
-    }  
+    }
     print "\n\n";
 }
 
@@ -1262,8 +1262,8 @@
     my $name = shift;
     my $functype = shift;
     my $func = "output_${functype}_$output_mode";
-    if (($function_only==0) || 
-	( $function_only == 1 && defined($function_table{$name})) || 
+    if (($function_only==0) ||
+	( $function_only == 1 && defined($function_table{$name})) ||
 	( $function_only == 2 && !defined($function_table{$name})))
     {
         &$func(@_);
@@ -1282,7 +1282,7 @@
 }
 
 ##
-# takes a declaration (struct, union, enum, typedef) and 
+# takes a declaration (struct, union, enum, typedef) and
 # invokes the right handler. NOT called for functions.
 sub dump_declaration($$) {
     no strict 'refs';
@@ -1352,7 +1352,7 @@
 	    }
 
 	}
-	
+
 	output_declaration($declaration_name,
 			   'enum',
 			   {'enum' => $declaration_name,
@@ -1409,7 +1409,7 @@
     while ($args =~ /(\([^\),]+),/) {
         $args =~ s/(\([^\),]+),/$1#/g;
     }
-    
+
     foreach my $arg (split($splitter, $args)) {
 	# strip comments
 	$arg =~ s/\/\*.*\*\///;
@@ -1529,7 +1529,7 @@
     # the following functions' documentation still comes out right:
     # - parport_register_device (function pointer parameters)
     # - atomic_set (macro)
-    # - pci_match_device (long return type)
+    # - pci_match_device, __copy_to_user (long return type)
 
     if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
 	$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
@@ -1544,7 +1544,9 @@
 	$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 	$prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 	$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
-	$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
+	$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+	$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+	$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
 	$return_type = $1;
 	$declaration_name = $2;
 	my $args = $3;
@@ -1556,7 +1558,7 @@
 	return;
     }
 
-    output_declaration($declaration_name, 
+    output_declaration($declaration_name,
 		       'function',
 		       {'function' => $declaration_name,
 			'module' => $modulename,
@@ -1615,11 +1617,11 @@
     %sections = ();
     @sectionlist = ();
     $prototype = "";
-    
+
     $state = 0;
 }
 
-sub process_state3_function($$) { 
+sub process_state3_function($$) {
     my $x = shift;
     my $file = shift;
 
@@ -1638,7 +1640,7 @@
     }
 }
 
-sub process_state3_type($$) { 
+sub process_state3_type($$) {
     my $x = shift;
     my $file = shift;
 
@@ -1778,7 +1780,7 @@
 	    } elsif (/$doc_content/) {
 		# miguel-style comment kludge, look for blank lines after
 		# @parameter line to signify start of description
-		if ($1 eq "" && 
+		if ($1 eq "" &&
 			($section =~ m/^@/ || $section eq $section_context)) {
 		    dump_section($section, xml_escape($contents));
 		    $section = $section_default;
@@ -1788,7 +1790,7 @@
 		}
 	    } else {
 		# i dont know - bad line?  ignore.
-		print STDERR "Warning(${file}:$.): bad line: $_"; 
+		print STDERR "Warning(${file}:$.): bad line: $_";
 		++$warnings;
 	    }
 	} elsif ($state == 3) {	# scanning for function { (end of prototype)
@@ -1843,7 +1845,7 @@
 			else
 			{
 				$contents .= $1 . "\n";
-			}	
+			}
         	}
           }
     }
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 90db5c7..0c62798 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -67,9 +67,10 @@
 	description = kmalloc(dlen + 1, GFP_KERNEL);
 	if (!description)
 		goto error;
+	description[dlen] = '\0';
 
 	ret = -EFAULT;
-	if (copy_from_user(description, _description, dlen + 1) != 0)
+	if (copy_from_user(description, _description, dlen) != 0)
 		goto error2;
 
 	/* pull the payload in if one was supplied */
@@ -161,9 +162,10 @@
 	description = kmalloc(dlen + 1, GFP_KERNEL);
 	if (!description)
 		goto error;
+	description[dlen] = '\0';
 
 	ret = -EFAULT;
-	if (copy_from_user(description, _description, dlen + 1) != 0)
+	if (copy_from_user(description, _description, dlen) != 0)
 		goto error2;
 
 	/* pull the callout info into kernel space */
@@ -182,9 +184,10 @@
 		callout_info = kmalloc(dlen + 1, GFP_KERNEL);
 		if (!callout_info)
 			goto error2;
+		callout_info[dlen] = '\0';
 
 		ret = -EFAULT;
-		if (copy_from_user(callout_info, _callout_info, dlen + 1) != 0)
+		if (copy_from_user(callout_info, _callout_info, dlen) != 0)
 			goto error3;
 	}
 
@@ -279,9 +282,10 @@
 		name = kmalloc(nlen + 1, GFP_KERNEL);
 		if (!name)
 			goto error;
+		name[nlen] = '\0';
 
 		ret = -EFAULT;
-		if (copy_from_user(name, _name, nlen + 1) != 0)
+		if (copy_from_user(name, _name, nlen) != 0)
 			goto error2;
 	}
 
@@ -583,9 +587,10 @@
 	description = kmalloc(dlen + 1, GFP_KERNEL);
 	if (!description)
 		goto error;
+	description[dlen] = '\0';
 
 	ret = -EFAULT;
-	if (copy_from_user(description, _description, dlen + 1) != 0)
+	if (copy_from_user(description, _description, dlen) != 0)
 		goto error2;
 
 	/* get the keyring at which to begin the search */
diff --git a/security/seclvl.c b/security/seclvl.c
index 1caac01..8529ea6 100644
--- a/security/seclvl.c
+++ b/security/seclvl.c
@@ -368,8 +368,8 @@
  */
 static int seclvl_settime(struct timespec *tv, struct timezone *tz)
 {
-	struct timespec now;
-	if (seclvl > 1) {
+	if (tv && seclvl > 1) {
+		struct timespec now;
 		now = current_kernel_time();
 		if (tv->tv_sec < now.tv_sec ||
 		    (tv->tv_sec == now.tv_sec && tv->tv_nsec < now.tv_nsec)) {
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index b59582b..f636f53 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -1,6 +1,6 @@
 config SECURITY_SELINUX
 	bool "NSA SELinux Support"
-	depends on SECURITY && NET && INET
+	depends on SECURITY_NETWORK && AUDIT && NET && INET
 	default n
 	help
 	  This selects NSA Security-Enhanced Linux (SELinux).
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index 06d54d9..688c0a2 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -4,9 +4,7 @@
 
 obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
 
-selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o
-
-selinux-$(CONFIG_SECURITY_NETWORK) += netif.o
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o
 
 selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
 
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 53d6c7b..ac5d69b 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -43,13 +43,11 @@
 #undef S_
 };
 
-#ifdef CONFIG_AUDIT
 static const char *class_to_string[] = {
 #define S_(s) s,
 #include "class_to_string.h"
 #undef S_
 };
-#endif
 
 #define TB_(s) static const char * s [] = {
 #define TE_(s) };
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b9f8d97..b7773bf 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -127,7 +127,6 @@
 	if (!tsec)
 		return -ENOMEM;
 
-	tsec->magic = SELINUX_MAGIC;
 	tsec->task = task;
 	tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
 	task->security = tsec;
@@ -138,10 +137,6 @@
 static void task_free_security(struct task_struct *task)
 {
 	struct task_security_struct *tsec = task->security;
-
-	if (!tsec || tsec->magic != SELINUX_MAGIC)
-		return;
-
 	task->security = NULL;
 	kfree(tsec);
 }
@@ -157,14 +152,10 @@
 
 	init_MUTEX(&isec->sem);
 	INIT_LIST_HEAD(&isec->list);
-	isec->magic = SELINUX_MAGIC;
 	isec->inode = inode;
 	isec->sid = SECINITSID_UNLABELED;
 	isec->sclass = SECCLASS_FILE;
-	if (tsec && tsec->magic == SELINUX_MAGIC)
-		isec->task_sid = tsec->sid;
-	else
-		isec->task_sid = SECINITSID_UNLABELED;
+	isec->task_sid = tsec->sid;
 	inode->i_security = isec;
 
 	return 0;
@@ -175,9 +166,6 @@
 	struct inode_security_struct *isec = inode->i_security;
 	struct superblock_security_struct *sbsec = inode->i_sb->s_security;
 
-	if (!isec || isec->magic != SELINUX_MAGIC)
-		return;
-
 	spin_lock(&sbsec->isec_lock);
 	if (!list_empty(&isec->list))
 		list_del_init(&isec->list);
@@ -192,19 +180,13 @@
 	struct task_security_struct *tsec = current->security;
 	struct file_security_struct *fsec;
 
-	fsec = kzalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
+	fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
 	if (!fsec)
 		return -ENOMEM;
 
-	fsec->magic = SELINUX_MAGIC;
 	fsec->file = file;
-	if (tsec && tsec->magic == SELINUX_MAGIC) {
-		fsec->sid = tsec->sid;
-		fsec->fown_sid = tsec->sid;
-	} else {
-		fsec->sid = SECINITSID_UNLABELED;
-		fsec->fown_sid = SECINITSID_UNLABELED;
-	}
+	fsec->sid = tsec->sid;
+	fsec->fown_sid = tsec->sid;
 	file->f_security = fsec;
 
 	return 0;
@@ -213,10 +195,6 @@
 static void file_free_security(struct file *file)
 {
 	struct file_security_struct *fsec = file->f_security;
-
-	if (!fsec || fsec->magic != SELINUX_MAGIC)
-		return;
-
 	file->f_security = NULL;
 	kfree(fsec);
 }
@@ -233,7 +211,6 @@
 	INIT_LIST_HEAD(&sbsec->list);
 	INIT_LIST_HEAD(&sbsec->isec_head);
 	spin_lock_init(&sbsec->isec_lock);
-	sbsec->magic = SELINUX_MAGIC;
 	sbsec->sb = sb;
 	sbsec->sid = SECINITSID_UNLABELED;
 	sbsec->def_sid = SECINITSID_FILE;
@@ -246,9 +223,6 @@
 {
 	struct superblock_security_struct *sbsec = sb->s_security;
 
-	if (!sbsec || sbsec->magic != SELINUX_MAGIC)
-		return;
-
 	spin_lock(&sb_security_lock);
 	if (!list_empty(&sbsec->list))
 		list_del_init(&sbsec->list);
@@ -258,7 +232,6 @@
 	kfree(sbsec);
 }
 
-#ifdef CONFIG_SECURITY_NETWORK
 static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
 {
 	struct sk_security_struct *ssec;
@@ -270,7 +243,6 @@
 	if (!ssec)
 		return -ENOMEM;
 
-	ssec->magic = SELINUX_MAGIC;
 	ssec->sk = sk;
 	ssec->peer_sid = SECINITSID_UNLABELED;
 	sk->sk_security = ssec;
@@ -282,13 +254,12 @@
 {
 	struct sk_security_struct *ssec = sk->sk_security;
 
-	if (sk->sk_family != PF_UNIX || ssec->magic != SELINUX_MAGIC)
+	if (sk->sk_family != PF_UNIX)
 		return;
 
 	sk->sk_security = NULL;
 	kfree(ssec);
 }
-#endif	/* CONFIG_SECURITY_NETWORK */
 
 /* The security server must be initialized before
    any labeling or access decisions can be provided. */
@@ -1483,7 +1454,6 @@
 	if (!bsec)
 		return -ENOMEM;
 
-	bsec->magic = SELINUX_MAGIC;
 	bsec->bprm = bprm;
 	bsec->sid = SECINITSID_UNLABELED;
 	bsec->set = 0;
@@ -2454,35 +2424,27 @@
 		prot = reqprot;
 
 #ifndef CONFIG_PPC32
-	if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXECUTABLE) &&
-	   (vma->vm_start >= vma->vm_mm->start_brk &&
-	    vma->vm_end <= vma->vm_mm->brk)) {
-	    	/*
-		 * We are making an executable mapping in the brk region.
-		 * This has an additional execheap check.
-		 */
-		rc = task_has_perm(current, current, PROCESS__EXECHEAP);
-		if (rc)
-			return rc;
-	}
-	if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) {
-		/*
-		 * We are making executable a file mapping that has
-		 * had some COW done. Since pages might have been written,
-		 * check ability to execute the possibly modified content.
-		 * This typically should only occur for text relocations.
-		 */
-		int rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD);
-		if (rc)
-			return rc;
-	}
-	if (!vma->vm_file && (prot & PROT_EXEC) &&
-		vma->vm_start <= vma->vm_mm->start_stack &&
-		vma->vm_end >= vma->vm_mm->start_stack) {
-		/* Attempt to make the process stack executable.
-		 * This has an additional execstack check.
-		 */
-		rc = task_has_perm(current, current, PROCESS__EXECSTACK);
+	if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
+		rc = 0;
+		if (vma->vm_start >= vma->vm_mm->start_brk &&
+		    vma->vm_end <= vma->vm_mm->brk) {
+			rc = task_has_perm(current, current,
+					   PROCESS__EXECHEAP);
+		} else if (!vma->vm_file &&
+			   vma->vm_start <= vma->vm_mm->start_stack &&
+			   vma->vm_end >= vma->vm_mm->start_stack) {
+			rc = task_has_perm(current, current, PROCESS__EXECSTACK);
+		} else if (vma->vm_file && vma->anon_vma) {
+			/*
+			 * We are making executable a file mapping that has
+			 * had some COW done. Since pages might have been
+			 * written, check ability to execute the possibly
+			 * modified content.  This typically should only
+			 * occur for text relocations.
+			 */
+			rc = file_has_perm(current, vma->vm_file,
+					   FILE__EXECMOD);
+		}
 		if (rc)
 			return rc;
 	}
@@ -2772,8 +2734,6 @@
 	return;
 }
 
-#ifdef CONFIG_SECURITY_NETWORK
-
 /* Returns error only if unable to parse addresses */
 static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad)
 {
@@ -3592,15 +3552,6 @@
 
 #endif	/* CONFIG_NETFILTER */
 
-#else
-
-static inline int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
-{
-	return 0;
-}
-
-#endif	/* CONFIG_SECURITY_NETWORK */
-
 static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
 	struct task_security_struct *tsec;
@@ -3642,14 +3593,9 @@
 	if (!isec)
 		return -ENOMEM;
 
-	isec->magic = SELINUX_MAGIC;
 	isec->sclass = sclass;
 	isec->ipc_perm = perm;
-	if (tsec) {
-		isec->sid = tsec->sid;
-	} else {
-		isec->sid = SECINITSID_UNLABELED;
-	}
+	isec->sid = tsec->sid;
 	perm->security = isec;
 
 	return 0;
@@ -3658,9 +3604,6 @@
 static void ipc_free_security(struct kern_ipc_perm *perm)
 {
 	struct ipc_security_struct *isec = perm->security;
-	if (!isec || isec->magic != SELINUX_MAGIC)
-		return;
-
 	perm->security = NULL;
 	kfree(isec);
 }
@@ -3673,7 +3616,6 @@
 	if (!msec)
 		return -ENOMEM;
 
-	msec->magic = SELINUX_MAGIC;
 	msec->msg = msg;
 	msec->sid = SECINITSID_UNLABELED;
 	msg->security = msec;
@@ -3684,8 +3626,6 @@
 static void msg_msg_free_security(struct msg_msg *msg)
 {
 	struct msg_security_struct *msec = msg->security;
-	if (!msec || msec->magic != SELINUX_MAGIC)
-		return;
 
 	msg->security = NULL;
 	kfree(msec);
@@ -4387,7 +4327,6 @@
 	.getprocattr =                  selinux_getprocattr,
 	.setprocattr =                  selinux_setprocattr,
 
-#ifdef CONFIG_SECURITY_NETWORK
         .unix_stream_connect =		selinux_socket_unix_stream_connect,
 	.unix_may_send =		selinux_socket_unix_may_send,
 
@@ -4409,7 +4348,6 @@
 	.sk_alloc_security =		selinux_sk_alloc_security,
 	.sk_free_security =		selinux_sk_free_security,
 	.sk_getsid = 			selinux_sk_getsid_security,
-#endif
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 	.xfrm_policy_alloc_security =	selinux_xfrm_policy_alloc,
@@ -4487,7 +4425,7 @@
    all processes and objects when they are created. */
 security_initcall(selinux_init);
 
-#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_NETFILTER)
+#if defined(CONFIG_NETFILTER)
 
 static struct nf_hook_ops selinux_ipv4_op = {
 	.hook =		selinux_ipv4_postroute_last,
@@ -4548,13 +4486,13 @@
 }
 #endif
 
-#else /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */
+#else /* CONFIG_NETFILTER */
 
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 #define selinux_nf_ip_exit()
 #endif
 
-#endif /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */
+#endif /* CONFIG_NETFILTER */
 
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 int selinux_disable(void)
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 887937c..54c0307 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -27,7 +27,6 @@
 #include "avc.h"
 
 struct task_security_struct {
-        unsigned long magic;           /* magic number for this module */
 	struct task_struct *task;      /* back pointer to task object */
 	u32 osid;            /* SID prior to last execve */
 	u32 sid;             /* current SID */
@@ -37,7 +36,6 @@
 };
 
 struct inode_security_struct {
-	unsigned long magic;           /* magic number for this module */
         struct inode *inode;           /* back pointer to inode object */
 	struct list_head list;         /* list of inode_security_struct */
 	u32 task_sid;        /* SID of creating task */
@@ -49,14 +47,12 @@
 };
 
 struct file_security_struct {
-	unsigned long magic;            /* magic number for this module */
 	struct file *file;              /* back pointer to file object */
 	u32 sid;              /* SID of open file description */
 	u32 fown_sid;         /* SID of file owner (for SIGIO) */
 };
 
 struct superblock_security_struct {
-	unsigned long magic;            /* magic number for this module */
 	struct super_block *sb;         /* back pointer to sb object */
 	struct list_head list;          /* list of superblock_security_struct */
 	u32 sid;              /* SID of file system */
@@ -70,20 +66,17 @@
 };
 
 struct msg_security_struct {
-        unsigned long magic;		/* magic number for this module */
 	struct msg_msg *msg;		/* back pointer */
 	u32 sid;              /* SID of message */
 };
 
 struct ipc_security_struct {
-        unsigned long magic;		/* magic number for this module */
 	struct kern_ipc_perm *ipc_perm; /* back pointer */
 	u16 sclass;	/* security class of this object */
 	u32 sid;              /* SID of IPC resource */
 };
 
 struct bprm_security_struct {
-	unsigned long magic;           /* magic number for this module */
 	struct linux_binprm *bprm;     /* back pointer to bprm object */
 	u32 sid;                       /* SID for transformed process */
 	unsigned char set;
@@ -102,7 +95,6 @@
 };
 
 struct sk_security_struct {
-	unsigned long magic;		/* magic number for this module */
 	struct sock *sk;		/* back pointer to sk object */
 	u32 peer_sid;			/* SID of peer */
 };
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 54147c1..149feb4 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -882,15 +882,21 @@
 	writel(0x1fff, aaci->base + AACI_INTCLR);
 	writel(aaci->maincr, aaci->base + AACI_MAINCR);
 
-	/*
-	 * Size the FIFOs.
-	 */
-	aaci->fifosize = aaci_size_fifo(aaci);
-
 	ret = aaci_probe_ac97(aaci);
 	if (ret)
 		goto out;
 
+	/*
+	 * Size the FIFOs (must be multiple of 16).
+	 */
+	aaci->fifosize = aaci_size_fifo(aaci);
+	if (aaci->fifosize & 15) {
+		printk(KERN_WARNING "AACI: fifosize = %d not supported\n",
+		       aaci->fifosize);
+		ret = -ENODEV;
+		goto out;
+	}
+
 	ret = aaci_init_pcm(aaci);
 	if (ret)
 		goto out;
diff --git a/sound/core/info.c b/sound/core/info.c
index ae88539..af123e3 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -444,8 +444,8 @@
 	return mask;
 }
 
-static inline int _snd_info_entry_ioctl(struct inode *inode, struct file *file,
-					unsigned int cmd, unsigned long arg)
+static long snd_info_entry_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
 {
 	struct snd_info_private_data *data;
 	struct snd_info_entry *entry;
@@ -465,17 +465,6 @@
 	return -ENOTTY;
 }
 
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_info_entry_ioctl(struct inode *inode, struct file *file,
-				unsigned int cmd, unsigned long arg)
-{
-	int err;
-	unlock_kernel();
-	err = _snd_info_entry_ioctl(inode, file, cmd, arg);
-	lock_kernel();
-	return err;
-}
-
 static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct inode *inode = file->f_dentry->d_inode;
@@ -499,15 +488,15 @@
 
 static struct file_operations snd_info_entry_operations =
 {
-	.owner =	THIS_MODULE,
-	.llseek =	snd_info_entry_llseek,
-	.read =		snd_info_entry_read,
-	.write =	snd_info_entry_write,
-	.poll =		snd_info_entry_poll,
-	.ioctl =	snd_info_entry_ioctl,
-	.mmap =		snd_info_entry_mmap,
-	.open =		snd_info_entry_open,
-	.release =	snd_info_entry_release,
+	.owner =		THIS_MODULE,
+	.llseek =		snd_info_entry_llseek,
+	.read =			snd_info_entry_read,
+	.write =		snd_info_entry_write,
+	.poll =			snd_info_entry_poll,
+	.unlocked_ioctl =	snd_info_entry_ioctl,
+	.mmap =			snd_info_entry_mmap,
+	.open =			snd_info_entry_open,
+	.release =		snd_info_entry_release,
 };
 
 /**
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 29676d8..112ddf7 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -789,7 +789,7 @@
 
 	if ((err = snd_uart16550_detect(uart)) <= 0) {
 		printk(KERN_ERR "no UART detected at 0x%lx\n", iobase);
-		return err;
+		return -ENODEV;
 	}
 
 	if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index bd8e238..fd9bb25 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -109,7 +109,9 @@
 MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
 
 static struct platform_device *platform_devices[SNDRV_CARDS];
+#ifdef CONFIG_PNP
 static int pnp_registered;
+#endif
 
 #define CMI8330_RMUX3D    16
 #define CMI8330_MUTEMUX   17
@@ -672,8 +674,10 @@
 {
 	int i;
 
+#ifdef CONFIG_PNP
 	if (pnp_registered)
 		pnp_unregister_card_driver(&cmi8330_pnpc_driver);
+#endif
 	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
 		platform_device_unregister(platform_devices[i]);
 	platform_driver_unregister(&snd_cmi8330_driver);
@@ -700,11 +704,13 @@
 		cards++;
 	}
 
+#ifdef CONFIG_PNP
 	err = pnp_register_card_driver(&cmi8330_pnpc_driver);
 	if (err >= 0) {
 		pnp_registered = 1;
 		cards += err;
 	}
+#endif
 
 	if (!cards) {
 #ifdef MODULE
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index e168333..4fa4310 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -75,8 +75,10 @@
 
 #ifdef CS4232
 #define IDENT "CS4232"
+#define CS423X_DRIVER "snd_cs4232"
 #else
 #define IDENT "CS4236+"
+#define CS423X_DRIVER "snd_cs4236"
 #endif
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -125,10 +127,12 @@
 MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
 
 static struct platform_device *platform_devices[SNDRV_CARDS];
+#ifdef CONFIG_PNP
 static int pnpc_registered;
 #ifdef CS4232
 static int pnp_registered;
 #endif
+#endif /* CONFIG_PNP */
 
 struct snd_card_cs4236 {
 	struct snd_cs4231 *chip;
@@ -158,7 +162,6 @@
 #endif /* CS4232 */
 
 #ifdef CS4232
-#define CS423X_DRIVER		"snd_cs4232"
 #define CS423X_ISAPNP_DRIVER	"cs4232_isapnp"
 static struct pnp_card_device_id snd_cs423x_pnpids[] = {
 	/* Philips PCA70PS */
@@ -175,11 +178,12 @@
 	{ .id = "CSC7632", .devs = { { "CSC0000" }, { "CSC0010" }, { "PNPb006" } } },
 	/* SIC CrystalWave 32 (CS4232) */
 	{ .id = "CSCf032", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
+	/* Netfinity 3000 on-board soundcard */
+	{ .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC010f" } } },
 	/* --- */
 	{ .id = "" }	/* end */
 };
 #else /* CS4236 */
-#define CS423X_DRIVER		"snd_cs4236"
 #define CS423X_ISAPNP_DRIVER	"cs4236_isapnp"
 static struct pnp_card_device_id snd_cs423x_pnpids[] = {
 	/* Intel Marlin Spike Motherboard - CS4235 */
@@ -747,12 +751,14 @@
 {
 	int i;
 
+#ifdef CONFIG_PNP
 	if (pnpc_registered)
 		pnp_unregister_card_driver(&cs423x_pnpc_driver);
 #ifdef CS4232
 	if (pnp_registered)
 		pnp_unregister_driver(&cs4232_pnp_driver);
 #endif
+#endif /* CONFIG_PNP */
 	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
 		platform_device_unregister(platform_devices[i]);
 	platform_driver_unregister(&cs423x_nonpnp_driver);
@@ -778,6 +784,7 @@
 		platform_devices[i] = device;
 		cards++;
 	}
+#ifdef CONFIG_PNP
 #ifdef CS4232
 	i = pnp_register_driver(&cs4232_pnp_driver);
 	if (i >= 0) {
@@ -790,6 +797,8 @@
 		pnpc_registered = 1;
 		cards += i;
 	}
+#endif /* CONFIG_PNP */
+
 	if (!cards) {
 #ifdef MODULE
 		printk(KERN_ERR IDENT " soundcard not found or device busy\n");
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index bf5de07..08f032b 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -1878,9 +1878,9 @@
 MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
 
 static struct platform_device *platform_devices[SNDRV_CARDS];
-static int pnp_registered;
 
 #ifdef CONFIG_PNP
+static int pnp_registered;
 
 static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
 	/* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */
@@ -2209,8 +2209,10 @@
 {
 	int i;
 
+#ifdef CONFIG_PNP
 	if (pnp_registered)
 		pnp_unregister_card_driver(&es18xx_pnpc_driver);
+#endif
 	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
 		platform_device_unregister(platform_devices[i]);
 	platform_driver_unregister(&snd_es18xx_nonpnp_driver);
@@ -2237,11 +2239,13 @@
 		cards++;
 	}
 
+#ifdef CONFIG_PNP
 	i = pnp_register_card_driver(&es18xx_pnpc_driver);
 	if (i >= 0) {
 		pnp_registered = 1;
 		cards += i;
 	}
+#endif
 
 	if(!cards) {
 #ifdef MODULE
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index d1165b9..91c2191 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -195,7 +195,7 @@
 			goto _err;
 	}
 	sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, xirq, xdma1);
-	if (dma2 >= 0)
+	if (xdma2 >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
 
 	snd_card_set_dev(card, &pdev->dev);
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index ca359e0..9d84319 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -91,8 +91,10 @@
 MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
 
 static struct platform_device *platform_devices[SNDRV_CARDS];
+#ifdef CONFIG_PNP
 static int pnp_registered;
 static int pnpc_registered;
+#endif
 
 /* control ports */
 #define OPL3SA2_PM_CTRL		0x01
@@ -721,7 +723,7 @@
 	}
 	sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
 		card->shortname, chip->port, xirq, xdma1);
-	if (dma2 >= 0)
+	if (xdma2 >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
 
 	return snd_card_register(card);
@@ -779,7 +781,7 @@
 #endif
 
 static struct pnp_driver opl3sa2_pnp_driver = {
-	.name = "opl3sa2-pnpbios",
+	.name = "snd-opl3sa2-pnpbios",
 	.id_table = snd_opl3sa2_pnpbiosids,
 	.probe = snd_opl3sa2_pnp_detect,
 	.remove = __devexit_p(snd_opl3sa2_pnp_remove),
@@ -846,7 +848,7 @@
 
 static struct pnp_card_driver opl3sa2_pnpc_driver = {
 	.flags = PNP_DRIVER_RES_DISABLE,
-	.name = "opl3sa2",
+	.name = "snd-opl3sa2-cpnp",
 	.id_table = snd_opl3sa2_pnpids,
 	.probe = snd_opl3sa2_pnp_cdetect,
 	.remove = __devexit_p(snd_opl3sa2_pnp_cremove),
@@ -929,10 +931,12 @@
 {
 	int i;
 
+#ifdef CONFIG_PNP
 	if (pnpc_registered)
 		pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
 	if (pnp_registered)
 		pnp_unregister_driver(&opl3sa2_pnp_driver);
+#endif
 	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
 		platform_device_unregister(platform_devices[i]);
 	platform_driver_unregister(&snd_opl3sa2_nonpnp_driver);
@@ -961,6 +965,7 @@
 		cards++;
 	}
 
+#ifdef CONFIG_PNP
 	err = pnp_register_driver(&opl3sa2_pnp_driver);
 	if (err >= 0) {
 		pnp_registered = 1;
@@ -971,6 +976,7 @@
 		pnpc_registered = 1;
 		cards += err;
 	}
+#endif
 
 	if (!cards) {
 #ifdef MODULE
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 1ea3944..63d96be 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -1349,7 +1349,7 @@
 	int error;
 	struct snd_pcm *pcm;
 
-	if ((error = snd_pcm_new(codec->card, "OPTi 82C93X", device, 1, 1, &pcm)))
+	if ((error = snd_pcm_new(codec->card, "OPTi 82C93X", device, 1, 1, &pcm)) < 0)
 		return error;
 
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_opti93x_playback_ops);
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index c0be7a5..0667bd1 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -179,6 +179,8 @@
 	{ .id = "CTL0086", .devs = { { "CTL0041" } } },
 	/* Sound Blaster Vibra16X */
 	{ .id = "CTL00f0", .devs = { { "CTL0043" } } },
+	/* Sound Blaster 16 (Virtual PC 2004) */
+	{ .id = "tBA03b0", .devs = { {.id="PNPb003" } } },
 #else  /* SNDRV_SBAWE defined */
 	/* Sound Blaster AWE 32 PnP */
 	{ .id = "CTL0035", .devs = { { "CTL0031" }, { "CTL0021" } } },
@@ -235,8 +237,6 @@
 	{ .id = "CTLXXXX" , .devs = { { "CTL0044" }, { "CTL0023" } } },
 	{ .id = "CTLXXXX" , .devs = { { "CTL0045" }, { "CTL0022" } } },
 #endif /* SNDRV_SBAWE */
-	/* Sound Blaster 16 PnP (Virtual PC 2004)*/
-	{ .id = "tBA03b0", .devs = { { "PNPb003" } } },
 	{ .id = "", }
 };
 
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 5fb981c0..29bba8c 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -69,9 +69,9 @@
 MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
 
 static struct platform_device *platform_devices[SNDRV_CARDS];
-static int pnp_registered;
   
 #ifdef CONFIG_PNP
+static int pnp_registered;
 static struct pnp_card_device_id sscape_pnpids[] = {
 	{ .id = "ENS3081", .devs = { { "ENS0000" } } },
 	{ .id = "" }	/* end */
@@ -1391,8 +1391,10 @@
 {
 	int i;
 
+#ifdef CONFIG_PNP
 	if (pnp_registered)
 		pnp_unregister_card_driver(&sscape_pnpc_driver);
+#endif
 	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
 		platform_device_unregister(platform_devices[i]);
 	platform_driver_unregister(&snd_sscape_driver);
@@ -1466,8 +1468,10 @@
 	ret = sscape_manual_probe();
 	if (ret < 0)
 		return ret;
+#ifdef CONFIG_PNP
 	if (pnp_register_card_driver(&sscape_pnpc_driver) >= 0)
 		pnp_registered = 1;
+#endif
 	return 0;
 }
 
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index a6dcb2f..fa3ab96 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -84,10 +84,9 @@
 MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
 
 static struct platform_device *platform_devices[SNDRV_CARDS];
-static int pnp_registered;
-
 
 #ifdef CONFIG_PNP
+static int pnp_registered;
 
 static struct pnp_card_device_id snd_wavefront_pnpids[] = {
 	/* Tropez */
@@ -695,8 +694,10 @@
 {
 	int i;
 
+#ifdef CONFIG_PNP
 	if (pnp_registered)
 		pnp_unregister_card_driver(&wavefront_pnpc_driver);
+#endif
 	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
 		platform_device_unregister(platform_devices[i]);
 	platform_driver_unregister(&snd_wavefront_driver);
@@ -725,11 +726,13 @@
 		cards++;
 	}
 
+#ifdef CONFIG_PNP
 	i = pnp_register_card_driver(&wavefront_pnpc_driver);
 	if (i >= 0) {
 		pnp_registered = 1;
 		cards += i;
 	}
+#endif
 
 	if (!cards) {
 #ifdef MODULE
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index ed81eec..68aa091 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -866,7 +866,7 @@
 	   divided by 2.
         */
 
-	u16 sample_short;
+	u16 sample_short = 0;
 	u32 length;
 	u16 __user *data_end = NULL;
 	unsigned int i;
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index b963c55..bdee050 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -462,7 +462,7 @@
 	/* Wait for Transmit Busy to show disabled.
 	*/
 	do {
-		stat = readl((void *)PSC_AC97STAT);
+		stat = au_readl(PSC_AC97STAT);
 		au_sync();
 	} while ((stat & PSC_AC97STAT_TB) != 0);
 
@@ -491,7 +491,7 @@
 	/* Wait for Receive Busy to show disabled.
 	*/
 	do {
-		stat = readl((void *)PSC_AC97STAT);
+		stat = au_readl(PSC_AC97STAT);
 		au_sync();
 	} while ((stat & PSC_AC97STAT_RB) != 0);
 
@@ -541,7 +541,7 @@
 	/* Wait for Device ready.
 	*/
 	do {
-		stat = readl((void *)PSC_AC97STAT);
+		stat = au_readl(PSC_AC97STAT);
 		au_sync();
 	} while ((stat & PSC_AC97STAT_DR) == 0);
 }
@@ -573,7 +573,7 @@
 	/* Wait for Device ready.
 	*/
 	do {
-		stat = readl((void *)PSC_AC97STAT);
+		stat = au_readl(PSC_AC97STAT);
 		au_sync();
 	} while ((stat & PSC_AC97STAT_DR) == 0);
 }
@@ -1995,7 +1995,7 @@
 	/* Wait for PSC ready.
 	*/
 	do {
-		val = readl((void *)PSC_AC97STAT);
+		val = au_readl(PSC_AC97STAT);
 		au_sync();
 	} while ((val & PSC_AC97STAT_SR) == 0);
 
@@ -2018,7 +2018,7 @@
 	/* Wait for Device ready.
 	*/
 	do {
-		val = readl((void *)PSC_AC97STAT);
+		val = au_readl(PSC_AC97STAT);
 		au_sync();
 	} while ((val & PSC_AC97STAT_DR) == 0);
 
diff --git a/sound/oss/dmasound/tas_common.h b/sound/oss/dmasound/tas_common.h
index 3a6d486..0741c28 100644
--- a/sound/oss/dmasound/tas_common.h
+++ b/sound/oss/dmasound/tas_common.h
@@ -178,10 +178,10 @@
 	if (write_mode & WRITE_SHADOW)
 		memcpy(self->shadow[reg_num],data,reg_width);
 	if (write_mode & WRITE_HW) {
-		rc=i2c_smbus_write_block_data(self->client,
-					      reg_num,
-					      reg_width,
-					      data);
+		rc=i2c_smbus_write_i2c_block_data(self->client,
+						  reg_num,
+						  reg_width,
+						  data);
 		if (rc < 0) {
 			printk("tas: I2C block write failed \n");  
 			return rc; 
@@ -199,10 +199,10 @@
 
 	if (reg_width==0 || self==NULL)
 		return -EINVAL;
-	rc=i2c_smbus_write_block_data(self->client,
-				      reg_num,
-				      reg_width,
-				      self->shadow[reg_num]);
+	rc=i2c_smbus_write_i2c_block_data(self->client,
+					  reg_num,
+					  reg_width,
+					  self->shadow[reg_num]);
 	if (rc < 0) {
 		printk("tas: I2C block write failed \n");
 		return rc;
diff --git a/sound/oss/emu10k1/recmgr.c b/sound/oss/emu10k1/recmgr.c
index 67c3fd0..2ce5618 100644
--- a/sound/oss/emu10k1/recmgr.c
+++ b/sound/oss/emu10k1/recmgr.c
@@ -29,7 +29,7 @@
  **********************************************************************
  */
 
-#include <asm/delay.h>
+#include <linux/delay.h>
 #include "8010.h"
 #include "recmgr.h"
 
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 5f0ad6b..a21c663 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -278,16 +278,14 @@
 };
 
 static struct pci_device_id trident_pci_tbl[] = {
-	{PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX},
-	{PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_NX},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018},
-	{PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI_5451},
-	{PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CYBER5050},
+	{PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
+		PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TRIDENT_4D_DX},
+	{PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
+		0, 0, TRIDENT_4D_NX},
+	{PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, SIS_7018},
+	{PCI_DEVICE(PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451), 0, 0, ALI_5451},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050),
+		0, 0, CYBER5050},
 	{0,}
 };
 
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 4aa5fdc..a444a78 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -1621,8 +1621,27 @@
 	AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
 };
 
+/* black list to avoid HP/Line jack-sense controls
+ * (SS vendor << 16 | device)
+ */
+static unsigned int ad1981_jacks_blacklist[] = {
+	0x10140554, /* Thinkpad T42p/R50p */
+	0 /* end */
+};
+
+static int check_list(struct snd_ac97 *ac97, const unsigned int *list)
+{
+	u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
+	for (; *list; list++)
+		if (*list == subid)
+			return 1;
+	return 0;
+}
+
 static int patch_ad1981a_specific(struct snd_ac97 * ac97)
 {
+	if (check_list(ac97, ad1981_jacks_blacklist))
+		return 0;
 	return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
 				    ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
 }
@@ -1635,22 +1654,26 @@
 #endif
 };
 
+/* white list to enable HP jack-sense bits
+ * (SS vendor << 16 | device)
+ */
+static unsigned int ad1981_jacks_whitelist[] = {
+	0x0e11005a, /* HP nc4000/4010 */
+	0x103c0890, /* HP nc6000 */
+	0x103c0938, /* HP nc4220 */
+	0x103c099c, /* HP nx6110 */
+	0x103c0944, /* HP nc6220 */
+	0x103c0934, /* HP nc8220 */
+	0x103c006d, /* HP nx9105 */
+	0x17340088, /* FSC Scenic-W */
+	0 /* end */
+};
+
 static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97)
 {
-	u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
-	switch (subid) {
-	case 0x0e11005a: /* HP nc4000/4010 */
-	case 0x103c0890: /* HP nc6000 */
-	case 0x103c0938: /* HP nc4220 */
-	case 0x103c099c: /* HP nx6110 */
-	case 0x103c0944: /* HP nc6220 */
-	case 0x103c0934: /* HP nc8220 */
-	case 0x103c006d: /* HP nx9105 */
-	case 0x17340088: /* FSC Scenic-W */
+	if (check_list(ac97, ad1981_jacks_whitelist))
 		/* enable headphone jack sense */
 		snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11);
-		break;
-	}
 }
 
 int patch_ad1981a(struct snd_ac97 *ac97)
@@ -1672,6 +1695,8 @@
 
 	if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
 		return err;
+	if (check_list(ac97, ad1981_jacks_blacklist))
+		return 0;
 	return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
 				    ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
 }
@@ -2210,9 +2235,9 @@
 	/* Vref disable (bit12), 1kOhm (bit13) */
 	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
 			     shared ? (1<<12) : (1<<13));
-	/* MIC-IN = 1, CENTER-LFE = 2 */
+	/* MIC-IN = 1, CENTER-LFE = 5 */
 	snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
-			     shared ? (2<<4) : (1<<4));
+			     shared ? (5<<4) : (1<<4));
 }
 
 static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index bc4d1ef..e264136 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -279,7 +279,7 @@
 };
 
 static struct pci_device_id snd_ali_ids[] = {
-	{0x10b9, 0x5451, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0},
 	{0, }
 };
 MODULE_DEVICE_TABLE(pci, snd_ali_ids);
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
index 13bc8ed..c8280f8 100644
--- a/sound/pci/au88x0/au88x0_eq.c
+++ b/sound/pci/au88x0/au88x0_eq.c
@@ -849,7 +849,7 @@
 snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
-	int i, count;
+	int i, count = 0;
 	u16 peaks[20];
 
 	vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count);
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index dc9cd30..c840a4c 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -781,6 +781,8 @@
 	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000),
 	/* Viewcast Osprey 200 */
 	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100),
+	/* AVerMedia Studio No. 103, 203, ...? */
+	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000),
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, snd_bt87x_ids);
@@ -808,7 +810,7 @@
 	const struct pci_device_id *supported;
 
 	supported = pci_match_device(&driver, pci);
-	if (supported)
+	if (supported && supported->driver_data > 0)
 		return supported->driver_data;
 
 	for (i = 0; i < ARRAY_SIZE(blacklist); ++i)
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 6ed7c0b..9477838 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -199,7 +199,8 @@
 	   .name   = "MSI K8N Diamond MB [SB0438]",
 	   .gpio_type = 1,
 	   .i2c_adc = 1 } ,
-	 /* Shuttle XPC SD31P which has an onboard Creative Labs Sound Blaster Live! 24-bit EAX
+	 /* Shuttle XPC SD31P which has an onboard Creative Labs
+	  * Sound Blaster Live! 24-bit EAX
 	  * high-definition 7.1 audio processor".
 	  * Added using info from andrewvegan in alsa bug #1298
 	  */
@@ -207,6 +208,15 @@
 	   .name   = "Shuttle XPC SD31P [SD31P]",
 	   .gpio_type = 1,
 	   .i2c_adc = 1 } ,
+	/* Shuttle XPC SD11G5 which has an onboard Creative Labs
+	 * Sound Blaster Live! 24-bit EAX
+	 * high-definition 7.1 audio processor".
+	 * Fixes ALSA bug#1600
+         */
+	{ .serial = 0x30411297,
+	  .name = "Shuttle XPC SD11G5 [SD11G5]",
+	  .gpio_type = 1,
+	  .i2c_adc = 1 } ,
 	 { .serial = 0,
 	   .name   = "AudigyLS [Unknown]" }
 };
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 509aa2b..d4e0fb3 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -675,7 +675,7 @@
 		if (pass_through) {
 			/* wont work with any other rate than
 			   the native DSP rate */
-			snd_assert (rate = 48000);
+			snd_assert (rate == 48000);
 
 			scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb,
 							    dest,"DMAREADER",parent_scb,
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index f36ede8..02e3721 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -46,8 +46,10 @@
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
 
 static struct pci_device_id snd_cs5535audio_ids[] = {
-	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO, PCI_ANY_ID,
-		PCI_ANY_ID, 0, 0, 0, },
+	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
 	{}
 };
 
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 2e86a90..2a9d12d 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -759,6 +759,8 @@
 		"Master Mono Playback Volume",
 		"PCM Out Path & Mute",
 		"Mono Output Select",
+		"Front Playback Switch",
+		"Front Playback Volume",
 		"Surround Playback Switch",
 		"Surround Playback Volume",
 		"Center Playback Switch",
@@ -829,9 +831,9 @@
 		}
 		if (emu->audigy) {
 			/* set master volume to 0 dB */
-			snd_ac97_write(emu->ac97, AC97_MASTER, 0x0000);
+			snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
 			/* set capture source to mic */
-			snd_ac97_write(emu->ac97, AC97_REC_SEL, 0x0000);
+			snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
 			c = audigy_remove_ctls;
 		} else {
 			/*
@@ -844,8 +846,8 @@
 				snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
 			}
 			/* remove unused AC97 controls */
-			snd_ac97_write(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
-			snd_ac97_write(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
+			snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
+			snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
 			c = emu10k1_remove_ctls;
 		}
 		for (; *c; c++)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index a983deb..fd12b69 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -75,6 +75,7 @@
 			 "{Intel, ICH6M},"
 			 "{Intel, ICH7},"
 			 "{Intel, ESB2},"
+			 "{Intel, ICH8},"
 			 "{ATI, SB450},"
 			 "{VIA, VT8251},"
 			 "{VIA, VT8237A},"
@@ -1586,6 +1587,7 @@
 	{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */
 	{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
 	{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
+	{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
 	{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
 	{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
 	{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index ad9e501..b767552 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1668,6 +1668,7 @@
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x8196, .config = ALC880_6ST }, /* ASUS P5GD1-HVM */
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x81b4, .config = ALC880_6ST },
 	{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
+	{ .pci_subvendor = 0x1458, .pci_subdevice = 0xa102, .config = ALC880_6ST }, /* Gigabyte K8N51 */
 
 	{ .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
 	{ .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
@@ -2475,7 +2476,7 @@
 	/* LINE-2 is used for line-out in rear */
 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 	/* select line-out */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
 	/* LINE-OUT pin */
 	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 	/* enable HP */
@@ -2945,6 +2946,8 @@
  */
 static struct hda_board_config alc260_cfg_tbl[] = {
 	{ .modelname = "basic", .config = ALC260_BASIC },
+	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb,
+	  .config = ALC260_BASIC }, /* Sony VAIO */
 	{ .modelname = "hp", .config = ALC260_HP },
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
@@ -3414,12 +3417,12 @@
  * configuration and preset
  */
 static struct hda_board_config alc882_cfg_tbl[] = {
-	{ .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
-	{ .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
+	{ .modelname = "3stack-dig", .config = ALC882_3ST_DIG },
+	{ .modelname = "6stack-dig", .config = ALC882_6ST_DIG },
 	{ .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI  */
 	{ .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */
 	{ .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */
-	{ .modelname = "auto", .config = ALC861_AUTO },
+	{ .modelname = "auto", .config = ALC882_AUTO },
 	{}
 };
 
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 8f8840e..250242c 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -297,6 +297,7 @@
 struct hda_codec_preset snd_hda_preset_si3054[] = {
  	{ .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 },
  	{ .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 },
+ 	{ .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 },
 	{}
 };
 
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 6190384..35c2823 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -50,10 +50,11 @@
 	unsigned int surr_switch: 1;
 	unsigned int line_switch: 1;
 	unsigned int mic_switch: 1;
+	unsigned int alt_switch: 1;
 
 	/* playback */
 	struct hda_multi_out multiout;
-	hda_nid_t dac_nids[4];
+	hda_nid_t dac_nids[5];
 
 	/* capture */
 	hda_nid_t *adc_nids;
@@ -73,7 +74,7 @@
 
 	/* capture source */
 	struct hda_input_mux *input_mux;
-	unsigned int cur_mux[2];
+	unsigned int cur_mux[3];
 
 	/* i/o switches */
 	unsigned int io_switch[2];
@@ -107,6 +108,14 @@
         0x12, 0x13,
 };
 
+static hda_nid_t stac927x_adc_nids[3] = {
+        0x07, 0x08, 0x09
+};
+
+static hda_nid_t stac927x_mux_nids[3] = {
+        0x15, 0x16, 0x17
+};
+
 static hda_nid_t stac9200_pin_nids[8] = {
 	0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
 };
@@ -116,6 +125,12 @@
 	0x0f, 0x10, 0x11, 0x15, 0x1b,
 };
 
+static hda_nid_t stac927x_pin_nids[14] = {
+	0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+	0x0f, 0x10, 0x11, 0x12, 0x13,
+	0x14, 0x21, 0x22, 0x23,
+};
+
 static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -155,6 +170,12 @@
 	{}
 };
 
+static struct hda_verb stac927x_core_init[] = {
+	/* set master volume and direct control */	
+	{ 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
+	{}
+};
+
 static struct snd_kcontrol_new stac9200_mixer[] = {
 	HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
@@ -183,10 +204,26 @@
 		.put = stac92xx_mux_enum_put,
 	},
 	HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),
 	{ } /* end */
 };
 
+static snd_kcontrol_new_t stac927x_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Input Source",
+		.count = 1,
+		.info = stac92xx_mux_enum_info,
+		.get = stac92xx_mux_enum_get,
+		.put = stac92xx_mux_enum_put,
+	},
+	HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
 static int stac92xx_build_controls(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
@@ -240,14 +277,14 @@
 };
 
 static unsigned int d945gtp3_pin_configs[10] = {
-	0x0221401f, 0x01a19022, 0x01813021, 0x01114010,
+	0x0221401f, 0x01a19022, 0x01813021, 0x01014010,
 	0x40000100, 0x40000100, 0x40000100, 0x40000100,
 	0x02a19120, 0x40000100,
 };
 
 static unsigned int d945gtp5_pin_configs[10] = {
-	0x0221401f, 0x01111012, 0x01813024, 0x01114010,
-	0x01a19021, 0x01116011, 0x01452130, 0x40000100,
+	0x0221401f, 0x01011012, 0x01813024, 0x01014010,
+	0x01a19021, 0x01016011, 0x01452130, 0x40000100,
 	0x02a19320, 0x40000100,
 };
 
@@ -274,6 +311,28 @@
 	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
 	  .pci_subdevice = 0x0013,
 	  .config = STAC_D945GTP5 },	/* Intel D955XBK - 5 Stack */
+	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
+	  .pci_subdevice = 0x0417,
+	  .config = STAC_D945GTP5 },	/* Intel D975XBK - 5 Stack */
+	{} /* terminator */
+};
+
+static unsigned int ref927x_pin_configs[14] = {
+	0x01813122, 0x01a19021, 0x01014010, 0x01016011,
+	0x01012012, 0x01011014, 0x40000100, 0x40000100, 
+	0x40000100, 0x40000100, 0x40000100, 0x01441030,
+	0x01c41030, 0x40000100,
+};
+
+static unsigned int *stac927x_brd_tbl[] = {
+	ref927x_pin_configs,
+};
+
+static struct hda_board_config stac927x_cfg_tbl[] = {
+	{ .modelname = "ref",
+	  .pci_subvendor = PCI_VENDOR_ID_INTEL,
+	  .pci_subdevice = 0x2668,	/* DFI LanParty */
+	  .config = STAC_REF },		/* SigmaTel reference board */
 	{} /* terminator */
 };
 
@@ -408,11 +467,23 @@
 	},
 };
 
+static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x06, /* NID to query formats and rates */
+	.ops = {
+		.open = stac92xx_playback_pcm_open,
+		.prepare = stac92xx_playback_pcm_prepare,
+		.cleanup = stac92xx_playback_pcm_cleanup
+	},
+};
+
 static struct hda_pcm_stream stac92xx_pcm_analog_capture = {
 	.substreams = 2,
 	.channels_min = 2,
 	.channels_max = 2,
-	.nid = 0x06, /* NID to query formats and rates */
+	/* NID is set in stac92xx_build_pcms */
 	.ops = {
 		.prepare = stac92xx_capture_pcm_prepare,
 		.cleanup = stac92xx_capture_pcm_cleanup
@@ -430,6 +501,14 @@
 	info->name = "STAC92xx Analog";
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
 	info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
+
+	if (spec->alt_switch) {
+		codec->num_pcms++;
+		info++;
+		info->name = "STAC92xx Analog Alt";
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_alt_playback;
+	}
 
 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
 		codec->num_pcms++;
@@ -588,6 +667,16 @@
 	return 0;
 }
 
+/*
+ * XXX The line_out pin widget connection list may not be set to the
+ * desired DAC nid. This is the case on 927x where ports A and B can
+ * be routed to several DACs.
+ *
+ * This requires an analysis of the line-out/hp pin configuration
+ * to provide a best fit for pin/DAC configurations that are routable.
+ * For now, 927x DAC4 is not supported and 927x DAC1 output to ports
+ * A and B is not supported.
+ */
 /* fill in the dac_nids table from the parsed pin configuration */
 static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
 {
@@ -602,7 +691,13 @@
 					AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
 	}
 
-	spec->multiout.num_dacs = cfg->line_outs;
+	if (cfg->line_outs)
+		spec->multiout.num_dacs = cfg->line_outs;
+	else if (cfg->hp_pin) {
+		spec->multiout.dac_nids[0] = snd_hda_codec_read(codec, cfg->hp_pin, 0,
+					AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
+		spec->multiout.num_dacs = 1;
+	}
 
 	return 0;
 }
@@ -753,19 +848,21 @@
 		stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
 }
 
-static int stac922x_parse_auto_config(struct hda_codec *codec)
+static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
 {
 	struct sigmatel_spec *spec = codec->spec;
 	int err;
 
 	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
 		return err;
+	if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin)
+		return 0; /* can't find valid pin config */
+	stac92xx_auto_init_multi_out(codec);
+	stac92xx_auto_init_hp_out(codec);
 	if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0)
 		return err;
 	if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
 		return err;
-	if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin)
-		return 0; /* can't find valid pin config */
 
 	if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
 	    (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 ||
@@ -777,11 +874,11 @@
 		spec->surr_switch = 1;
 
 	if (spec->autocfg.dig_out_pin) {
-		spec->multiout.dig_out_nid = 0x08;
+		spec->multiout.dig_out_nid = dig_out;
 		stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN);
 	}
 	if (spec->autocfg.dig_in_pin) {
-		spec->dig_in_nid = 0x09;
+		spec->dig_in_nid = dig_in;
 		stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN);
 	}
 
@@ -827,9 +924,6 @@
 
 	snd_hda_sequence_write(codec, spec->init);
 
-	stac92xx_auto_init_multi_out(codec);
-	stac92xx_auto_init_hp_out(codec);
-
 	return 0;
 }
 
@@ -996,7 +1090,47 @@
 
 	spec->multiout.dac_nids = spec->dac_nids;
 
-	err = stac922x_parse_auto_config(codec);
+	err = stac92xx_parse_auto_config(codec, 0x08, 0x09);
+	if (err < 0) {
+		stac92xx_free(codec);
+		return err;
+	}
+
+	codec->patch_ops = stac92xx_patch_ops;
+
+	return 0;
+}
+
+static int patch_stac927x(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec;
+	int err;
+
+	spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl);
+	if (spec->board_config < 0)
+                snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n");
+	else {
+		spec->num_pins = 14;
+		spec->pin_nids = stac927x_pin_nids;
+		spec->pin_configs = stac927x_brd_tbl[spec->board_config];
+		stac92xx_set_config_regs(codec);
+	}
+
+	spec->adc_nids = stac927x_adc_nids;
+	spec->mux_nids = stac927x_mux_nids;
+	spec->num_muxes = 3;
+
+	spec->init = stac927x_core_init;
+	spec->mixer = stac927x_mixer;
+
+	spec->multiout.dac_nids = spec->dac_nids;
+
+	err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
 	if (err < 0) {
 		stac92xx_free(codec);
 		return err;
@@ -1018,5 +1152,15 @@
  	{ .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x },
  	{ .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x },
  	{ .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x },
+ 	{ .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x },
+ 	{ .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x },
+ 	{ .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x },
+ 	{ .id = 0x83847623, .name = "STAC9273D", .patch = patch_stac927x },
+ 	{ .id = 0x83847624, .name = "STAC9272X", .patch = patch_stac927x },
+ 	{ .id = 0x83847625, .name = "STAC9272D", .patch = patch_stac927x },
+ 	{ .id = 0x83847626, .name = "STAC9271X", .patch = patch_stac927x },
+ 	{ .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x },
+ 	{ .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x },
+ 	{ .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x },
 	{} /* terminator */
 };
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 5466b1f..174237f 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -427,6 +427,7 @@
 	{ 0x10de, 0x008a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK8 */
 	{ 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE3 */
 	{ 0x10de, 0x00ea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK8S */
+	{ 0x10de, 0x026b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* MCP51 */
 	{ 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD8111 */
 	{ 0x1022, 0x7445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD768 */
 	{ 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI },   /* Ali5455 */
@@ -1805,6 +1806,12 @@
 	},
 	{
 		.subvendor = 0x1028,
+		.subdevice = 0x0151,
+		.name = "Dell Optiplex GX270",  /* AD1981B */
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.subvendor = 0x1028,
 		.subdevice = 0x0163,
 		.name = "Dell Unknown",	/* STAC9750/51 */
 		.type = AC97_TUNE_HP_ONLY
@@ -1847,12 +1854,6 @@
 	},
 	{
 		.subvendor = 0x103c,
-		.subdevice = 0x099c,
-		.name = "HP nx6110",	/* AD1981B */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.subvendor = 0x103c,
 		.subdevice = 0x129d,
 		.name = "HP xw8000",
 		.type = AC97_TUNE_HP_ONLY
@@ -1866,7 +1867,7 @@
 	{
 		.subvendor = 0x103c,
 		.subdevice = 0x099c,
-		.name = "HP nc6120",
+		.name = "HP nx6110/nc6120",
 		.type = AC97_TUNE_HP_MUTE_LED
 	},
 	{
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index b8c0853..b2cba75 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -454,7 +454,7 @@
 	is_capture = (subs->stream == SNDRV_PCM_STREAM_CAPTURE);
 	stream_num = is_capture ? 0 : subs->number;
 
-	snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%x) subs(%d)\n",
+	snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
 		    is_capture ? 'c' : 'p',
 		    chip->chip_idx, (void*)subs->runtime->dma_addr,
 		    subs->runtime->dma_bytes, subs->number);
@@ -744,13 +744,14 @@
 		/* only the first stream can choose the sample rate */
 		/* the further opened streams will be limited to its frequency (see open) */
 		/* set the clock only once (first stream) */
-		if (mgr->sample_rate == 0) {
+		if (mgr->sample_rate != subs->runtime->rate) {
 			err = pcxhr_set_clock(mgr, subs->runtime->rate);
 			if (err)
 				break;
+			if (mgr->sample_rate == 0)
+				/* start the DSP-timer */
+				err = pcxhr_hardware_timer(mgr, 1);
 			mgr->sample_rate = subs->runtime->rate;
-
-			err = pcxhr_hardware_timer(mgr, 1);	/* start the DSP-timer */
 		}
 	} while(0);	/* do only once (so we can use break instead of goto) */
 
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 3dec616..103b4d7 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -3324,11 +3324,11 @@
 						   snd_dma_pci_data(hdspm->pci),
 						   wanted,
 						   wanted)) < 0) {
-		snd_printdd("Could not preallocate %d  Bytes\n", wanted);
+		snd_printdd("Could not preallocate %zd Bytes\n", wanted);
 
 		return err;
 	} else
-		snd_printdd(" Preallocated %d  Bytes\n", wanted);
+		snd_printdd(" Preallocated %zd Bytes\n", wanted);
 
 	return 0;
 }
@@ -3510,7 +3510,7 @@
 
 	hdspm->monitor_outs = enable_monitor;
 
-	snd_printdd("kmalloc Mixer memory of %d Bytes\n",
+	snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
 		   sizeof(struct hdspm_mixer));
 	if ((hdspm->mixer = kmalloc(sizeof(struct hdspm_mixer), GFP_KERNEL))
 	    == NULL) {
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 2b21df1..b453804 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -64,9 +64,11 @@
 MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth.");
 
 static struct pci_device_id snd_trident_ids[] = {
-	{ 0x1023, 0x2000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },	/* Trident 4DWave DX PCI Audio */
-	{ 0x1023, 0x2001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },	/* Trident 4DWave NX PCI Audio */
-	{ 0x1039, 0x7018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },	/* SiS SI7018 PCI Audio */
+	{PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), 
+		PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
+	{PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), 
+		0, 0, 0},
+	{PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, 0},
 	{ 0, }
 };
 
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index ed26a15..4237413 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2340,6 +2340,7 @@
 		{ .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ 
 		{ .subvendor = 0x1043, .subdevice = 0x810d, .action = VIA_DXS_SRC }, /* ASUS */
 		{ .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC    }, /* ASUS A8V Deluxe */ 
+		{ .subvendor = 0x1043, .subdevice = 0x8174, .action = VIA_DXS_SRC    }, /* ASUS */
 		{ .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
 		{ .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */
 		{ .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
@@ -2358,6 +2359,7 @@
 		{ .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
 		{ .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
 		{ .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */
+		{ .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */
 		{ .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
 		{ .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
 		{ .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
@@ -2371,6 +2373,9 @@
 		{ .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
 		{ .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
 		{ .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
+		{ .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */
+		{ .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */
+		{ .subvendor = 0x1734, .subdevice = 0x1093, .action = VIA_DXS_SRC }, /* FSC */
 		{ .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
 		{ .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */
 		{ .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 1dfc723..a1aa74b 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -1229,6 +1229,7 @@
 	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.iec958.status[0] = (chip->spdif_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (chip->spdif_bits >> 8) & 0xff;
+	ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000;
 	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
@@ -1303,6 +1304,7 @@
 	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.iec958.status[0] = (chip->spdif_pcm_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (chip->spdif_pcm_bits >> 8) & 0xff;
+	ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000;
 	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index a642e4c..aa57170 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -66,7 +66,7 @@
 
 static void snd_pmac_dbdma_free(struct snd_pmac *chip, struct pmac_dbdma *rec)
 {
-	if (rec) {
+	if (rec->space) {
 		unsigned int rsize = sizeof(struct dbdma_cmd) * (rec->size + 1);
 
 		dma_free_coherent(&chip->pdev->dev, rsize, rec->space, rec->dma_base);
@@ -881,6 +881,7 @@
 	chip->can_capture = 1;
 	chip->num_freqs = ARRAY_SIZE(awacs_freqs);
 	chip->freq_table = awacs_freqs;
+	chip->pdev = NULL;
 
 	chip->control_mask = MASK_IEPC | MASK_IEE | 0x11; /* default */
 
@@ -1216,7 +1217,7 @@
 			goto __error;
 		}
 		for (i = 0; i < 3; i ++) {
-			if (of_address_to_resource(np->parent, i,
+			if (of_address_to_resource(np, i,
 						   &chip->rsrc[i])) {
 				printk(KERN_ERR "snd: can't translate rsrc "
 				       " %d (%s)\n", i, rnames[i]);
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 15c63cb..838fc11 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -239,8 +239,8 @@
 	block[4] = (right_vol >> 8)  & 0xff;
 	block[5] = (right_vol >> 0)  & 0xff;
   
-	if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_VOL,
-				       6, block) < 0) {
+	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6,
+					   block) < 0) {
 		snd_printk("failed to set volume \n");
 		return -EINVAL;
 	}
@@ -345,8 +345,8 @@
 		val[1] = 0;
 	}
 
-	if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC,
-				       2, val) < 0) {
+	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
+					   2, val) < 0) {
 		snd_printk("failed to set DRC\n");
 		return -EINVAL;
 	}
@@ -381,8 +381,8 @@
 	val[4] = 0x60;
 	val[5] = 0xa0;
 
-	if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC,
-				       6, val) < 0) {
+	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
+					   6, val) < 0) {
 		snd_printk("failed to set DRC\n");
 		return -EINVAL;
 	}
@@ -492,8 +492,8 @@
 	vol = info->table[vol];
 	for (i = 0; i < info->bytes; i++)
 		block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff;
-	if (i2c_smbus_write_block_data(mix->i2c.client, info->reg,
-				       info->bytes, block) < 0) {
+	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg,
+					   info->bytes, block) < 0) {
 		snd_printk("failed to set mono volume %d\n", info->index);
 		return -EINVAL;
 	}
@@ -625,7 +625,8 @@
 		for (j = 0; j < 3; j++)
 			block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff;
 	}
-	if (i2c_smbus_write_block_data(mix->i2c.client, reg, 9, block) < 0) {
+	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg,
+					   9, block) < 0) {
 		snd_printk("failed to set mono volume %d\n", reg);
 		return -EINVAL;
 	}
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index a1bd804..d501338 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -478,22 +478,38 @@
 /*
  * Prepare urb for streaming before playback starts.
  *
- * We don't care about (or have) any data, so we just send a transfer delimiter.
+ * We don't yet have data, so we send a frame of silence.
  */
 static int prepare_startup_playback_urb(struct snd_usb_substream *subs,
 					struct snd_pcm_runtime *runtime,
 					struct urb *urb)
 {
-	unsigned int i;
+	unsigned int i, offs, counts;
 	struct snd_urb_ctx *ctx = urb->context;
+	int stride = runtime->frame_bits >> 3;
 
+	offs = 0;
 	urb->dev = ctx->subs->dev;
 	urb->number_of_packets = subs->packs_per_ms;
 	for (i = 0; i < subs->packs_per_ms; ++i) {
-		urb->iso_frame_desc[i].offset = 0;
-		urb->iso_frame_desc[i].length = 0;
+		/* calculate the size of a packet */
+		if (subs->fill_max)
+			counts = subs->maxframesize; /* fixed */
+		else {
+			subs->phase = (subs->phase & 0xffff)
+				+ (subs->freqm << subs->datainterval);
+			counts = subs->phase >> 16;
+			if (counts > subs->maxframesize)
+				counts = subs->maxframesize;
+		}
+		urb->iso_frame_desc[i].offset = offs * stride;
+		urb->iso_frame_desc[i].length = counts * stride;
+		offs += counts;
 	}
-	urb->transfer_buffer_length = 0;
+	urb->transfer_buffer_length = offs * stride;
+	memset(urb->transfer_buffer,
+	       subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
+	       offs * stride);
 	return 0;
 }
 
@@ -2477,12 +2493,13 @@
 	if (err < 0)
 		return err;
 #if 1
-	/* FIXME: temporary hack for extigy/audigy 2 nx */
+	/* FIXME: temporary hack for extigy/audigy 2 nx/zs */
 	/* extigy apparently supports sample rates other than 48k
 	 * but not in ordinary way.  so we enable only 48k atm.
 	 */
 	if (chip->usb_id == USB_ID(0x041e, 0x3000) ||
-	    chip->usb_id == USB_ID(0x041e, 0x3020)) {
+	    chip->usb_id == USB_ID(0x041e, 0x3020) ||
+	    chip->usb_id == USB_ID(0x041e, 0x3061)) {
 		if (fmt[3] == USB_FORMAT_TYPE_I &&
 		    fp->rates != SNDRV_PCM_RATE_48000 &&
 		    fp->rates != SNDRV_PCM_RATE_96000)