Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6
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/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 6910c01..391dd64 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -27,6 +27,7 @@
 - laptop_mode
 - block_dump
 - drop-caches
+- zone_reclaim_mode
 
 ==============================================================
 
@@ -120,3 +121,20 @@
 
 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:
+
+This is set during bootup to 1 if it is determined that pages from
+remote zones will cause a significant performance reduction. The
+page allocator will then reclaim easily reusable pages (those page
+cache pages that are currently not used) before going off node.
+
+The user can override this setting. 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.
+
+It may be beneficial to switch this on if one wants to do zone
+reclaim regardless of the numa distances in the system.
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 6d1b048..3f8a90a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -867,6 +867,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
@@ -1398,7 +1407,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
@@ -1696,11 +1705,13 @@
 W: ftp://ftp.kernel.org/pub/linux/docs/manpages
 S: Maintained
 
-MARVELL MV64340 ETHERNET DRIVER
+MARVELL MV643XX ETHERNET DRIVER
+P:	Dale Farnsworth
+M:	dale@farnsworth.org
 P:	Manish Lachwani
-L:	linux-mips@linux-mips.org
+M:	mlachwani@mvista.com
 L:	netdev@vger.kernel.org
-S:	Supported
+S:	Odd Fixes for 2.4; Maintained for 2.6.
 
 MATROX FRAMEBUFFER DRIVER
 P:	Petr Vandrovec
@@ -1841,7 +1852,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
@@ -2534,11 +2552,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/
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/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/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/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 874e6bb..d401d90 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -735,8 +735,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
 
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/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/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/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/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/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/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/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/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/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 6ff3e52..1b66592 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -294,3 +294,18 @@
 	.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_newfstatat		/* 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
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/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/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/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/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/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 177bba7..3747ab0 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -252,8 +252,7 @@
 /*
  * 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;
 
@@ -264,55 +263,10 @@
 	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
@@ -1174,7 +1128,7 @@
 {
 	siginfo_t info;
 	struct k_sigaction ka;
-	unsigned int frame, newsp;
+	unsigned int newsp;
 	int signr, ret;
 
 #ifdef CONFIG_PPC32
@@ -1185,11 +1139,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 +1173,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 +1213,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..b319311 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -67,42 +67,6 @@
 	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/systbl.S b/arch/powerpc/kernel/systbl.S
index 6801317..007b15e 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -321,3 +321,5 @@
 SYSCALL(inotify_rm_watch)
 SYSCALL(spu_run)
 SYSCALL(spu_create)
+COMPAT_SYS(pselect6)
+COMPAT_SYS(ppoll)
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/sparc64/defconfig b/arch/sparc64/defconfig
index a3fb337..9ceddad 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-rc1
+# Wed Jan 18 13:41:02 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -233,6 +233,11 @@
 # 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
@@ -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
@@ -652,7 +657,6 @@
 CONFIG_SERIAL_SUNSAB=m
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 
@@ -738,6 +742,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
@@ -1014,6 +1024,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
@@ -1268,12 +1279,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 +1293,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/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/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/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index d4b7a10..9264ccb 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -821,7 +821,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 +1003,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/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/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..6430a63 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))
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index 30d285b..507e3cb 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -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);
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/net_kern.c b/arch/um/drivers/net_kern.c
index fb1f9fb..8ebb224 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);
 }
@@ -317,6 +328,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 +374,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
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..c649108 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -120,8 +120,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/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..569fe8b 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"
 
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/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.c b/arch/um/kernel/skas/process.c
index 3b3955d..eea1c9c4 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -18,7 +18,6 @@
 #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"
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/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/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/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..9890e90
--- /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);
+	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/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
new file mode 100644
index 0000000..120a21c
--- /dev/null
+++ b/arch/um/os-Linux/skas/process.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#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>
+#include <sys/time.h>
+#include <asm/unistd.h>
+#include <asm/types.h>
+#include "user.h"
+#include "sysdep/ptrace.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "skas.h"
+#include "stub-data.h"
+#include "mm_id.h"
+#include "sysdep/sigcontext.h"
+#include "sysdep/stub.h"
+#include "os.h"
+#include "proc_mm.h"
+#include "skas_ptrace.h"
+#include "chan_user.h"
+#include "registers.h"
+#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())
+		return(0);
+
+	register_winch_irq(-1, fd, -1, data);
+	return(1);
+}
+
+void wait_stub_done(int pid, int sig, char * fname)
+{
+	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;
+
+		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)){
+		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);
+		else {
+			int i;
+
+			printk("Stub registers -\n");
+			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);
+	}
+}
+
+extern unsigned long current_stub_stack(void);
+
+void get_skas_faultinfo(int pid, struct faultinfo * fi)
+{
+	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);
+
+		/* 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));
+	}
+}
+
+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);
+}
+
+/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
+static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
+{
+	int err, status;
+
+	/* Mark this as a syscall */
+	UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs);
+
+	if (!local_using_sysemu)
+	{
+		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+			     __NR_getpid);
+		if(err < 0)
+			panic("handle_trap - nullifying syscall failed errno = %d\n",
+			      errno);
+
+		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+		if(err < 0)
+			panic("handle_trap - continuing to end of syscall failed, "
+			      "errno = %d\n", errno);
+
+		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+		if((err < 0) || !WIFSTOPPED(status) ||
+		   (WSTOPSIG(status) != SIGTRAP + 0x80))
+			panic("handle_trap - failed to wait at end of syscall, "
+			      "errno = %d, status = %d\n", errno, status);
+	}
+
+	handle_syscall(regs);
+}
+
+extern int __syscall_stub_start;
+
+static int userspace_tramp(void *stack)
+{
+	void *addr;
+
+	ptrace(PTRACE_TRACEME, 0, 0, 0);
+
+	init_new_thread_signals(1);
+	enable_timer();
+
+	if(!proc_mm){
+		/* 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, fd, offset);
+		if(addr == MAP_FAILED){
+			printk("mapping mmap stub failed, errno = %d\n",
+			       errno);
+			exit(1);
+		}
+
+		if(stack != NULL){
+			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 segfault stack failed, "
+				       "errno = %d\n", errno);
+				exit(1);
+			}
+		}
+	}
+	if(!ptrace_faultinfo && (stack != NULL)){
+		unsigned long v = UML_CONFIG_STUB_CODE +
+				  (unsigned long) stub_segv_handler -
+				  (unsigned long) &__syscall_stub_start;
+
+		set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
+		set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
+			    SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
+			    SIGUSR1, -1);
+	}
+
+	os_stop_process(os_getpid());
+	return(0);
+}
+
+/* Each element set once, and only accessed by a single processor anyway */
+#undef NR_CPUS
+#define NR_CPUS 1
+int userspace_pid[NR_CPUS];
+
+int start_userspace(unsigned long stub_stack)
+{
+	void *stack;
+	unsigned long sp;
+	int pid, status, n, flags;
+
+	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
+		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if(stack == MAP_FAILED)
+		panic("start_userspace : mmap failed, errno = %d", errno);
+	sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
+
+	flags = CLONE_FILES | SIGCHLD;
+	if(proc_mm) flags |= CLONE_VM;
+	pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
+	if(pid < 0)
+		panic("start_userspace : clone failed, errno = %d", errno);
+
+	do {
+		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+		if(n < 0)
+			panic("start_userspace : wait failed, errno = %d",
+			      errno);
+	} while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
+
+	if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
+		panic("start_userspace : expected SIGSTOP, got status = %d",
+		      status);
+
+	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
+		panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
+		      errno);
+
+	if(munmap(stack, PAGE_SIZE) < 0)
+		panic("start_userspace : munmap failed, errno = %d\n", errno);
+
+	return(pid);
+}
+
+void userspace(union uml_pt_regs *regs)
+{
+	int err, status, op, pid = userspace_pid[0];
+	int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
+
+	while(1){
+		restore_registers(pid, regs);
+
+		/* Now we set local_using_sysemu to be used for one loop */
+		local_using_sysemu = get_using_sysemu();
+
+		op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));
+
+		err = ptrace(op, pid, 0, 0);
+		if(err)
+			panic("userspace - could not resume userspace process, "
+			      "pid=%d, ptrace operation = %d, errno = %d\n",
+			      op, errno);
+
+		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+		if(err < 0)
+			panic("userspace - waitpid failed, errno = %d\n",
+			      errno);
+
+		regs->skas.is_user = 1;
+		save_registers(pid, regs);
+		UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
+
+		if(WIFSTOPPED(status)){
+		  	switch(WSTOPSIG(status)){
+			case SIGSEGV:
+				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);
+				break;
+			case SIGTRAP:
+				relay_signal(SIGTRAP, regs);
+				break;
+			case SIGIO:
+			case SIGVTALRM:
+			case SIGILL:
+			case SIGBUS:
+			case SIGFPE:
+			case SIGWINCH:
+				user_signal(WSTOPSIG(status), regs, pid);
+				break;
+			default:
+			        printk("userspace - child stopped with signal "
+				       "%d\n", WSTOPSIG(status));
+			}
+			pid = userspace_pid[0];
+			interrupt_end();
+
+			/* Avoid -ERESTARTSYS handling in host */
+			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 current_stack = current_stub_stack();
+	struct stub_data *data = (struct stub_data *) current_stack;
+	struct stub_data *child_data = (struct stub_data *) new_stack;
+	__u64 new_offset;
+	int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
+
+	/* prepare offset and fd of child's stack as argument for parent's
+	 * and child's mmap2 calls
+	 */
+	*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);
+
+	/* Set parent's instruction pointer to start of clone-stub */
+	regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+				(unsigned long) stub_clone_handler -
+				(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);
+
+	/* set a well known return code for detection of child write failure */
+	child_data->err = 12345678;
+
+	/* Wait, until parent has finished its work: read child's pid from
+	 * parent's stack, and check, if bad result.
+	 */
+	wait_stub_done(pid, 0, "copy_context_skas0");
+
+	pid = data->err;
+	if(pid < 0)
+		panic("copy_context_skas0 - stub-parent reports error %d\n",
+		      pid);
+
+	/* Wait, until child has finished too: read child's result from
+	 * child's stack and check it.
+	 */
+	wait_stub_done(pid, -1, "copy_context_skas0");
+	if (child_data->err != UML_CONFIG_STUB_DATA)
+		panic("copy_context_skas0 - stub-child reports error %d\n",
+		      child_data->err);
+
+	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
+		   (void *)PTRACE_O_TRACESYSGOOD) < 0)
+		panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
+		      "errno = %d\n", errno);
+
+	return pid;
+}
+
+/*
+ * This is used only, if stub pages are needed, while proc_mm is
+ * availabl. Opening /proc/mm creates a new mm_context, which lacks
+ * the stub-pages. Thus, we map them using /proc/mm-fd
+ */
+void map_stub_pages(int fd, unsigned long code,
+		    unsigned long data, unsigned long stack)
+{
+	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         =
+				      { .mmap    =
+					{ .addr    = code,
+					  .len     = PAGE_SIZE,
+					  .prot    = PROT_EXEC,
+					  .flags   = MAP_FIXED | MAP_PRIVATE,
+					  .fd      = code_fd,
+					  .offset  = code_offset
+	} } });
+	n = os_write_file(fd, &mmop, sizeof(mmop));
+	if(n != sizeof(mmop))
+		panic("map_stub_pages : /proc/mm map for code failed, "
+		      "err = %d\n", -n);
+
+	if ( stack ) {
+		__u64 map_offset;
+		int map_fd = phys_mapping(to_phys((void *)stack), &map_offset);
+		mmop = ((struct proc_mm_op)
+				{ .op        = MM_MMAP,
+				  .u         =
+				  { .mmap    =
+				    { .addr    = data,
+				      .len     = PAGE_SIZE,
+				      .prot    = PROT_READ | PROT_WRITE,
+				      .flags   = MAP_FIXED | MAP_SHARED,
+				      .fd      = map_fd,
+				      .offset  = map_offset
+		} } });
+		n = os_write_file(fd, &mmop, sizeof(mmop));
+		if(n != sizeof(mmop))
+			panic("map_stub_pages : /proc/mm map for data failed, "
+			      "err = %d\n", -n);
+	}
+}
+
+void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
+		void (*handler)(int))
+{
+	unsigned long flags;
+	sigjmp_buf switch_buf, fork_buf;
+	int enable;
+
+	*switch_buf_ptr = &switch_buf;
+	*fork_buf_ptr = &fork_buf;
+
+	/* Somewhat subtle - siglongjmp restores the signal mask before doing
+	 * the longjmp.  This means that when jumping from one stack to another
+	 * when the target stack has interrupts enabled, an interrupt may occur
+	 * on the source stack.  This is bad when starting up a process because
+	 * it's not supposed to get timer ticks until it has been scheduled.
+	 * So, we disable interrupts around the sigsetjmp to ensure that
+	 * they can't happen until we get back here where they are safe.
+	 */
+	flags = get_signals();
+	block_signals();
+	if(UML_SIGSETJMP(&fork_buf, enable) == 0)
+		new_thread_proc(stack, handler);
+
+	remove_sigstack();
+
+	set_signals(flags);
+}
+
+void thread_wait(void *sw, void *fb)
+{
+	sigjmp_buf buf, **switch_buf = sw, *fork_buf;
+	int enable;
+
+	*switch_buf = &buf;
+	fork_buf = fb;
+	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(UML_SIGSETJMP(&my_buf, enable) == 0)
+		UML_SIGLONGJMP(next_buf, 1);
+}
+
+static sigjmp_buf initial_jmpbuf;
+
+/* XXX Make these percpu */
+static void (*cb_proc)(void *arg);
+static void *cb_arg;
+static sigjmp_buf *cb_back;
+
+int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
+{
+	sigjmp_buf **switch_buf = switch_buf_ptr;
+	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 = 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);
+		UML_SIGLONGJMP(cb_back, 1);
+		break;
+	case INIT_JMP_HALT:
+		kmalloc_ok = 0;
+		return(0);
+	case INIT_JMP_REBOOT:
+		kmalloc_ok = 0;
+		return(1);
+	default:
+		panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
+	}
+	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(UML_SIGSETJMP(&here, enable) == 0)
+		UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
+	unblock_signals();
+
+	cb_proc = NULL;
+	cb_arg = NULL;
+	cb_back = NULL;
+}
+
+void halt_skas(void)
+{
+	block_signals();
+	UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
+}
+
+void reboot_skas(void)
+{
+	block_signals();
+	UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
+}
+
+void switch_mm_skas(struct mm_id *mm_idp)
+{
+	int err;
+
+#warning need cpu pid in switch_mm_skas
+	if(proc_mm){
+		err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
+			     mm_idp->u.mm_fd);
+		if(err)
+			panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "
+			      "errno = %d\n", errno);
+	}
+	else userspace_pid[0] = mm_idp->u.pid;
+}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index b47e5e7..6c5b17e 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"
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..0cdfd44 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -16,6 +16,8 @@
 #include "choose-mode.h"
 #include "kern.h"
 #include "mode_kern.h"
+#include "proc_mm.h"
+#include "os.h"
 
 extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
 
@@ -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/x86_64/defconfig b/arch/x86_64/defconfig
index 5231fe8..09a3eb7 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -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
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 58f5bfb..f05c2a8 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -672,6 +672,19 @@
 	.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 sys_futimesat
+	.quad compat_sys_newfstatat	/* 300 */
+	.quad sys_unlinkat
+	.quad sys_renameat
+	.quad sys_linkat
+	.quad sys_symlinkat
+	.quad sys_readlinkat		/* 305 */
+	.quad sys_fchmodat
+	.quad sys_faccessat
 ia32_syscall_end:		
 	.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
 		.quad ni_syscall
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/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..619dd96 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -63,6 +63,7 @@
 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/
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/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/edac/Kconfig b/drivers/edac/Kconfig
new file mode 100644
index 0000000..4819e7f
--- /dev/null
+++ b/drivers/edac/Kconfig
@@ -0,0 +1,102 @@
+#
+#	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
+	default y
+	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
+	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..770a5a6
--- /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..4be9bd0
--- /dev/null
+++ b/drivers/edac/edac_mc.c
@@ -0,0 +1,2209 @@
+/*
+ * 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/version.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..009c08f
--- /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 *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/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/net/Kconfig b/drivers/net/Kconfig
index 1421941..626508a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -7,6 +7,7 @@
 
 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
@@ -1914,6 +1915,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
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 7aa49b9..df9d6e8 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -2136,7 +2136,7 @@
 
 	/* Setup paramaters for syncing RX/TX DMA descriptors */
 	dma_desc_align_mask = ~(dma_desc_align_size - 1);
-	dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
+	dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
 
 	return pci_module_init(&b44_driver);
 }
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 4726722..bf1fd2b 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1,25 +1,25 @@
 /*******************************************************************************
 
-  
+
   Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the 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 
+
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.
-  
+
   You 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 
+  this program; if not, write to the Free Software Foundation, Inc., 59
   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
+
   The full GNU General Public License is included in this distribution in the
   file called LICENSE.
-  
+
   Contact Information:
   Linux NICS <linux.nics@intel.com>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -160,7 +160,7 @@
 
 #define DRV_NAME		"e100"
 #define DRV_EXT		"-NAPI"
-#define DRV_VERSION		"3.4.14-k4"DRV_EXT
+#define DRV_VERSION		"3.5.10-k2"DRV_EXT
 #define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
 #define DRV_COPYRIGHT		"Copyright(c) 1999-2005 Intel Corporation"
 #define PFX			DRV_NAME ": "
@@ -320,7 +320,7 @@
 	cuc_dump_complete       = 0x0000A005,
 	cuc_dump_reset_complete = 0x0000A007,
 };
-		
+
 enum port {
 	software_reset  = 0x0000,
 	selftest        = 0x0001,
@@ -715,10 +715,10 @@
 		ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
 		writeb(ctrl, &nic->csr->eeprom_ctrl_lo);
 		e100_write_flush(nic); udelay(4);
-		
+
 		writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
 		e100_write_flush(nic); udelay(4);
-		
+
 		/* Eeprom drives a dummy zero to EEDO after receiving
 		 * complete address.  Use this to adjust addr_len. */
 		ctrl = readb(&nic->csr->eeprom_ctrl_lo);
@@ -726,7 +726,7 @@
 			*addr_len -= (i - 16);
 			i = 17;
 		}
-		
+
 		data = (data << 1) | (ctrl & eedo ? 1 : 0);
 	}
 
@@ -1170,7 +1170,7 @@
 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
 }
 
-static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 {
 /* *INDENT-OFF* */
 	static struct {
@@ -1213,13 +1213,13 @@
 *  driver can change the algorithm.
 *
 *  INTDELAY - This loads the dead-man timer with its inital value.
-*    When this timer expires the interrupt is asserted, and the 
+*    When this timer expires the interrupt is asserted, and the
 *    timer is reset each time a new packet is received.  (see
 *    BUNDLEMAX below to set the limit on number of chained packets)
 *    The current default is 0x600 or 1536.  Experiments show that
 *    the value should probably stay within the 0x200 - 0x1000.
 *
-*  BUNDLEMAX - 
+*  BUNDLEMAX -
 *    This sets the maximum number of frames that will be bundled.  In
 *    some situations, such as the TCP windowing algorithm, it may be
 *    better to limit the growth of the bundle size than let it go as
@@ -1229,7 +1229,7 @@
 *    an interrupt for every frame received.  If you do not want to put
 *    a limit on the bundle size, set this value to xFFFF.
 *
-*  BUNDLESMALL - 
+*  BUNDLESMALL -
 *    This contains a bit-mask describing the minimum size frame that
 *    will be bundled.  The default masks the lower 7 bits, which means
 *    that any frame less than 128 bytes in length will not be bundled,
@@ -1244,7 +1244,7 @@
 *
 *    The current default is 0xFF80, which masks out the lower 7 bits.
 *    This means that any frame which is x7F (127) bytes or smaller
-*    will cause an immediate interrupt.  Because this value must be a 
+*    will cause an immediate interrupt.  Because this value must be a
 *    bit mask, there are only a few valid values that can be used.  To
 *    turn this feature off, the driver can write the value xFFFF to the
 *    lower word of this instruction (in the same way that the other
@@ -1253,7 +1253,7 @@
 *    standard Ethernet frames are <= 2047 bytes in length.
 *************************************************************************/
 
-/* if you wish to disable the ucode functionality, while maintaining the 
+/* if you wish to disable the ucode functionality, while maintaining the
  * workarounds it provides, set the following defines to:
  * BUNDLESMALL 0
  * BUNDLEMAX 1
@@ -1284,12 +1284,46 @@
 
 		for (i = 0; i < UCODE_SIZE; i++)
 			cb->u.ucode[i] = cpu_to_le32(ucode[i]);
-		cb->command = cpu_to_le16(cb_ucode);
+		cb->command = cpu_to_le16(cb_ucode | cb_el);
 		return;
 	}
 
 noloaducode:
-	cb->command = cpu_to_le16(cb_nop);
+	cb->command = cpu_to_le16(cb_nop | cb_el);
+}
+
+static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb,
+	void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
+{
+	int err = 0, counter = 50;
+	struct cb *cb = nic->cb_to_clean;
+
+	if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode)))
+		DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err);
+
+	/* must restart cuc */
+	nic->cuc_cmd = cuc_start;
+
+	/* wait for completion */
+	e100_write_flush(nic);
+	udelay(10);
+
+	/* wait for possibly (ouch) 500ms */
+	while (!(cb->status & cpu_to_le16(cb_complete))) {
+		msleep(10);
+		if (!--counter) break;
+	}
+
+	/* ack any interupts, something could have been set */
+	writeb(~0, &nic->csr->scb.stat_ack);
+
+	/* if the command failed, or is not OK, notify and return */
+	if (!counter || !(cb->status & cpu_to_le16(cb_ok))) {
+		DPRINTK(PROBE,ERR, "ucode load failed\n");
+		err = -EPERM;
+	}
+
+	return err;
 }
 
 static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
@@ -1357,13 +1391,13 @@
 		mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
 	}
 
-	if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && 
+	if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
 	   (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) {
 		/* enable/disable MDI/MDI-X auto-switching.
 		   MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */
 		if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) ||
-		   (nic->mac == mac_82551_10) || (nic->mii.force_media) || 
-		   !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled)) 
+		   (nic->mac == mac_82551_10) || (nic->mii.force_media) ||
+		   !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))
 			mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0);
 		else
 			mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH);
@@ -1388,7 +1422,7 @@
 		return err;
 	if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
 		return err;
-	if((err = e100_exec_cb(nic, NULL, e100_load_ucode)))
+	if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode)))
 		return err;
 	if((err = e100_exec_cb(nic, NULL, e100_configure)))
 		return err;
@@ -1493,7 +1527,7 @@
 		}
 	}
 
-	
+
 	if(e100_exec_cmd(nic, cuc_dump_reset, 0))
 		DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n");
 }
@@ -1542,10 +1576,10 @@
 	mii_check_link(&nic->mii);
 
 	/* Software generated interrupt to recover from (rare) Rx
-	* allocation failure.
-	* Unfortunately have to use a spinlock to not re-enable interrupts
-	* accidentally, due to hardware that shares a register between the
-	* interrupt mask bit and the SW Interrupt generation bit */
+	 * allocation failure.
+	 * Unfortunately have to use a spinlock to not re-enable interrupts
+	 * accidentally, due to hardware that shares a register between the
+	 * interrupt mask bit and the SW Interrupt generation bit */
 	spin_lock_irq(&nic->cmd_lock);
 	writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
 	spin_unlock_irq(&nic->cmd_lock);
@@ -1830,7 +1864,7 @@
 	struct rx *rx_to_start = NULL;
 
 	/* are we already rnr? then pay attention!!! this ensures that
-	 * the state machine progression never allows a start with a 
+	 * the state machine progression never allows a start with a
 	 * partially cleaned list, avoiding a race between hardware
 	 * and rx_to_clean when in NAPI mode */
 	if(RU_SUSPENDED == nic->ru_running)
@@ -2066,7 +2100,7 @@
 {
 	struct nic *nic = netdev_priv(netdev);
 
-	/* Reset outside of interrupt context, to avoid request_irq 
+	/* Reset outside of interrupt context, to avoid request_irq
 	 * in interrupt context */
 	schedule_work(&nic->tx_timeout_task);
 }
@@ -2313,7 +2347,7 @@
 	struct param_range *rfds = &nic->params.rfds;
 	struct param_range *cbs = &nic->params.cbs;
 
-	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 
+	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 		return -EINVAL;
 
 	if(netif_running(netdev))
@@ -2631,7 +2665,9 @@
 		nic->flags |= wol_magic;
 
 	/* ack any pending wake events, disable PME */
-	pci_enable_wake(pdev, 0, 0);
+	err = pci_enable_wake(pdev, 0, 0);
+	if (err)
+		DPRINTK(PROBE, ERR, "Error clearing wake event\n");
 
 	strcpy(netdev->name, "eth%d");
 	if((err = register_netdev(netdev))) {
@@ -2682,6 +2718,7 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct nic *nic = netdev_priv(netdev);
+	int retval;
 
 	if(netif_running(netdev))
 		e100_down(nic);
@@ -2689,9 +2726,14 @@
 	netif_device_detach(netdev);
 
 	pci_save_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), nic->flags & (wol_magic | e100_asf(nic)));
+	retval = pci_enable_wake(pdev, pci_choose_state(pdev, state),
+	                         nic->flags & (wol_magic | e100_asf(nic)));
+	if (retval)
+		DPRINTK(PROBE,ERR, "Error enabling wake\n");
 	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	if (retval)
+		DPRINTK(PROBE,ERR, "Error %d setting power state\n", retval);
 
 	return 0;
 }
@@ -2700,11 +2742,16 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct nic *nic = netdev_priv(netdev);
+	int retval;
 
-	pci_set_power_state(pdev, PCI_D0);
+	retval = pci_set_power_state(pdev, PCI_D0);
+	if (retval)
+		DPRINTK(PROBE,ERR, "Error waking adapter\n");
 	pci_restore_state(pdev);
 	/* ack any pending wake events, disable PME */
-	pci_enable_wake(pdev, 0, 0);
+	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");
 
@@ -2721,12 +2768,15 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct nic *nic = netdev_priv(netdev);
+	int retval;
 
 #ifdef CONFIG_PM
-	pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+	retval = pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
 #else
-	pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
+	retval = pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
 #endif
+	if (retval)
+		DPRINTK(PROBE,ERR, "Error enabling wake\n");
 }
 
 
@@ -2739,7 +2789,7 @@
 	.suspend =      e100_suspend,
 	.resume =       e100_resume,
 #endif
-	.shutdown =	e100_shutdown,
+	.shutdown =     e100_shutdown,
 };
 
 static int __init e100_init_module(void)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index e02e9ba..27c7730 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -72,10 +72,6 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
-#ifdef CONFIG_E1000_MQ
-#include <linux/cpu.h>
-#include <linux/smp.h>
-#endif
 
 #define BAR_0		0
 #define BAR_1		1
@@ -87,6 +83,10 @@
 struct e1000_adapter;
 
 #include "e1000_hw.h"
+#ifdef CONFIG_E1000_MQ
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#endif
 
 #ifdef DBG
 #define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
@@ -169,6 +169,13 @@
 	uint16_t next_to_watch;
 };
 
+#ifdef CONFIG_E1000_MQ
+struct e1000_queue_stats {
+	uint64_t packets;
+	uint64_t bytes;
+};
+#endif
+
 struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
 struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
 
@@ -191,10 +198,12 @@
 	spinlock_t tx_lock;
 	uint16_t tdh;
 	uint16_t tdt;
-	uint64_t pkt;
 
 	boolean_t last_tx_tso;
 
+#ifdef CONFIG_E1000_MQ
+	struct e1000_queue_stats tx_stats;
+#endif
 };
 
 struct e1000_rx_ring {
@@ -216,9 +225,17 @@
 	struct e1000_ps_page *ps_page;
 	struct e1000_ps_page_dma *ps_page_dma;
 
+	struct sk_buff *rx_skb_top;
+	struct sk_buff *rx_skb_prev;
+
+	/* cpu for rx queue */
+	int cpu;
+
 	uint16_t rdh;
 	uint16_t rdt;
-	uint64_t pkt;
+#ifdef CONFIG_E1000_MQ
+	struct e1000_queue_stats rx_stats;
+#endif
 };
 
 #define E1000_DESC_UNUSED(R) \
@@ -251,6 +268,9 @@
 	uint16_t link_speed;
 	uint16_t link_duplex;
 	spinlock_t stats_lock;
+#ifdef CONFIG_E1000_NAPI
+	spinlock_t tx_queue_lock;
+#endif
 	atomic_t irq_sem;
 	struct work_struct tx_timeout_task;
 	struct work_struct watchdog_task;
@@ -264,6 +284,7 @@
 #ifdef CONFIG_E1000_MQ
 	struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
 #endif
+	unsigned long tx_queue_len;
 	uint32_t txd_cmd;
 	uint32_t tx_int_delay;
 	uint32_t tx_abs_int_delay;
@@ -271,9 +292,11 @@
 	uint64_t gotcl_old;
 	uint64_t tpt_old;
 	uint64_t colc_old;
+	uint32_t tx_timeout_count;
 	uint32_t tx_fifo_head;
 	uint32_t tx_head_addr;
 	uint32_t tx_fifo_size;
+	uint8_t  tx_timeout_factor;
 	atomic_t tx_fifo_stall;
 	boolean_t pcix_82544;
 	boolean_t detect_tx_hung;
@@ -281,14 +304,15 @@
 	/* RX */
 #ifdef CONFIG_E1000_NAPI
 	boolean_t (*clean_rx) (struct e1000_adapter *adapter,
-			       struct e1000_rx_ring *rx_ring,
-			       int *work_done, int work_to_do);
+						   struct e1000_rx_ring *rx_ring,
+						   int *work_done, int work_to_do);
 #else
 	boolean_t (*clean_rx) (struct e1000_adapter *adapter,
-			       struct e1000_rx_ring *rx_ring);
+						   struct e1000_rx_ring *rx_ring);
 #endif
 	void (*alloc_rx_buf) (struct e1000_adapter *adapter,
-			      struct e1000_rx_ring *rx_ring);
+						  struct e1000_rx_ring *rx_ring,
+						  int cleaned_count);
 	struct e1000_rx_ring *rx_ring;      /* One per active queue */
 #ifdef CONFIG_E1000_NAPI
 	struct net_device *polling_netdev;  /* One per active queue */
@@ -296,13 +320,15 @@
 #ifdef CONFIG_E1000_MQ
 	struct net_device **cpu_netdev;     /* per-cpu */
 	struct call_async_data_struct rx_sched_call_data;
-	int cpu_for_queue[4];
+	cpumask_t cpumask;
 #endif
-	int num_queues;
+	int num_tx_queues;
+	int num_rx_queues;
 
 	uint64_t hw_csum_err;
 	uint64_t hw_csum_good;
 	uint64_t rx_hdr_split;
+	uint32_t alloc_rx_buff_failed;
 	uint32_t rx_int_delay;
 	uint32_t rx_abs_int_delay;
 	boolean_t rx_csum;
@@ -330,6 +356,7 @@
 	struct e1000_rx_ring test_rx_ring;
 
 
+	u32 *config_space;
 	int msg_enable;
 #ifdef CONFIG_PCI_MSI
 	boolean_t have_msi;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index c88f1a3..5cedc81 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -80,6 +80,7 @@
 	{ "tx_deferred_ok", E1000_STAT(stats.dc) },
 	{ "tx_single_coll_ok", E1000_STAT(stats.scc) },
 	{ "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
+	{ "tx_timeout_count", E1000_STAT(tx_timeout_count) },
 	{ "rx_long_length_errors", E1000_STAT(stats.roc) },
 	{ "rx_short_length_errors", E1000_STAT(stats.ruc) },
 	{ "rx_align_errors", E1000_STAT(stats.algnerrc) },
@@ -93,9 +94,20 @@
 	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
 	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
 	{ "rx_header_split", E1000_STAT(rx_hdr_split) },
+	{ "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
 };
-#define E1000_STATS_LEN	\
+
+#ifdef CONFIG_E1000_MQ
+#define E1000_QUEUE_STATS_LEN \
+	(((struct e1000_adapter *)netdev->priv)->num_tx_queues + \
+	 ((struct e1000_adapter *)netdev->priv)->num_rx_queues) \
+	* (sizeof(struct e1000_queue_stats) / sizeof(uint64_t))
+#else
+#define E1000_QUEUE_STATS_LEN 0
+#endif
+#define E1000_GLOBAL_STATS_LEN	\
 	sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
+#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN)
 static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
 	"Register test  (offline)", "Eeprom test    (offline)",
 	"Interrupt test (offline)", "Loopback test  (offline)",
@@ -109,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 |
@@ -121,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 */
@@ -132,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;
@@ -148,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);
@@ -163,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;
@@ -183,13 +195,21 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
-	if(ecmd->autoneg == AUTONEG_ENABLE) {
+	/* When SoL/IDER sessions are active, autoneg/speed/duplex
+	 * cannot be changed */
+	if (e1000_check_phy_reset_block(hw)) {
+		DPRINTK(DRV, ERR, "Cannot change link characteristics "
+		        "when SoL/IDER is active.\n");
+		return -EINVAL;
+	}
+
+	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 |
@@ -199,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);
@@ -221,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;
 	}
@@ -240,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;
 }
 
@@ -281,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)
 {
@@ -300,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;
@@ -319,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)
@@ -328,7 +347,7 @@
 	else
 		netdev->features &= ~NETIF_F_TSO;
 	return 0;
-} 
+}
 #endif /* NETIF_F_TSO */
 
 static uint32_t
@@ -345,7 +364,7 @@
 	adapter->msg_enable = data;
 }
 
-static int 
+static int
 e1000_get_regs_len(struct net_device *netdev)
 {
 #define E1000_REGS_LEN 32
@@ -381,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 &
@@ -435,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);
 	}
@@ -459,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);
@@ -469,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;
 	}
@@ -505,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;
@@ -516,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,
@@ -547,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);
 
@@ -567,21 +586,21 @@
 
 	strncpy(drvinfo->driver,  e1000_driver_name, 32);
 	strncpy(drvinfo->version, e1000_driver_version, 32);
-	
-	/* EEPROM image version # is reported as firware version # for
+
+	/* EEPROM image version # is reported as firmware version # for
 	 * 8257{1|2|3} controllers */
 	e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
 	switch (adapter->hw.mac_type) {
 	case e1000_82571:
 	case e1000_82572:
 	case e1000_82573:
-		sprintf(firmware_version, "%d.%d-%d", 
+		sprintf(firmware_version, "%d.%d-%d",
 			(eeprom_data & 0xF000) >> 12,
 			(eeprom_data & 0x0FF0) >> 4,
 			eeprom_data & 0x000F);
 		break;
 	default:
-		sprintf(firmware_version, "n/a");
+		sprintf(firmware_version, "N/A");
 	}
 
 	strncpy(drvinfo->fw_version, firmware_version, 32);
@@ -613,7 +632,7 @@
 	ring->rx_jumbo_pending = 0;
 }
 
-static int 
+static int
 e1000_set_ringparam(struct net_device *netdev,
                     struct ethtool_ringparam *ring)
 {
@@ -623,8 +642,8 @@
 	struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
 	int i, err, tx_ring_size, rx_ring_size;
 
-	tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
-	rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+	tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
+	rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
 
 	if (netif_running(adapter->netdev))
 		e1000_down(adapter);
@@ -650,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_queues; i++) {
+	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;
@@ -688,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;
 	}
 
@@ -707,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));        \
@@ -726,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) ?                 \
@@ -762,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;
@@ -790,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);
@@ -798,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,
@@ -814,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;
@@ -830,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;
 		}
@@ -839,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;
@@ -868,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;
@@ -881,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
@@ -897,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;
  			}
@@ -915,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
@@ -932,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;
 			}
@@ -957,40 +976,39 @@
 	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);
 		}
 	}
 
-	if(txdr->desc) {
+	if (txdr->desc) {
 		pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
 		txdr->desc = NULL;
 	}
-	if(rxdr->desc) {
+	if (rxdr->desc) {
 		pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
 		rxdr->desc = NULL;
 	}
 
 	kfree(txdr->buffer_info);
 	txdr->buffer_info = NULL;
-
 	kfree(rxdr->buffer_info);
 	rxdr->buffer_info = NULL;
 
@@ -1008,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;
 	}
@@ -1020,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;
 	}
@@ -1039,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;
 		}
@@ -1064,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;
 	}
@@ -1095,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;
@@ -1208,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;
@@ -1230,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);
@@ -1250,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);
 	}
 
@@ -1266,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);
@@ -1282,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;
@@ -1327,11 +1345,11 @@
 static int
 e1000_setup_loopback_test(struct e1000_adapter *adapter)
 {
-	uint32_t rctl;
 	struct e1000_hw *hw = &adapter->hw;
+	uint32_t rctl;
 
 	if (hw->media_type == e1000_media_type_fiber ||
-	   hw->media_type == e1000_media_type_internal_serdes) {
+	    hw->media_type == e1000_media_type_internal_serdes) {
 		switch (hw->mac_type) {
 		case e1000_82545:
 		case e1000_82546:
@@ -1362,25 +1380,25 @@
 static void
 e1000_loopback_cleanup(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	uint32_t rctl;
 	uint16_t phy_reg;
-	struct e1000_hw *hw = &adapter->hw;
 
-	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+	rctl = E1000_READ_REG(hw, RCTL);
 	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
-	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+	E1000_WRITE_REG(hw, RCTL, rctl);
 
 	switch (hw->mac_type) {
 	case e1000_82571:
 	case e1000_82572:
 		if (hw->media_type == e1000_media_type_fiber ||
-		   hw->media_type == e1000_media_type_internal_serdes){
+		    hw->media_type == e1000_media_type_internal_serdes) {
 #define E1000_SERDES_LB_OFF 0x400
 			E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
 			msec_delay(10);
 			break;
 		}
-		/* fall thru for Cu adapters */
+		/* Fall Through */
 	case e1000_82545:
 	case e1000_82546:
 	case e1000_82545_rev_3:
@@ -1401,7 +1419,7 @@
 e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
 {
 	memset(skb->data, 0xFF, frame_size);
-	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
+	frame_size &= ~1;
 	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
 	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
 	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
@@ -1410,9 +1428,9 @@
 static int
 e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
 {
-	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
-	if(*(skb->data + 3) == 0xFF) {
-		if((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
+	frame_size &= ~1;
+	if (*(skb->data + 3) == 0xFF) {
+		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
 		   (*(skb->data + frame_size / 2 + 12) == 0xAF)) {
 			return 0;
 		}
@@ -1431,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;
 		}
@@ -1488,14 +1506,25 @@
 static int
 e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
 {
-	if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
-	if((*data = e1000_setup_loopback_test(adapter)))
-		goto err_loopback_setup;
+	/* PHY loopback cannot be performed if SoL/IDER
+	 * sessions are active */
+	if (e1000_check_phy_reset_block(&adapter->hw)) {
+		DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
+		        "when SoL/IDER is active.\n");
+		*data = 0;
+		goto out;
+	}
+
+	if ((*data = e1000_setup_desc_rings(adapter)))
+		goto out;
+	if ((*data = e1000_setup_loopback_test(adapter)))
+		goto err_loopback;
 	*data = e1000_run_loopback_test(adapter);
 	e1000_loopback_cleanup(adapter);
-err_loopback_setup:
-	e1000_free_desc_rings(adapter);
+
 err_loopback:
+	e1000_free_desc_rings(adapter);
+out:
 	return *data;
 }
 
@@ -1519,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;
@@ -1542,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 */
@@ -1552,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 */
@@ -1581,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 */
@@ -1603,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:
@@ -1617,8 +1646,9 @@
 
 	case E1000_DEV_ID_82546EB_FIBER:
 	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;
@@ -1630,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;
 	}
@@ -1648,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:
@@ -1660,24 +1690,25 @@
 
 	case E1000_DEV_ID_82546EB_FIBER:
 	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;
 	}
 
@@ -1695,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);
@@ -1708,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;
@@ -1721,21 +1752,21 @@
 		mod_timer(&adapter->blink_timer, jiffies);
 		msleep_interruptible(data * 1000);
 		del_timer_sync(&adapter->blink_timer);
-	}
-	else if(adapter->hw.mac_type < e1000_82573) {
-		E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
-			E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
-			(E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
-			(E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
-			(E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+	} else if (adapter->hw.mac_type < e1000_82573) {
+		E1000_WRITE_REG(&adapter->hw, LEDCTL,
+			(E1000_LEDCTL_LED2_BLINK_RATE |
+			 E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
+			 (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+			 (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
+			 (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
 		msleep_interruptible(data * 1000);
-	}
-	else {
-		E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
-			E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK | 
-			(E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
-			(E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
-			(E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
+	} else {
+		E1000_WRITE_REG(&adapter->hw, LEDCTL,
+			(E1000_LEDCTL_LED2_BLINK_RATE |
+			 E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
+			 (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+			 (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
+			 (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
 		msleep_interruptible(data * 1000);
 	}
 
@@ -1750,50 +1781,89 @@
 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);
+#ifdef CONFIG_E1000_MQ
+	uint64_t *queue_stat;
+	int stat_count = sizeof(struct e1000_queue_stats) / sizeof(uint64_t);
+	int j, k;
+#endif
 	int i;
 
 	e1000_update_stats(adapter);
-	for(i = 0; i < E1000_STATS_LEN; i++) {
-		char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;	
-		data[i] = (e1000_gstrings_stats[i].sizeof_stat == 
+	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+		char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
+		data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
 			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
 	}
+#ifdef CONFIG_E1000_MQ
+	for (j = 0; j < adapter->num_tx_queues; j++) {
+		queue_stat = (uint64_t *)&adapter->tx_ring[j].tx_stats;
+		for (k = 0; k < stat_count; k++)
+			data[i + k] = queue_stat[k];
+		i += k;
+	}
+	for (j = 0; j < adapter->num_rx_queues; j++) {
+		queue_stat = (uint64_t *)&adapter->rx_ring[j].rx_stats;
+		for (k = 0; k < stat_count; k++)
+			data[i + k] = queue_stat[k];
+		i += k;
+	}
+#endif
+/*	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
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+#endif
+	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:
-		for (i=0; i < E1000_STATS_LEN; i++) {
-			memcpy(data + i * ETH_GSTRING_LEN, 
-			e1000_gstrings_stats[i].stat_string,
-			ETH_GSTRING_LEN);
+		for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+			memcpy(p, e1000_gstrings_stats[i].stat_string,
+			       ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
 		}
+#ifdef CONFIG_E1000_MQ
+		for (i = 0; i < adapter->num_tx_queues; i++) {
+			sprintf(p, "tx_queue_%u_packets", i);
+			p += ETH_GSTRING_LEN;
+			sprintf(p, "tx_queue_%u_bytes", i);
+			p += ETH_GSTRING_LEN;
+		}
+		for (i = 0; i < adapter->num_rx_queues; i++) {
+			sprintf(p, "rx_queue_%u_packets", i);
+			p += ETH_GSTRING_LEN;
+			sprintf(p, "rx_queue_%u_bytes", i);
+			p += ETH_GSTRING_LEN;
+		}
+#endif
+/*		BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */
 		break;
 	}
 }
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 136fc03..beeec0f 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -318,6 +318,8 @@
     case E1000_DEV_ID_82546GB_FIBER:
     case E1000_DEV_ID_82546GB_SERDES:
     case E1000_DEV_ID_82546GB_PCIE:
+    case E1000_DEV_ID_82546GB_QUAD_COPPER:
+    case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
         hw->mac_type = e1000_82546_rev_3;
         break;
     case E1000_DEV_ID_82541EI:
@@ -639,6 +641,7 @@
     uint16_t cmd_mmrbc;
     uint16_t stat_mmrbc;
     uint32_t mta_size;
+    uint32_t ctrl_ext;
 
     DEBUGFUNC("e1000_init_hw");
 
@@ -735,7 +738,6 @@
             break;
         case e1000_82571:
         case e1000_82572:
-            ctrl |= (1 << 22);
         case e1000_82573:
             ctrl |= E1000_TXDCTL_COUNT_DESC;
             break;
@@ -775,6 +777,15 @@
      */
     e1000_clear_hw_cntrs(hw);
 
+    if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
+        hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
+        ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+        /* Relaxed ordering must be disabled to avoid a parity
+         * error crash in a PCI slot. */
+        ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+    }
+
     return ret_val;
 }
 
@@ -838,6 +849,11 @@
 
     DEBUGFUNC("e1000_setup_link");
 
+    /* In the case of the phy reset being blocked, we already have a link.
+     * We do not have to set it up again. */
+    if (e1000_check_phy_reset_block(hw))
+        return E1000_SUCCESS;
+
     /* Read and store word 0x0F of the EEPROM. This word contains bits
      * that determine the hardware's default PAUSE (flow control) mode,
      * a bit that determines whether the HW defaults to enabling or
@@ -1584,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
@@ -1929,14 +1945,19 @@
 void
 e1000_config_collision_dist(struct e1000_hw *hw)
 {
-    uint32_t tctl;
+    uint32_t tctl, coll_dist;
 
     DEBUGFUNC("e1000_config_collision_dist");
 
+    if (hw->mac_type < e1000_82543)
+        coll_dist = E1000_COLLISION_DISTANCE_82542;
+    else
+        coll_dist = E1000_COLLISION_DISTANCE;
+
     tctl = E1000_READ_REG(hw, TCTL);
 
     tctl &= ~E1000_TCTL_COLD;
-    tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+    tctl |= coll_dist << E1000_COLD_SHIFT;
 
     E1000_WRITE_REG(hw, TCTL, tctl);
     E1000_WRITE_FLUSH(hw);
@@ -2982,6 +3003,8 @@
         
         if (hw->mac_type < e1000_82571) 
             msec_delay(10);
+        else
+            udelay(100);
         
         E1000_WRITE_REG(hw, CTRL, ctrl);
         E1000_WRITE_FLUSH(hw);
@@ -3881,17 +3904,19 @@
         return -E1000_ERR_EEPROM;
     }
 
-    /* FLASH reads without acquiring the semaphore are safe in 82573-based
-     * controllers.
-     */
-    if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
-        (hw->mac_type != e1000_82573)) {
-        /* Prepare the EEPROM for reading  */
-        if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
-            return -E1000_ERR_EEPROM;
+    /* FLASH reads without acquiring the semaphore are safe */
+    if (e1000_is_onboard_nvm_eeprom(hw) == TRUE &&
+    hw->eeprom.use_eerd == FALSE) {
+        switch (hw->mac_type) {
+        default:
+            /* Prepare the EEPROM for reading  */
+            if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+                return -E1000_ERR_EEPROM;
+            break;
+        }
     }
 
-    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))
@@ -4398,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);
         }
@@ -4406,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;
@@ -4479,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;
@@ -6720,6 +6746,12 @@
         break;
     }
 
+    /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
+     * Need to wait for PHY configuration completion before accessing NVM
+     * and PHY. */
+    if (hw->mac_type == e1000_82573)
+        msec_delay(25);
+
     return E1000_SUCCESS;
 }
 
@@ -6809,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 7caa357..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);
@@ -439,6 +442,7 @@
 #define E1000_DEV_ID_82546GB_FIBER       0x107A
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82546GB_PCIE        0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
 #define E1000_DEV_ID_82547EI             0x1019
 #define E1000_DEV_ID_82571EB_COPPER      0x105E
 #define E1000_DEV_ID_82571EB_FIBER       0x105F
@@ -449,6 +453,7 @@
 #define E1000_DEV_ID_82573E              0x108B
 #define E1000_DEV_ID_82573E_IAMT         0x108C
 #define E1000_DEV_ID_82573L              0x109A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
 
 
 #define NODE_ADDRESS_SIZE 6
@@ -897,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 */
@@ -1497,6 +1502,7 @@
 #define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
 #define E1000_CTRL_EXT_IPS       0x00004000 /* Invert Power State */
 #define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
 #define E1000_CTRL_EXT_LINK_MODE_TBI  0x00C00000
@@ -1758,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 */
@@ -1954,6 +1959,23 @@
 
 #define E1000_MDALIGN          4096
 
+/* PCI-Ex registers */
+
+/* PCI-Ex Control Register */
+#define E1000_GCR_RXD_NO_SNOOP			0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP		0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP		0x00000004
+#define E1000_GCR_TXD_NO_SNOOP			0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP		0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP		0x00000020
+
+#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP		| \
+							 E1000_GCR_RXDSCW_NO_SNOOP	| \
+							 E1000_GCR_RXDSCR_NO_SNOOP	| \
+							 E1000_GCR TXD_NO_SNOOP		| \
+							 E1000_GCR_TXDSCW_NO_SNOOP	| \
+							 E1000_GCR_TXDSCR_NO_SNOOP)
+
 #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
 /* Function Active and Power State to MNG */
 #define E1000_FACTPS_FUNC0_POWER_STATE_MASK         0x00000003
@@ -2077,7 +2099,10 @@
 /* Collision related configuration parameters */
 #define E1000_COLLISION_THRESHOLD       15
 #define E1000_CT_SHIFT                  4
-#define E1000_COLLISION_DISTANCE        64
+/* Collision distance is a 0-based value that applies to
+ * half-duplex-capable hardware only. */
+#define E1000_COLLISION_DISTANCE        63
+#define E1000_COLLISION_DISTANCE_82542  64
 #define E1000_FDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
 #define E1000_HDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
 #define E1000_COLD_SHIFT                12
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 438a931..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";
@@ -43,7 +103,7 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
+#define DRV_VERSION "6.3.9-k2"DRIVERNAPI
 char e1000_driver_version[] = DRV_VERSION;
 static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 
@@ -97,7 +157,9 @@
 	INTEL_E1000_ETHERNET_DEVICE(0x108A),
 	INTEL_E1000_ETHERNET_DEVICE(0x108B),
 	INTEL_E1000_ETHERNET_DEVICE(0x108C),
+	INTEL_E1000_ETHERNET_DEVICE(0x1099),
 	INTEL_E1000_ETHERNET_DEVICE(0x109A),
+	INTEL_E1000_ETHERNET_DEVICE(0x10B5),
 	/* required last entry */
 	{0,}
 };
@@ -171,9 +233,11 @@
                                        struct e1000_rx_ring *rx_ring);
 #endif
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
-                                   struct e1000_rx_ring *rx_ring);
+                                   struct e1000_rx_ring *rx_ring,
+				   int cleaned_count);
 static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
-                                      struct e1000_rx_ring *rx_ring);
+                                      struct e1000_rx_ring *rx_ring,
+				      int cleaned_count);
 static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
 static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
 			   int cmd);
@@ -291,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);
 	}
@@ -303,23 +367,91 @@
 	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);
 		}
 	}
 }
-	
+
+/**
+ * e1000_release_hw_control - release control of the h/w to f/w
+ * @adapter: address of board private structure
+ *
+ * e1000_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit.
+ * For ASF and Pass Through versions of f/w this means that the
+ * driver is no longer loaded. For AMT version (only with 82573) i
+ * of the f/w this means that the netowrk i/f is closed.
+ * 
+ **/
+
+static inline void 
+e1000_release_hw_control(struct e1000_adapter *adapter)
+{
+	uint32_t ctrl_ext;
+	uint32_t swsm;
+
+	/* Let firmware taken over control of h/w */
+	switch (adapter->hw.mac_type) {
+	case e1000_82571:
+	case e1000_82572:
+		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+				ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+		break;
+	case e1000_82573:
+		swsm = E1000_READ_REG(&adapter->hw, SWSM);
+		E1000_WRITE_REG(&adapter->hw, SWSM,
+				swsm & ~E1000_SWSM_DRV_LOAD);
+	default:
+		break;
+	}
+}
+
+/**
+ * e1000_get_hw_control - get control of the h/w from f/w
+ * @adapter: address of board private structure
+ *
+ * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit.
+ * For ASF and Pass Through versions of f/w this means that 
+ * the driver is loaded. For AMT version (only with 82573) 
+ * of the f/w this means that the netowrk i/f is open.
+ * 
+ **/
+
+static inline void 
+e1000_get_hw_control(struct e1000_adapter *adapter)
+{
+	uint32_t ctrl_ext;
+	uint32_t swsm;
+	/* Let firmware know the driver has taken over */
+	switch (adapter->hw.mac_type) {
+	case e1000_82571:
+	case e1000_82572:
+		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+				ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+		break;
+	case e1000_82573:
+		swsm = E1000_READ_REG(&adapter->hw, SWSM);
+		E1000_WRITE_REG(&adapter->hw, SWSM,
+				swsm | E1000_SWSM_DRV_LOAD);
+		break;
+	default:
+		break;
+	}
+}
+
 int
 e1000_up(struct e1000_adapter *adapter)
 {
@@ -329,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);
 	}
 
@@ -343,20 +475,26 @@
 	e1000_configure_tx(adapter);
 	e1000_setup_rctl(adapter);
 	e1000_configure_rx(adapter);
-	for (i = 0; i < adapter->num_queues; i++)
-		adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
+	/* call E1000_DESC_UNUSED which always leaves
+	 * at least 1 descriptor unused to make sure
+	 * next_to_use != next_to_clean */
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		struct e1000_rx_ring *ring = &adapter->rx_ring[i];
+		adapter->alloc_rx_buf(adapter, ring,
+		                      E1000_DESC_UNUSED(ring));
+	}
 
 #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,
@@ -364,6 +502,12 @@
 		return err;
 	}
 
+#ifdef CONFIG_E1000_MQ
+	e1000_setup_queue_mapping(adapter);
+#endif
+
+	adapter->tx_queue_len = netdev->tx_queue_len;
+
 	mod_timer(&adapter->watchdog_timer, jiffies);
 
 #ifdef CONFIG_E1000_NAPI
@@ -378,6 +522,8 @@
 e1000_down(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
+	boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) &&
+				     e1000_check_mng_mode(&adapter->hw);
 
 	e1000_irq_disable(adapter);
 #ifdef CONFIG_E1000_MQ
@@ -385,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
@@ -396,6 +542,7 @@
 #ifdef CONFIG_E1000_NAPI
 	netif_poll_disable(netdev);
 #endif
+	netdev->tx_queue_len = adapter->tx_queue_len;
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 	netif_carrier_off(netdev);
@@ -405,12 +552,16 @@
 	e1000_clean_all_tx_rings(adapter);
 	e1000_clean_all_rx_rings(adapter);
 
-	/* If WoL is not enabled and management mode is not IAMT
-	 * Power down the PHY so no link is implied when interface is down */
-	if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
+	/* Power down the PHY so no link is implied when interface is down *
+	 * The PHY cannot be powered down if any of the following is TRUE *
+	 * (a) WoL is enabled
+	 * (b) AMT is active
+	 * (c) SoL/IDER session is active */
+	if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
 	   adapter->hw.media_type == e1000_media_type_copper &&
-	   !e1000_check_mng_mode(&adapter->hw) &&
-	   !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) {
+	   !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) &&
+	   !mng_mode_enabled &&
+	   !e1000_check_phy_reset_block(&adapter->hw)) {
 		uint16_t mii_reg;
 		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
 		mii_reg |= MII_CR_POWER_DOWN;
@@ -422,10 +573,8 @@
 void
 e1000_reset(struct e1000_adapter *adapter)
 {
-	struct net_device *netdev = adapter->netdev;
 	uint32_t pba, manc;
 	uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
-	uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF;
 
 	/* Repartition Pba for greater than 9k mtu
 	 * To take effect CTRL.RST is required.
@@ -448,19 +597,12 @@
 		break;
 	}
 
-	if((adapter->hw.mac_type != e1000_82573) &&
-	   (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) {
+	if ((adapter->hw.mac_type != e1000_82573) &&
+	   (adapter->netdev->mtu > E1000_RXBUFFER_8192))
 		pba -= 8; /* allocate more FIFO for Tx */
-		/* send an XOFF when there is enough space in the
-		 * Rx FIFO to hold one extra full size Rx packet 
-		*/
-		fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE + 
-					ETHERNET_FCS_SIZE + 1;
-		fc_low_water_mark = fc_high_water_mark + 8;
-	}
 
 
-	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 =
@@ -471,19 +613,21 @@
 	E1000_WRITE_REG(&adapter->hw, PBA, pba);
 
 	/* flow control settings */
-	adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) -
-				    fc_high_water_mark;
-	adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) -
-				   fc_low_water_mark;
+	/* Set the FC high water mark to 90% of the FIFO size.
+	 * Required to clear last 3 LSB */
+	fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;
+
+	adapter->hw.fc_high_water = fc_high_water_mark;
+	adapter->hw.fc_low_water = fc_high_water_mark - 8;
 	adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
 	adapter->hw.fc_send_xon = 1;
 	adapter->hw.fc = adapter->hw.original_fc;
 
 	/* 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 */
@@ -517,33 +661,31 @@
 	struct net_device *netdev;
 	struct e1000_adapter *adapter;
 	unsigned long mmio_start, mmio_len;
-	uint32_t ctrl_ext;
-	uint32_t swsm;
 
 	static int cards_found = 0;
 	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;
 	}
@@ -562,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;
 		}
@@ -607,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 |
@@ -622,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 */
@@ -639,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;
@@ -654,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;
@@ -699,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:
@@ -712,8 +854,7 @@
 	case e1000_82546:
 	case e1000_82546_rev_3:
 	case e1000_82571:
-		if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
-		   && (adapter->hw.media_type == e1000_media_type_copper)) {
+		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;
@@ -724,31 +865,42 @@
 			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 */
+	{
+	struct e1000_hw *hw = &adapter->hw;
+	DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
+		((hw->bus_type == e1000_bus_type_pcix) ? "-X" :
+		 (hw->bus_type == e1000_bus_type_pci_express ? " Express":"")),
+		((hw->bus_speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
+		 (hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
+		 (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
+		 (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
+		 (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
+		((hw->bus_width == e1000_bus_width_64) ? "64-bit" :
+		 (hw->bus_width == e1000_bus_width_pciex_4) ? "Width x4" :
+		 (hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
+		 "32-bit"));
+	}
+
+	for (i = 0; i < 6; i++)
+		printk("%2.2x%c", netdev->dev_addr[i], i == 5 ? '\n' : ':');
+
 	/* reset the hardware with the new settings */
 	e1000_reset(adapter);
 
-	/* Let firmware know the driver has taken over */
-	switch(adapter->hw.mac_type) {
-	case e1000_82571:
-	case e1000_82572:
-		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
-		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
-				ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
-		break;
-	case e1000_82573:
-		swsm = E1000_READ_REG(&adapter->hw, SWSM);
-		E1000_WRITE_REG(&adapter->hw, SWSM,
-				swsm | E1000_SWSM_DRV_LOAD);
-		break;
-	default:
-		break;
-	}
+	/* If the controller is 82573 and f/w is AMT, do not set
+	 * DRV_LOAD until the interface is up.  For all other cases,
+	 * let the f/w know that the h/w is now under the control
+	 * of the driver. */
+	if (adapter->hw.mac_type != e1000_82573 ||
+	    !e1000_check_mng_mode(&adapter->hw))
+		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");
@@ -782,47 +934,33 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	uint32_t ctrl_ext;
-	uint32_t manc, swsm;
+	uint32_t manc;
 #ifdef CONFIG_E1000_NAPI
 	int i;
 #endif
 
 	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);
 		}
 	}
 
-	switch(adapter->hw.mac_type) {
-	case e1000_82571:
-	case e1000_82572:
-		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
-		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
-				ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
-		break;
-	case e1000_82573:
-		swsm = E1000_READ_REG(&adapter->hw, SWSM);
-		E1000_WRITE_REG(&adapter->hw, SWSM,
-				swsm & ~E1000_SWSM_DRV_LOAD);
-		break;
-
-	default:
-		break;
-	}
+	/* Release control of h/w to f/w.  If f/w is AMT enabled, this
+	 * would have already happened in close and is redundant. */
+	e1000_release_hw_control(adapter);
 
 	unregister_netdev(netdev);
 #ifdef CONFIG_E1000_NAPI
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_rx_queues; i++)
 		__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);
@@ -881,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:
@@ -912,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;
@@ -923,15 +1061,34 @@
 	switch (hw->mac_type) {
 	case e1000_82571:
 	case e1000_82572:
-		adapter->num_queues = 2;
+		/* These controllers support 2 tx queues, but with a single
+		 * qdisc implementation, multiple tx queues aren't quite as
+		 * interesting.  If we can find a logical way of mapping
+		 * flows to a queue, then perhaps we can up the num_tx_queue
+		 * count back to its default.  Until then, we run the risk of
+		 * terrible performance due to SACK overload. */
+		adapter->num_tx_queues = 1;
+		adapter->num_rx_queues = 2;
 		break;
 	default:
-		adapter->num_queues = 1;
+		adapter->num_tx_queues = 1;
+		adapter->num_rx_queues = 1;
 		break;
 	}
-	adapter->num_queues = min(adapter->num_queues, num_online_cpus());
+	adapter->num_rx_queues = min(adapter->num_rx_queues, num_online_cpus());
+	adapter->num_tx_queues = min(adapter->num_tx_queues, num_online_cpus());
+	DPRINTK(DRV, INFO, "Multiqueue Enabled: Rx Queue count = %u %s\n",
+		adapter->num_rx_queues,
+		((adapter->num_rx_queues == 1)
+		 ? ((num_online_cpus() > 1)
+			? "(due to unsupported feature in current adapter)"
+			: "(due to unsupported system configuration)")
+		 : ""));
+	DPRINTK(DRV, INFO, "Multiqueue Enabled: Tx Queue count = %u\n",
+		adapter->num_tx_queues);
 #else
-	adapter->num_queues = 1;
+	adapter->num_tx_queues = 1;
+	adapter->num_rx_queues = 1;
 #endif
 
 	if (e1000_alloc_queues(adapter)) {
@@ -940,17 +1097,14 @@
 	}
 
 #ifdef CONFIG_E1000_NAPI
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_rx_queues; i++) {
 		adapter->polling_netdev[i].priv = adapter;
 		adapter->polling_netdev[i].poll = &e1000_clean;
 		adapter->polling_netdev[i].weight = 64;
 		dev_hold(&adapter->polling_netdev[i]);
 		set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
 	}
-#endif
-
-#ifdef CONFIG_E1000_MQ
-	e1000_setup_queue_mapping(adapter);
+	spin_lock_init(&adapter->tx_queue_lock);
 #endif
 
 	atomic_set(&adapter->irq_sem, 1);
@@ -973,13 +1127,13 @@
 {
 	int size;
 
-	size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+	size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
 	adapter->tx_ring = kmalloc(size, GFP_KERNEL);
 	if (!adapter->tx_ring)
 		return -ENOMEM;
 	memset(adapter->tx_ring, 0, size);
 
-	size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+	size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
 	adapter->rx_ring = kmalloc(size, GFP_KERNEL);
 	if (!adapter->rx_ring) {
 		kfree(adapter->tx_ring);
@@ -988,7 +1142,7 @@
 	memset(adapter->rx_ring, 0, size);
 
 #ifdef CONFIG_E1000_NAPI
-	size = sizeof(struct net_device) * adapter->num_queues;
+	size = sizeof(struct net_device) * adapter->num_rx_queues;
 	adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
 	if (!adapter->polling_netdev) {
 		kfree(adapter->tx_ring);
@@ -998,6 +1152,14 @@
 	memset(adapter->polling_netdev, 0, size);
 #endif
 
+#ifdef CONFIG_E1000_MQ
+	adapter->rx_sched_call_data.func = e1000_rx_schedule;
+	adapter->rx_sched_call_data.info = adapter->netdev;
+
+	adapter->cpu_netdev = alloc_percpu(struct net_device *);
+	adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
+#endif
+
 	return E1000_SUCCESS;
 }
 
@@ -1017,14 +1179,15 @@
 	lock_cpu_hotplug();
 	i = 0;
 	for_each_online_cpu(cpu) {
-		*per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_queues];
+		*per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_tx_queues];
 		/* This is incomplete because we'd like to assign separate
 		 * physical cpus to these netdev polling structures and
 		 * avoid saturating a subset of cpus.
 		 */
-		if (i < adapter->num_queues) {
+		if (i < adapter->num_rx_queues) {
 			*per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
-			adapter->cpu_for_queue[i] = cpu;
+			adapter->rx_ring[i].cpu = cpu;
+			cpu_set(cpu, adapter->cpumask);
 		} else
 			*per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
 
@@ -1063,14 +1226,20 @@
 	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);
 	}
 
+	/* If AMT is enabled, let the firmware know that the network
+	 * interface is now open */
+	if (adapter->hw.mac_type == e1000_82573 &&
+	    e1000_check_mng_mode(&adapter->hw))
+		e1000_get_hw_control(adapter);
+
 	return E1000_SUCCESS;
 
 err_up:
@@ -1105,10 +1274,17 @@
 	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);
 	}
+
+	/* If AMT is enabled, let the firmware know that the network
+	 * interface is now closed */
+	if (adapter->hw.mac_type == e1000_82573 &&
+	    e1000_check_mng_mode(&adapter->hw))
+		e1000_release_hw_control(adapter);
+
 	return 0;
 }
 
@@ -1153,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;
@@ -1166,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,
@@ -1182,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;
 		}
@@ -1229,7 +1405,7 @@
 {
 	int i, err = 0;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_tx_queues; i++) {
 		err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
 		if (err) {
 			DPRINTK(PROBE, ERR,
@@ -1254,10 +1430,11 @@
 	uint64_t tdba;
 	struct e1000_hw *hw = &adapter->hw;
 	uint32_t tdlen, tctl, tipg, tarc;
+	uint32_t ipgr1, ipgr2;
 
 	/* Setup the HW Tx Head and Tail descriptor pointers */
 
-	switch (adapter->num_queues) {
+	switch (adapter->num_tx_queues) {
 	case 2:
 		tdba = adapter->tx_ring[1].dma;
 		tdlen = adapter->tx_ring[1].count *
@@ -1287,22 +1464,26 @@
 
 	/* Set the default values for the Tx Inter Packet Gap timer */
 
+	if (hw->media_type == e1000_media_type_fiber ||
+	    hw->media_type == e1000_media_type_internal_serdes)
+		tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
+	else
+		tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
+
 	switch (hw->mac_type) {
 	case e1000_82542_rev2_0:
 	case e1000_82542_rev2_1:
 		tipg = DEFAULT_82542_TIPG_IPGT;
-		tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
-		tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+		ipgr1 = DEFAULT_82542_TIPG_IPGR1;
+		ipgr2 = DEFAULT_82542_TIPG_IPGR2;
 		break;
 	default:
-		if (hw->media_type == e1000_media_type_fiber ||
-		    hw->media_type == e1000_media_type_internal_serdes)
-			tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
-		else
-			tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
-		tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
-		tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+		ipgr1 = DEFAULT_82543_TIPG_IPGR1;
+		ipgr2 = DEFAULT_82543_TIPG_IPGR2;
+		break;
 	}
+	tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
+	tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
 	E1000_WRITE_REG(hw, TIPG, tipg);
 
 	/* Set the Tx Interrupt Delay register */
@@ -1378,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");
@@ -1388,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,
@@ -1397,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);
@@ -1454,6 +1635,8 @@
 
 	rxdr->next_to_clean = 0;
 	rxdr->next_to_use = 0;
+	rxdr->rx_skb_top = NULL;
+	rxdr->rx_skb_prev = NULL;
 
 	return 0;
 }
@@ -1475,7 +1658,7 @@
 {
 	int i, err = 0;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_rx_queues; i++) {
 		err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
 		if (err) {
 			DPRINTK(PROBE, ERR,
@@ -1498,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
 
@@ -1510,7 +1693,10 @@
 		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
 		(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
 
-	if(adapter->hw.tbi_compatibility_on == 1)
+	if (adapter->hw.mac_type > e1000_82543)
+		rctl |= E1000_RCTL_SECRC;
+
+	if (adapter->hw.tbi_compatibility_on == 1)
 		rctl |= E1000_RCTL_SBP;
 	else
 		rctl &= ~E1000_RCTL_SBP;
@@ -1521,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.
@@ -1570,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;
 
@@ -1632,22 +1803,27 @@
 
 	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));
 	}
 
 	if (hw->mac_type >= e1000_82571) {
-		/* Reset delay timers after every interrupt */
 		ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+		/* Reset delay timers after every interrupt */
 		ctrl_ext |= E1000_CTRL_EXT_CANC;
+#ifdef CONFIG_E1000_NAPI
+		/* Auto-Mask interrupts upon ICR read. */
+		ctrl_ext |= E1000_CTRL_EXT_IAME;
+#endif
 		E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+		E1000_WRITE_REG(hw, IAM, ~0);
 		E1000_WRITE_FLUSH(hw);
 	}
 
 	/* Setup the HW Rx Head and Tail Descriptor Pointers and
 	 * the Base and Length of the Rx Descriptor Ring */
-	switch (adapter->num_queues) {
+	switch (adapter->num_rx_queues) {
 #ifdef CONFIG_E1000_MQ
 	case 2:
 		rdba = adapter->rx_ring[1].dma;
@@ -1674,7 +1850,7 @@
 	}
 
 #ifdef CONFIG_E1000_MQ
-	if (adapter->num_queues > 1) {
+	if (adapter->num_rx_queues > 1) {
 		uint32_t random[10];
 
 		get_random_bytes(&random[0], 40);
@@ -1684,7 +1860,7 @@
 			E1000_WRITE_REG(hw, RSSIM, 0);
 		}
 
-		switch (adapter->num_queues) {
+		switch (adapter->num_rx_queues) {
 		case 2:
 		default:
 			reta = 0x00800080;
@@ -1716,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 {
@@ -1776,7 +1952,7 @@
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_tx_queues; i++)
 		e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
 }
 
@@ -1784,17 +1960,15 @@
 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,
 				PCI_DMA_TODEVICE);
-		buffer_info->dma = 0;
 	}
-	if(buffer_info->skb) {
+	if (buffer_info->skb)
 		dev_kfree_skb_any(buffer_info->skb);
-		buffer_info->skb = NULL;
-	}
+	memset(buffer_info, 0, sizeof(struct e1000_buffer));
 }
 
 /**
@@ -1813,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);
 	}
@@ -1843,7 +2017,7 @@
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_tx_queues; i++)
 		e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
 }
 
@@ -1887,7 +2061,7 @@
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_rx_queues; i++)
 		e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
 }
 
@@ -1909,12 +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) {
-			ps_page = &rx_ring->ps_page[i];
-			ps_page_dma = &rx_ring->ps_page_dma[i];
+		if (buffer_info->skb) {
 			pci_unmap_single(pdev,
 					 buffer_info->dma,
 					 buffer_info->length,
@@ -1922,19 +2093,30 @@
 
 			dev_kfree_skb(buffer_info->skb);
 			buffer_info->skb = NULL;
-
-			for(j = 0; j < adapter->rx_ps_pages; j++) {
-				if(!ps_page->ps_page[j]) break;
-				pci_unmap_single(pdev,
-						 ps_page_dma->ps_page_dma[j],
-						 PAGE_SIZE, PCI_DMA_FROMDEVICE);
-				ps_page_dma->ps_page_dma[j] = 0;
-				put_page(ps_page->ps_page[j]);
-				ps_page->ps_page[j] = NULL;
-			}
+		}
+		ps_page = &rx_ring->ps_page[i];
+		ps_page_dma = &rx_ring->ps_page_dma[i];
+		for (j = 0; j < adapter->rx_ps_pages; j++) {
+			if (!ps_page->ps_page[j]) break;
+			pci_unmap_page(pdev,
+				       ps_page_dma->ps_page_dma[j],
+				       PAGE_SIZE, PCI_DMA_FROMDEVICE);
+			ps_page_dma->ps_page_dma[j] = 0;
+			put_page(ps_page->ps_page[j]);
+			ps_page->ps_page[j] = NULL;
 		}
 	}
 
+	/* there also may be some cached data in our adapter */
+	if (rx_ring->rx_skb_top) {
+		dev_kfree_skb(rx_ring->rx_skb_top);
+
+		/* rx_skb_prev will be wiped out by rx_skb_top */
+		rx_ring->rx_skb_top = NULL;
+		rx_ring->rx_skb_prev = NULL;
+	}
+
+
 	size = sizeof(struct e1000_buffer) * rx_ring->count;
 	memset(rx_ring->buffer_info, 0, size);
 	size = sizeof(struct e1000_ps_page) * rx_ring->count;
@@ -1963,7 +2145,7 @@
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_rx_queues; i++)
 		e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
 }
 
@@ -1984,7 +2166,7 @@
 	E1000_WRITE_FLUSH(&adapter->hw);
 	mdelay(5);
 
-	if(netif_running(netdev))
+	if (netif_running(netdev))
 		e1000_clean_all_rx_rings(adapter);
 }
 
@@ -2000,12 +2182,14 @@
 	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)) {
+	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);
-		e1000_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
+		adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
 	}
 }
 
@@ -2023,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);
@@ -2042,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;
@@ -2086,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 {
@@ -2099,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
@@ -2109,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;
@@ -2121,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);
 }
 
@@ -2157,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)) &&
@@ -2204,24 +2388,24 @@
 e1000_watchdog_task(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
-	struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
+	struct e1000_tx_ring *txdr = adapter->tx_ring;
 	uint32_t link;
 
 	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);
@@ -2231,13 +2415,28 @@
 			       adapter->link_duplex == FULL_DUPLEX ?
 			       "Full Duplex" : "Half Duplex");
 
+			/* tweak tx_queue_len according to speed/duplex */
+			netdev->tx_queue_len = adapter->tx_queue_len;
+			adapter->tx_timeout_factor = 1;
+			if (adapter->link_duplex == HALF_DUPLEX) {
+				switch (adapter->link_speed) {
+				case SPEED_10:
+					netdev->tx_queue_len = 10;
+					adapter->tx_timeout_factor = 8;
+					break;
+				case SPEED_100:
+					netdev->tx_queue_len = 100;
+					break;
+				}
+			}
+
 			netif_carrier_on(netdev);
 			netif_wake_queue(netdev);
 			mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
 			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");
@@ -2263,7 +2462,10 @@
 
 	e1000_update_adaptive(&adapter->hw);
 
-	if (adapter->num_queues == 1 && !netif_carrier_ok(netdev)) {
+#ifdef CONFIG_E1000_MQ
+	txdr = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
+#endif
+	if (!netif_carrier_ok(netdev)) {
 		if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
 			/* We've lost link, so the controller stops DMA,
 			 * but we've got queued Tx work that's never going
@@ -2274,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;
@@ -2292,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);
@@ -2314,13 +2516,14 @@
 {
 #ifdef NETIF_F_TSO
 	struct e1000_context_desc *context_desc;
+	struct e1000_buffer *buffer_info;
 	unsigned int i;
 	uint32_t cmd_length = 0;
 	uint16_t ipcse = 0, tucse, mss;
 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
 	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)
@@ -2329,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 =
@@ -2341,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,
@@ -2363,6 +2566,7 @@
 
 		i = tx_ring->next_to_use;
 		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+		buffer_info = &tx_ring->buffer_info[i];
 
 		context_desc->lower_setup.ip_fields.ipcss  = ipcss;
 		context_desc->lower_setup.ip_fields.ipcso  = ipcso;
@@ -2374,14 +2578,16 @@
 		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
 		context_desc->cmd_and_length = cpu_to_le32(cmd_length);
 
+		buffer_info->time_stamp = jiffies;
+
 		if (++i == tx_ring->count) i = 0;
 		tx_ring->next_to_use = i;
 
-		return 1;
+		return TRUE;
 	}
 #endif
 
-	return 0;
+	return FALSE;
 }
 
 static inline boolean_t
@@ -2389,13 +2595,15 @@
               struct sk_buff *skb)
 {
 	struct e1000_context_desc *context_desc;
+	struct e1000_buffer *buffer_info;
 	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;
+		buffer_info = &tx_ring->buffer_info[i];
 		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
 
 		context_desc->upper_setup.tcp_fields.tucss = css;
@@ -2404,6 +2612,8 @@
 		context_desc->tcp_seg_setup.data = 0;
 		context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
 
+		buffer_info->time_stamp = jiffies;
+
 		if (unlikely(++i == tx_ring->count)) i = 0;
 		tx_ring->next_to_use = i;
 
@@ -2429,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
@@ -2445,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
@@ -2453,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;
@@ -2475,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;
@@ -2514,7 +2724,7 @@
 			len -= size;
 			offset += size;
 			count++;
-			if(unlikely(++i == tx_ring->count)) i = 0;
+			if (unlikely(++i == tx_ring->count)) i = 0;
 		}
 	}
 
@@ -2534,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);
@@ -2597,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;
 }
@@ -2621,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);
 				}
 			}
@@ -2664,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;
 
@@ -2687,16 +2897,35 @@
 	 * 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;
+
+	/* TSO Workaround for 82571/2 Controllers -- if skb->data
+	 * points to just header, pull a few bytes of payload from
+	 * frags into skb->data */
+		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+		if (skb->data_len && (hdr_len == (skb->len - skb->data_len)) &&
+			(adapter->hw.mac_type == e1000_82571 ||
+			adapter->hw.mac_type == e1000_82572)) {
+			unsigned int pull_size;
+			pull_size = min((unsigned int)4, skb->data_len);
+			if (!__pskb_pull_tail(skb, pull_size)) {
+				printk(KERN_ERR "__pskb_pull_tail failed.\n");
+				dev_kfree_skb_any(skb);
+				return -EFAULT;
+			}
+			len = skb->len - skb->data_len;
+		}
 	}
 
-	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
 
@@ -2709,45 +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;
 
-#ifdef NETIF_F_TSO
-	/* TSO Workaround for 82571/2 Controllers -- if skb->data
-	 * points to just header, pull a few bytes of payload from 
-	 * frags into skb->data */
-	if (skb_shinfo(skb)->tso_size) {
-		uint8_t hdr_len;
-		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
-		if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) && 
-			(adapter->hw.mac_type == e1000_82571 ||
-			adapter->hw.mac_type == e1000_82572)) {
-			unsigned int pull_size;
-			pull_size = min((unsigned int)4, skb->data_len);
-			if (!__pskb_pull_tail(skb, pull_size)) {
-				printk(KERN_ERR "__pskb_pull_tail failed.\n");
-				dev_kfree_skb_any(skb);
-				return -EFAULT;
-			}
-		}
-	}
-#endif
-
-	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);
@@ -2765,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);
@@ -2774,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);
@@ -2833,6 +3041,7 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
+	adapter->tx_timeout_count++;
 	e1000_down(adapter);
 	e1000_up(adapter);
 }
@@ -2850,7 +3059,7 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
-	e1000_update_stats(adapter);
+	/* only return the current stats */
 	return &adapter->net_stats;
 }
 
@@ -2868,56 +3077,57 @@
 	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");
-			return -EINVAL;
-	}
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
-	/* might want this to be bigger enum check... */
-	/* 82571 controllers limit jumbo frame size to 10500 bytes */
-	if ((adapter->hw.mac_type == e1000_82571 || 
-	     adapter->hw.mac_type == e1000_82572) &&
-	    max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
-		DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported "
-				    "on 82571 and 82572 controllers.\n");
+	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
 		return -EINVAL;
 	}
 
-	if(adapter->hw.mac_type == e1000_82573 &&
-	    max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
-		DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
-				    "on 82573\n");
-		return -EINVAL;
-	}
-
-	if(adapter->hw.mac_type > e1000_82547_rev_2) {
-		adapter->rx_buffer_len = max_frame;
-		E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
-	} else {
-		if(unlikely((adapter->hw.mac_type < e1000_82543) &&
-		   (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
-			DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
-					    "on 82542\n");
+	/* Adapter-specific max frame size limits. */
+	switch (adapter->hw.mac_type) {
+	case e1000_82542_rev2_0:
+	case e1000_82542_rev2_1:
+	case e1000_82573:
+		if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+			DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
 			return -EINVAL;
-
-		} else {
-			if(max_frame <= E1000_RXBUFFER_2048) {
-				adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-			} else if(max_frame <= E1000_RXBUFFER_4096) {
-				adapter->rx_buffer_len = E1000_RXBUFFER_4096;
-			} else if(max_frame <= E1000_RXBUFFER_8192) {
-				adapter->rx_buffer_len = E1000_RXBUFFER_8192;
-			} else if(max_frame <= E1000_RXBUFFER_16384) {
-				adapter->rx_buffer_len = E1000_RXBUFFER_16384;
-			}
 		}
+		break;
+	case e1000_82571:
+	case e1000_82572:
+#define MAX_STD_JUMBO_FRAME_SIZE 9234
+		if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
+			DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n");
+			return -EINVAL;
+		}
+		break;
+	default:
+		/* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
+		break;
 	}
 
+	/* since the driver code now supports splitting a packet across
+	 * multiple descriptors, most of the fifo related limitations on
+	 * jumbo frame traffic have gone away.
+	 * simply use 2k descriptors for everything.
+	 *
+	 * NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+	 * means we reserve 2 more, this pushes us to allocate from the next
+	 * larger slab size
+	 * i.e. RXBUFFER_2048 --> size-4096 slab */
+
+	/* recent hardware supports 1KB granularity */
+	if (adapter->hw.mac_type > e1000_82547_rev_2) {
+		adapter->rx_buffer_len =
+		    ((max_frame < E1000_RXBUFFER_2048) ?
+		        max_frame : E1000_RXBUFFER_2048);
+		E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
+	} else
+		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+
 	netdev->mtu = new_mtu;
 
-	if(netif_running(netdev)) {
+	if (netif_running(netdev)) {
 		e1000_down(adapter);
 		e1000_up(adapter);
 	}
@@ -3004,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);
@@ -3012,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);
@@ -3037,12 +3247,11 @@
 
 	adapter->net_stats.rx_errors = adapter->stats.rxerrc +
 		adapter->stats.crcerrs + adapter->stats.algnerrc +
-		adapter->stats.rlec + adapter->stats.mpc + 
-		adapter->stats.cexterr;
+		adapter->stats.rlec + adapter->stats.cexterr;
+	adapter->net_stats.rx_dropped = 0;
 	adapter->net_stats.rx_length_errors = adapter->stats.rlec;
 	adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
 	adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
-	adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
 	adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
 
 	/* Tx Errors */
@@ -3057,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;
@@ -3110,32 +3319,44 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	uint32_t icr = E1000_READ_REG(hw, ICR);
-#if defined(CONFIG_E1000_NAPI) && defined(CONFIG_E1000_MQ) || !defined(CONFIG_E1000_NAPI)
+#ifndef CONFIG_E1000_NAPI
 	int i;
+#else
+	/* Interrupt Auto-Mask...upon reading ICR,
+	 * interrupts are masked.  No need for the
+	 * IMC write, but it does mean we should
+	 * account for it ASAP. */
+	if (likely(hw->mac_type >= e1000_82571))
+		atomic_inc(&adapter->irq_sem);
 #endif
 
-	if(unlikely(!icr))
+	if (unlikely(!icr)) {
+#ifdef CONFIG_E1000_NAPI
+		if (hw->mac_type >= e1000_82571)
+			e1000_irq_enable(adapter);
+#endif
 		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);
 	}
 
 #ifdef CONFIG_E1000_NAPI
-	atomic_inc(&adapter->irq_sem);
-	E1000_WRITE_REG(hw, IMC, ~0);
-	E1000_WRITE_FLUSH(hw);
+	if (unlikely(hw->mac_type < e1000_82571)) {
+		atomic_inc(&adapter->irq_sem);
+		E1000_WRITE_REG(hw, IMC, ~0);
+		E1000_WRITE_FLUSH(hw);
+	}
 #ifdef CONFIG_E1000_MQ
 	if (atomic_read(&adapter->rx_sched_call_data.count) == 0) {
-		cpu_set(adapter->cpu_for_queue[0],
-			adapter->rx_sched_call_data.cpumask);
-		for (i = 1; i < adapter->num_queues; i++) {
-			cpu_set(adapter->cpu_for_queue[i],
-				adapter->rx_sched_call_data.cpumask);
-			atomic_inc(&adapter->irq_sem);
-		}
-		atomic_set(&adapter->rx_sched_call_data.count, i);
+		/* We must setup the cpumask once count == 0 since
+		 * each cpu bit is cleared when the work is done. */
+		adapter->rx_sched_call_data.cpumask = adapter->cpumask;
+		atomic_add(adapter->num_rx_queues - 1, &adapter->irq_sem);
+		atomic_set(&adapter->rx_sched_call_data.count,
+		           adapter->num_rx_queues);
 		smp_call_async_mask(&adapter->rx_sched_call_data);
 	} else {
 		printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
@@ -3149,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 */
@@ -3187,7 +3408,7 @@
 {
 	struct e1000_adapter *adapter;
 	int work_to_do = min(*budget, poll_dev->quota);
-	int tx_cleaned, i = 0, work_done = 0;
+	int tx_cleaned = 0, i = 0, work_done = 0;
 
 	/* Must NOT use netdev_priv macro here. */
 	adapter = poll_dev->priv;
@@ -3198,19 +3419,31 @@
 
 	while (poll_dev != &adapter->polling_netdev[i]) {
 		i++;
-		if (unlikely(i == adapter->num_queues))
+		if (unlikely(i == adapter->num_rx_queues))
 			BUG();
 	}
 
-	tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+	if (likely(adapter->num_tx_queues == 1)) {
+		/* e1000_clean is called per-cpu.  This lock protects
+		 * tx_ring[0] from being cleaned by multiple cpus
+		 * simultaneously.  A failure obtaining the lock means
+		 * tx_ring[0] is currently being cleaned anyway. */
+		if (spin_trylock(&adapter->tx_queue_lock)) {
+			tx_cleaned = e1000_clean_tx_irq(adapter,
+							&adapter->tx_ring[0]);
+			spin_unlock(&adapter->tx_queue_lock);
+		}
+	} else
+		tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+
 	adapter->clean_rx(adapter, &adapter->rx_ring[i],
 	                  &work_done, work_to_do);
 
 	*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);
@@ -3242,22 +3475,24 @@
 	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);
 
+#ifdef CONFIG_E1000_MQ
+			tx_ring->tx_stats.bytes += buffer_info->length;
+#endif
 			e1000_unmap_and_free_tx_resource(adapter, buffer_info);
+			memset(tx_desc, 0, sizeof(struct e1000_tx_desc));
 
-			tx_desc->buffer_addr = 0;
-			tx_desc->lower.data = 0;
-			tx_desc->upper.data = 0;
-
-			if(unlikely(++i == tx_ring->count)) i = 0;
+			if (unlikely(++i == tx_ring->count)) i = 0;
 		}
 
-		tx_ring->pkt++;
-		
+#ifdef CONFIG_E1000_MQ
+		tx_ring->tx_stats.packets++;
+#endif
+
 		eop = tx_ring->buffer_info[i].next_to_watch;
 		eop_desc = E1000_TX_DESC(*tx_ring, eop);
 	}
@@ -3266,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);
 
@@ -3276,32 +3511,31 @@
 		/* Detect a transmit hang in hardware, this serializes the
 		 * check with the clearing of time_stamp and movement of i */
 		adapter->detect_tx_hung = FALSE;
-		if (tx_ring->buffer_info[i].dma &&
-		    time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+		if (tx_ring->buffer_info[eop].dma &&
+		    time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
+		               adapter->tx_timeout_factor * HZ)
 		    && !(E1000_READ_REG(&adapter->hw, STATUS) &
-			E1000_STATUS_TXOFF)) {
+		         E1000_STATUS_TXOFF)) {
 
 			/* detected Tx unit hang */
-			i = tx_ring->next_to_clean;
-			eop = tx_ring->buffer_info[i].next_to_watch;
-			eop_desc = E1000_TX_DESC(*tx_ring, eop);
 			DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+					"  Tx Queue             <%lu>\n"
 					"  TDH                  <%x>\n"
 					"  TDT                  <%x>\n"
 					"  next_to_use          <%x>\n"
 					"  next_to_clean        <%x>\n"
 					"buffer_info[next_to_clean]\n"
-					"  dma                  <%llx>\n"
 					"  time_stamp           <%lx>\n"
 					"  next_to_watch        <%x>\n"
 					"  jiffies              <%lx>\n"
 					"  next_to_watch.status <%x>\n",
+				(unsigned long)((tx_ring - adapter->tx_ring) /
+					sizeof(struct e1000_tx_ring)),
 				readl(adapter->hw.hw_addr + tx_ring->tdh),
 				readl(adapter->hw.hw_addr + tx_ring->tdt),
 				tx_ring->next_to_use,
-				i,
-				(unsigned long long)tx_ring->buffer_info[i].dma,
-				tx_ring->buffer_info[i].time_stamp,
+				tx_ring->next_to_clean,
+				tx_ring->buffer_info[eop].time_stamp,
 				eop,
 				jiffies,
 				eop_desc->upper.fields.status);
@@ -3329,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 */
@@ -3379,46 +3613,87 @@
 {
 	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;
 	unsigned int i;
-	boolean_t cleaned = FALSE;
+	int cleaned_count = 0;
+	boolean_t cleaned = FALSE, multi_descriptor = FALSE;
 
 	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
-		cleaned = TRUE;
+		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,
 		                 buffer_info->dma,
 		                 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,
@@ -3433,18 +3708,41 @@
 			}
 		}
 
-		/* Good Receive */
-		skb_put(skb, length - ETHERNET_FCS_SIZE);
+		/* code added for copybreak, this should improve
+		 * performance for small packets with large amounts
+		 * of reassembly being done in the stack */
+#define E1000_CB_LENGTH 256
+		if ((length < E1000_CB_LENGTH) &&
+		   !rx_ring->rx_skb_top &&
+		   /* or maybe (status & E1000_RXD_STAT_EOP) && */
+		   !multi_descriptor) {
+			struct sk_buff *new_skb =
+			    dev_alloc_skb(length + NET_IP_ALIGN);
+			if (new_skb) {
+				skb_reserve(new_skb, NET_IP_ALIGN);
+				new_skb->dev = netdev;
+				memcpy(new_skb->data - NET_IP_ALIGN,
+				       skb->data - NET_IP_ALIGN,
+				       length + NET_IP_ALIGN);
+				/* save the skb in buffer_info as good */
+				buffer_info->skb = skb;
+				skb = new_skb;
+				skb_put(skb, length);
+			}
+		}
+
+		/* end copybreak code */
 
 		/* Receive Checksum Offload */
 		e1000_rx_checksum(adapter,
-				  (uint32_t)(rx_desc->status) |
+				  (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 &&
-			    (rx_desc->status & E1000_RXD_STAT_VP))) {
+		if (unlikely(adapter->vlgrp &&
+			    (status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
 						 le16_to_cpu(rx_desc->special) &
 						 E1000_RXD_SPC_VLAN_MASK);
@@ -3452,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);
@@ -3462,17 +3760,28 @@
 		}
 #endif /* CONFIG_E1000_NAPI */
 		netdev->last_rx = jiffies;
-		rx_ring->pkt++;
+#ifdef CONFIG_E1000_MQ
+		rx_ring->rx_stats.packets++;
+		rx_ring->rx_stats.bytes += length;
+#endif
 
 next_desc:
 		rx_desc->status = 0;
-		buffer_info->skb = NULL;
-		if(unlikely(++i == rx_ring->count)) i = 0;
 
-		rx_desc = E1000_RX_DESC(*rx_ring, i);
+		/* return some buffers to hardware, one at a time is too slow */
+		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
+			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+			cleaned_count = 0;
+		}
+
+		rx_desc = next_rxd;
+		buffer_info = next_buffer;
 	}
 	rx_ring->next_to_clean = i;
-	adapter->alloc_rx_buf(adapter, rx_ring);
+
+	cleaned_count = E1000_DESC_UNUSED(rx_ring);
+	if (cleaned_count)
+		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
 
 	return cleaned;
 }
@@ -3492,52 +3801,59 @@
                       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;
 	boolean_t cleaned = FALSE;
 
 	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);
@@ -3547,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],
@@ -3568,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);
@@ -3584,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);
@@ -3593,18 +3905,31 @@
 		}
 #endif /* CONFIG_E1000_NAPI */
 		netdev->last_rx = jiffies;
-		rx_ring->pkt++;
+#ifdef CONFIG_E1000_MQ
+		rx_ring->rx_stats.packets++;
+		rx_ring->rx_stats.bytes += length;
+#endif
 
 next_desc:
 		rx_desc->wb.middle.status_error &= ~0xFF;
 		buffer_info->skb = NULL;
-		if(unlikely(++i == rx_ring->count)) i = 0;
 
-		rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+		/* return some buffers to hardware, one at a time is too slow */
+		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
+			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+			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;
-	adapter->alloc_rx_buf(adapter, rx_ring);
+
+	cleaned_count = E1000_DESC_UNUSED(rx_ring);
+	if (cleaned_count)
+		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
 
 	return cleaned;
 }
@@ -3616,7 +3941,8 @@
 
 static void
 e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
-                       struct e1000_rx_ring *rx_ring)
+                       struct e1000_rx_ring *rx_ring,
+		       int cleaned_count)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
@@ -3629,11 +3955,18 @@
 	i = rx_ring->next_to_use;
 	buffer_info = &rx_ring->buffer_info[i];
 
-	while(!buffer_info->skb) {
-		skb = dev_alloc_skb(bufsz);
+	while (cleaned_count--) {
+		if (!(skb = buffer_info->skb))
+			skb = dev_alloc_skb(bufsz);
+		else {
+			skb_trim(skb, 0);
+			goto map_skb;
+		}
 
-		if(unlikely(!skb)) {
+
+		if (unlikely(!skb)) {
 			/* Better luck next round */
+			adapter->alloc_rx_buff_failed++;
 			break;
 		}
 
@@ -3670,6 +4003,7 @@
 
 		buffer_info->skb = skb;
 		buffer_info->length = adapter->rx_buffer_len;
+map_skb:
 		buffer_info->dma = pci_map_single(pdev,
 						  skb->data,
 						  adapter->rx_buffer_len,
@@ -3695,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);
+	}
 }
 
 /**
@@ -3718,7 +4055,8 @@
 
 static void
 e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
-                          struct e1000_rx_ring *rx_ring)
+                          struct e1000_rx_ring *rx_ring,
+			  int cleaned_count)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
@@ -3734,16 +4072,18 @@
 	ps_page = &rx_ring->ps_page[i];
 	ps_page_dma = &rx_ring->ps_page_dma[i];
 
-	while(!buffer_info->skb) {
+	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],
@@ -3751,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] =
@@ -3762,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
@@ -3781,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);
+	}
 }
 
 /**
@@ -3815,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 |
@@ -3842,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);
@@ -3855,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;
 }
 
@@ -3896,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) {
@@ -3904,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;
@@ -3915,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 {
@@ -3946,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
@@ -3961,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;
@@ -3971,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
@@ -3995,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");
 }
 
@@ -4044,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;
@@ -4066,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;
 		}
@@ -4080,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;
@@ -4099,15 +4443,19 @@
 
 	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) &&
-		(vid == adapter->mng_vlan_id))
+	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);
 		return;
+	}
+
 	/* remove VID from filter table */
 	index = (vid >> 5) & 0x7F;
 	vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
@@ -4120,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);
 		}
@@ -4136,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;
@@ -4168,35 +4516,92 @@
 }
 
 #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)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
+	uint32_t ctrl, ctrl_ext, rctl, manc, status;
 	uint32_t wufc = adapter->wol;
+	int retval = 0;
 
 	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
@@ -4207,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);
@@ -4220,96 +4625,96 @@
 
 		E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
 		E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
-		pci_enable_wake(pdev, 3, 1);
-		pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
+		retval = pci_enable_wake(pdev, PCI_D3hot, 1);
+		if (retval)
+			DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+		retval = pci_enable_wake(pdev, PCI_D3cold, 1);
+		if (retval)
+			DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
 	} else {
 		E1000_WRITE_REG(&adapter->hw, WUC, 0);
 		E1000_WRITE_REG(&adapter->hw, WUFC, 0);
-		pci_enable_wake(pdev, 3, 0);
-		pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+		retval = pci_enable_wake(pdev, PCI_D3hot, 0);
+		if (retval)
+			DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+		retval = pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */
+		if (retval)
+			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);
-			pci_enable_wake(pdev, 3, 1);
-			pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
+			retval = pci_enable_wake(pdev, PCI_D3hot, 1);
+			if (retval)
+				DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+			retval = pci_enable_wake(pdev, PCI_D3cold, 1);
+			if (retval)
+				DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
 		}
 	}
 
-	switch(adapter->hw.mac_type) {
-	case e1000_82571:
-	case e1000_82572:
-		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
-		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
-				ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
-		break;
-	case e1000_82573:
-		swsm = E1000_READ_REG(&adapter->hw, SWSM);
-		E1000_WRITE_REG(&adapter->hw, SWSM,
-				swsm & ~E1000_SWSM_DRV_LOAD);
-		break;
-	default:
-		break;
-	}
+	/* Release control of h/w to f/w.  If f/w is AMT enabled, this
+	 * would have already happened in close and is redundant. */
+	e1000_release_hw_control(adapter);
 
 	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	if (retval)
+		DPRINTK(PROBE, ERR, "Error in setting power state\n");
 
 	return 0;
 }
 
+#ifdef CONFIG_PM
 static int
 e1000_resume(struct pci_dev *pdev)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	uint32_t manc, ret_val, swsm;
-	uint32_t ctrl_ext;
+	int retval;
+	uint32_t manc, ret_val;
 
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
+	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);
 
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
+	retval = pci_enable_wake(pdev, PCI_D3hot, 0);
+	if (retval)
+		DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+	retval = pci_enable_wake(pdev, PCI_D3cold, 0);
+	if (retval)
+		DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
 
 	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);
 		E1000_WRITE_REG(&adapter->hw, MANC, manc);
 	}
 
-	switch(adapter->hw.mac_type) {
-	case e1000_82571:
-	case e1000_82572:
-		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
-		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
-				ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
-		break;
-	case e1000_82573:
-		swsm = E1000_READ_REG(&adapter->hw, SWSM);
-		E1000_WRITE_REG(&adapter->hw, SWSM,
-				swsm | E1000_SWSM_DRV_LOAD);
-		break;
-	default:
-		break;
-	}
+	/* If the controller is 82573 and f/w is AMT, do not set
+	 * DRV_LOAD until the interface is up.  For all other cases,
+	 * let the f/w know that the h/w is now under the control
+	 * of the driver. */
+	if (adapter->hw.mac_type != e1000_82573 ||
+	    !e1000_check_mng_mode(&adapter->hw))
+		e1000_get_hw_control(adapter);
 
 	return 0;
 }
@@ -4327,6 +4732,9 @@
 	disable_irq(adapter->pdev->irq);
 	e1000_intr(adapter->pdev->irq, netdev, NULL);
 	e1000_clean_tx_irq(adapter, adapter->tx_ring);
+#ifndef CONFIG_E1000_NAPI
+	adapter->clean_rx(adapter, adapter->rx_ring);
+#endif
 	enable_irq(adapter->pdev->irq);
 }
 #endif
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 ccbbe5a..3768d83 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -177,7 +177,7 @@
  *
  * Valid Range: 100-100000 (0=off, 1=dynamic)
  *
- * Default Value: 1
+ * Default Value: 8000
  */
 
 E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
@@ -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,12 +315,12 @@
 		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;
 		}
-		for (i = 0; i < adapter->num_queues; i++)
+		for (i = 0; i < adapter->num_tx_queues; i++)
 			tx_ring[i].count = tx_ring->count;
 	}
 	{ /* Receive Descriptor Count */
@@ -341,12 +341,12 @@
 		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;
 		}
-		for (i = 0; i < adapter->num_queues; i++)
+		for (i = 0; i < adapter->num_rx_queues; i++)
 			rx_ring[i].count = rx_ring->count;
 	}
 	{ /* Checksum Offload Enable/Disable */
@@ -388,7 +388,7 @@
 			e1000_validate_option(&fc, &opt, adapter);
 			adapter->hw.fc = adapter->hw.original_fc = fc;
 		} else {
-			adapter->hw.fc = opt.def;
+			adapter->hw.fc = adapter->hw.original_fc = opt.def;
 		}
 	}
 	{ /* Transmit Interrupt Delay */
@@ -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");
@@ -584,6 +584,12 @@
 					 .p = dplx_list }}
 		};
 
+		if (e1000_check_phy_reset_block(&adapter->hw)) {
+			DPRINTK(PROBE, INFO,
+				"Link active due to SoL/IDER Session. "
+			        "Speed/Duplex/AutoNeg parameter ignored.\n");
+			return;
+		}
 		if (num_Duplex > bd) {
 			dplx = Duplex[bd];
 			e1000_validate_option(&dplx, &opt, adapter);
@@ -592,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");
@@ -653,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/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 22c3a37..40ae36b 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -35,6 +35,8 @@
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/ip.h>
 
 #include <linux/bitops.h>
 #include <linux/delay.h>
@@ -55,13 +57,15 @@
 /* Constants */
 #define VLAN_HLEN		4
 #define FCS_LEN			4
-#define WRAP			NET_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
+#define DMA_ALIGN		8	/* hw requires 8-byte alignment */
+#define HW_IP_ALIGN		2	/* hw aligns IP header */
+#define WRAP			HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
 #define RX_SKB_SIZE		((dev->mtu + WRAP + 7) & ~0x7)
 
-#define INT_CAUSE_UNMASK_ALL		0x0007ffff
-#define INT_CAUSE_UNMASK_ALL_EXT	0x0011ffff
-#define INT_CAUSE_MASK_ALL		0x00000000
-#define INT_CAUSE_MASK_ALL_EXT		0x00000000
+#define INT_UNMASK_ALL			0x0007ffff
+#define INT_UNMASK_ALL_EXT		0x0011ffff
+#define INT_MASK_ALL			0x00000000
+#define INT_MASK_ALL_EXT		0x00000000
 #define INT_CAUSE_CHECK_BITS		INT_CAUSE_UNMASK_ALL
 #define INT_CAUSE_CHECK_BITS_EXT	INT_CAUSE_UNMASK_ALL_EXT
 
@@ -78,8 +82,9 @@
 static int eth_port_link_is_up(unsigned int eth_port_num);
 static void eth_port_uc_addr_get(struct net_device *dev,
 						unsigned char *MacAddr);
-static int mv643xx_eth_real_open(struct net_device *);
-static int mv643xx_eth_real_stop(struct net_device *);
+static void eth_port_set_multicast_list(struct net_device *);
+static int mv643xx_eth_open(struct net_device *);
+static int mv643xx_eth_stop(struct net_device *);
 static int mv643xx_eth_change_mtu(struct net_device *, int);
 static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *);
 static void eth_port_init_mac_tables(unsigned int eth_port_num);
@@ -124,15 +129,8 @@
  */
 static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct mv643xx_private *mp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&mp->lock, flags);
-
-	if ((new_mtu > 9500) || (new_mtu < 64)) {
-		spin_unlock_irqrestore(&mp->lock, flags);
+	if ((new_mtu > 9500) || (new_mtu < 64))
 		return -EINVAL;
-	}
 
 	dev->mtu = new_mtu;
 	/*
@@ -142,17 +140,13 @@
 	 * to memory is full, which might fail the open function.
 	 */
 	if (netif_running(dev)) {
-		if (mv643xx_eth_real_stop(dev))
-			printk(KERN_ERR
-				"%s: Fatal error on stopping device\n",
-				dev->name);
-		if (mv643xx_eth_real_open(dev))
+		mv643xx_eth_stop(dev);
+		if (mv643xx_eth_open(dev))
 			printk(KERN_ERR
 				"%s: Fatal error on opening device\n",
 				dev->name);
 	}
 
-	spin_unlock_irqrestore(&mp->lock, flags);
 	return 0;
 }
 
@@ -170,15 +164,19 @@
 	struct mv643xx_private *mp = netdev_priv(dev);
 	struct pkt_info pkt_info;
 	struct sk_buff *skb;
+	int unaligned;
 
 	if (test_and_set_bit(0, &mp->rx_task_busy))
 		panic("%s: Error in test_set_bit / clear_bit", dev->name);
 
 	while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
-		skb = dev_alloc_skb(RX_SKB_SIZE);
+		skb = dev_alloc_skb(RX_SKB_SIZE + DMA_ALIGN);
 		if (!skb)
 			break;
 		mp->rx_ring_skbs++;
+		unaligned = (u32)skb->data & (DMA_ALIGN - 1);
+		if (unaligned)
+			skb_reserve(skb, DMA_ALIGN - unaligned);
 		pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
 		pkt_info.byte_cnt = RX_SKB_SIZE;
 		pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE,
@@ -189,7 +187,7 @@
 				"%s: Error allocating RX Ring\n", dev->name);
 			break;
 		}
-		skb_reserve(skb, 2);
+		skb_reserve(skb, HW_IP_ALIGN);
 	}
 	clear_bit(0, &mp->rx_task_busy);
 	/*
@@ -207,7 +205,7 @@
 	else {
 		/* Return interrupts */
 		mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(mp->port_num),
-							INT_CAUSE_UNMASK_ALL);
+							INT_UNMASK_ALL);
 	}
 #endif
 }
@@ -267,6 +265,8 @@
 		mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
 
 	mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config);
+
+	eth_port_set_multicast_list(dev);
 }
 
 /*
@@ -342,8 +342,6 @@
 	if (!(eth_int_cause_ext & (BIT0 | BIT8)))
 		return released;
 
-	spin_lock(&mp->lock);
-
 	/* Check only queue 0 */
 	while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
 		if (pkt_info.cmd_sts & BIT0) {
@@ -351,31 +349,21 @@
 			stats->tx_errors++;
 		}
 
-		/*
-		 * If return_info is different than 0, release the skb.
-		 * The case where return_info is not 0 is only in case
-		 * when transmitted a scatter/gather packet, where only
-		 * last skb releases the whole chain.
-		 */
-		if (pkt_info.return_info) {
-			if (skb_shinfo(pkt_info.return_info)->nr_frags)
-				dma_unmap_page(NULL, pkt_info.buf_ptr,
-						pkt_info.byte_cnt,
-						DMA_TO_DEVICE);
-			else
-				dma_unmap_single(NULL, pkt_info.buf_ptr,
-						pkt_info.byte_cnt,
-						DMA_TO_DEVICE);
+		if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
+			dma_unmap_single(NULL, pkt_info.buf_ptr,
+					pkt_info.byte_cnt,
+					DMA_TO_DEVICE);
+		else
+			dma_unmap_page(NULL, pkt_info.buf_ptr,
+					pkt_info.byte_cnt,
+					DMA_TO_DEVICE);
 
+		if (pkt_info.return_info) {
 			dev_kfree_skb_irq(pkt_info.return_info);
 			released = 0;
-		} else
-			dma_unmap_page(NULL, pkt_info.buf_ptr,
-					pkt_info.byte_cnt, DMA_TO_DEVICE);
+		}
 	}
 
-	spin_unlock(&mp->lock);
-
 	return released;
 }
 
@@ -482,12 +470,12 @@
 
 	/* Read interrupt cause registers */
 	eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
-						INT_CAUSE_UNMASK_ALL;
+						INT_UNMASK_ALL;
 
 	if (eth_int_cause & BIT1)
 		eth_int_cause_ext = mv_read(
 			MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
-						INT_CAUSE_UNMASK_ALL_EXT;
+						INT_UNMASK_ALL_EXT;
 
 #ifdef MV643XX_NAPI
 	if (!(eth_int_cause & 0x0007fffd)) {
@@ -512,9 +500,10 @@
 	} else {
 		if (netif_rx_schedule_prep(dev)) {
 			/* Mask all the interrupts */
-			mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
-			mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG
-								(port_num), 0);
+			mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+								INT_MASK_ALL);
+			/* wait for previous write to complete */
+			mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
 			__netif_rx_schedule(dev);
 		}
 #else
@@ -527,9 +516,12 @@
 		 * with skb's.
 		 */
 #ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
-		/* Unmask all interrupts on ethernet port */
+		/* Mask all interrupts on ethernet port */
 		mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-							INT_CAUSE_MASK_ALL);
+							INT_MASK_ALL);
+		/* wait for previous write to take effect */
+		mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
 		queue_task(&mp->rx_task, &tq_immediate);
 		mark_bh(IMMEDIATE_BH);
 #else
@@ -636,56 +628,6 @@
 }
 
 /*
- * mv643xx_eth_open
- *
- * This function is called when openning the network device. The function
- * should initialize all the hardware, initialize cyclic Rx/Tx
- * descriptors chain and buffers and allocate an IRQ to the network
- * device.
- *
- * Input :	a pointer to the network device structure
- *
- * Output :	zero of success , nonzero if fails.
- */
-
-static int mv643xx_eth_open(struct net_device *dev)
-{
-	struct mv643xx_private *mp = netdev_priv(dev);
-	unsigned int port_num = mp->port_num;
-	int err;
-
-	spin_lock_irq(&mp->lock);
-
-	err = request_irq(dev->irq, mv643xx_eth_int_handler,
-			SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
-
-	if (err) {
-		printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
-								port_num);
-		err = -EAGAIN;
-		goto out;
-	}
-
-	if (mv643xx_eth_real_open(dev)) {
-		printk("%s: Error opening interface\n", dev->name);
-		err = -EBUSY;
-		goto out_free;
-	}
-
-	spin_unlock_irq(&mp->lock);
-
-	return 0;
-
-out_free:
-	free_irq(dev->irq, dev);
-
-out:
-	spin_unlock_irq(&mp->lock);
-
-	return err;
-}
-
-/*
  * ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
  *
  * DESCRIPTION:
@@ -777,28 +719,37 @@
 	mp->port_tx_queue_command |= 1;
 }
 
-/* Helper function for mv643xx_eth_open */
-static int mv643xx_eth_real_open(struct net_device *dev)
+/*
+ * mv643xx_eth_open
+ *
+ * This function is called when openning the network device. The function
+ * should initialize all the hardware, initialize cyclic Rx/Tx
+ * descriptors chain and buffers and allocate an IRQ to the network
+ * device.
+ *
+ * Input :	a pointer to the network device structure
+ *
+ * Output :	zero of success , nonzero if fails.
+ */
+
+static int mv643xx_eth_open(struct net_device *dev)
 {
 	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
 	unsigned int size;
+	int err;
+
+	err = request_irq(dev->irq, mv643xx_eth_int_handler,
+			SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+	if (err) {
+		printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
+								port_num);
+		return -EAGAIN;
+	}
 
 	/* Stop RX Queues */
 	mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
 
-	/* Clear the ethernet port interrupts */
-	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
-	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
-	/* Unmask RX buffer and TX end interrupt */
-	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-						INT_CAUSE_UNMASK_ALL);
-
-	/* Unmask phy and link status changes interrupts */
-	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
-						INT_CAUSE_UNMASK_ALL_EXT);
-
 	/* Set the MAC Address */
 	memcpy(mp->port_mac_addr, dev->dev_addr, 6);
 
@@ -818,14 +769,15 @@
 								GFP_KERNEL);
 	if (!mp->rx_skb) {
 		printk(KERN_ERR "%s: Cannot allocate Rx skb ring\n", dev->name);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out_free_irq;
 	}
 	mp->tx_skb = kmalloc(sizeof(*mp->tx_skb) * mp->tx_ring_size,
 								GFP_KERNEL);
 	if (!mp->tx_skb) {
 		printk(KERN_ERR "%s: Cannot allocate Tx skb ring\n", dev->name);
-		kfree(mp->rx_skb);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out_free_rx_skb;
 	}
 
 	/* Allocate TX ring */
@@ -845,9 +797,8 @@
 	if (!mp->p_tx_desc_area) {
 		printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
 							dev->name, size);
-		kfree(mp->rx_skb);
-		kfree(mp->tx_skb);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out_free_tx_skb;
 	}
 	BUG_ON((u32) mp->p_tx_desc_area & 0xf);	/* check 16-byte alignment */
 	memset((void *)mp->p_tx_desc_area, 0, mp->tx_desc_area_size);
@@ -874,13 +825,12 @@
 		printk(KERN_ERR "%s: Freeing previously allocated TX queues...",
 							dev->name);
 		if (mp->rx_sram_size)
-			iounmap(mp->p_rx_desc_area);
+			iounmap(mp->p_tx_desc_area);
 		else
 			dma_free_coherent(NULL, mp->tx_desc_area_size,
 					mp->p_tx_desc_area, mp->tx_desc_dma);
-		kfree(mp->rx_skb);
-		kfree(mp->tx_skb);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out_free_tx_skb;
 	}
 	memset((void *)mp->p_rx_desc_area, 0, size);
 
@@ -900,9 +850,26 @@
 	mp->tx_int_coal =
 		eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
 
-	netif_start_queue(dev);
+	/* Clear any pending ethernet port interrupts */
+	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
 
+	/* Unmask phy and link status changes interrupts */
+	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+						INT_UNMASK_ALL_EXT);
+
+	/* Unmask RX buffer and TX end interrupt */
+	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
 	return 0;
+
+out_free_tx_skb:
+	kfree(mp->tx_skb);
+out_free_rx_skb:
+	kfree(mp->rx_skb);
+out_free_irq:
+	free_irq(dev->irq, dev);
+
+	return err;
 }
 
 static void mv643xx_eth_free_tx_rings(struct net_device *dev)
@@ -910,14 +877,17 @@
 	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
 	unsigned int curr;
+	struct sk_buff *skb;
 
 	/* Stop Tx Queues */
 	mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
 
 	/* Free outstanding skb's on TX rings */
 	for (curr = 0; mp->tx_ring_skbs && curr < mp->tx_ring_size; curr++) {
-		if (mp->tx_skb[curr]) {
-			dev_kfree_skb(mp->tx_skb[curr]);
+		skb = mp->tx_skb[curr];
+		if (skb) {
+			mp->tx_ring_skbs -= skb_shinfo(skb)->nr_frags;
+			dev_kfree_skb(skb);
 			mp->tx_ring_skbs--;
 		}
 	}
@@ -973,44 +943,32 @@
  * Output :	zero if success , nonzero if fails
  */
 
-/* Helper function for mv643xx_eth_stop */
-
-static int mv643xx_eth_real_stop(struct net_device *dev)
+static int mv643xx_eth_stop(struct net_device *dev)
 {
 	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
 
+	/* Mask all interrupts on ethernet port */
+	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+	/* wait for previous write to complete */
+	mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
+#ifdef MV643XX_NAPI
+	netif_poll_disable(dev);
+#endif
 	netif_carrier_off(dev);
 	netif_stop_queue(dev);
 
+	eth_port_reset(mp->port_num);
+
 	mv643xx_eth_free_tx_rings(dev);
 	mv643xx_eth_free_rx_rings(dev);
 
-	eth_port_reset(mp->port_num);
-
-	/* Disable ethernet port interrupts */
-	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
-	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
-	/* Mask RX buffer and TX end interrupt */
-	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
-
-	/* Mask phy and link status changes interrupts */
-	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
-
-	return 0;
-}
-
-static int mv643xx_eth_stop(struct net_device *dev)
-{
-	struct mv643xx_private *mp = netdev_priv(dev);
-
-	spin_lock_irq(&mp->lock);
-
-	mv643xx_eth_real_stop(dev);
+#ifdef MV643XX_NAPI
+	netif_poll_enable(dev);
+#endif
 
 	free_irq(dev->irq, dev);
-	spin_unlock_irq(&mp->lock);
 
 	return 0;
 }
@@ -1022,20 +980,17 @@
 	struct pkt_info pkt_info;
 
 	while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
-		if (pkt_info.return_info) {
-			if (skb_shinfo(pkt_info.return_info)->nr_frags)
-				dma_unmap_page(NULL, pkt_info.buf_ptr,
-						pkt_info.byte_cnt,
-						DMA_TO_DEVICE);
-			else
-				dma_unmap_single(NULL, pkt_info.buf_ptr,
-						pkt_info.byte_cnt,
-						DMA_TO_DEVICE);
-
-			dev_kfree_skb_irq(pkt_info.return_info);
-		} else
+		if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
+			dma_unmap_single(NULL, pkt_info.buf_ptr,
+					pkt_info.byte_cnt,
+					DMA_TO_DEVICE);
+		else
 			dma_unmap_page(NULL, pkt_info.buf_ptr,
-					pkt_info.byte_cnt, DMA_TO_DEVICE);
+					pkt_info.byte_cnt,
+					DMA_TO_DEVICE);
+
+		if (pkt_info.return_info)
+			dev_kfree_skb_irq(pkt_info.return_info);
 	}
 
 	if (netif_queue_stopped(dev) &&
@@ -1053,14 +1008,11 @@
 	struct mv643xx_private *mp = netdev_priv(dev);
 	int done = 1, orig_budget, work_done;
 	unsigned int port_num = mp->port_num;
-	unsigned long flags;
 
 #ifdef MV643XX_TX_FAST_REFILL
 	if (++mp->tx_clean_threshold > 5) {
-		spin_lock_irqsave(&mp->lock, flags);
 		mv643xx_tx(dev);
 		mp->tx_clean_threshold = 0;
-		spin_unlock_irqrestore(&mp->lock, flags);
 	}
 #endif
 
@@ -1078,21 +1030,36 @@
 	}
 
 	if (done) {
-		spin_lock_irqsave(&mp->lock, flags);
-		__netif_rx_complete(dev);
+		netif_rx_complete(dev);
 		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
 		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
 		mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-						INT_CAUSE_UNMASK_ALL);
-		mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
-						INT_CAUSE_UNMASK_ALL_EXT);
-		spin_unlock_irqrestore(&mp->lock, flags);
+						INT_UNMASK_ALL);
 	}
 
 	return done ? 0 : 1;
 }
 #endif
 
+/* Hardware can't handle unaligned fragments smaller than 9 bytes.
+ * This helper function detects that case.
+ */
+
+static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
+{
+        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;
+}
+
+
 /*
  * mv643xx_eth_start_xmit
  *
@@ -1136,12 +1103,19 @@
 		return 1;
 	}
 
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+	if (has_tiny_unaligned_frags(skb)) {
+		if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
+			stats->tx_dropped++;
+			printk(KERN_DEBUG "%s: failed to linearize tiny "
+					"unaligned fragment\n", dev->name);
+			return 1;
+		}
+	}
+
 	spin_lock_irqsave(&mp->lock, flags);
 
-	/* Update packet info data structure -- DMA owned, first last */
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
 	if (!skb_shinfo(skb)->nr_frags) {
-linear:
 		if (skb->ip_summed != CHECKSUM_HW) {
 			/* Errata BTS #50, IHL must be 5 if no HW checksum */
 			pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
@@ -1150,7 +1124,6 @@
 					   5 << ETH_TX_IHL_SHIFT;
 			pkt_info.l4i_chk = 0;
 		} else {
-
 			pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
 					   ETH_TX_FIRST_DESC |
 					   ETH_TX_LAST_DESC |
@@ -1158,14 +1131,16 @@
 					   ETH_GEN_IP_V_4_CHECKSUM |
 					   skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
 			/* CPU already calculated pseudo header checksum. */
-			if (skb->nh.iph->protocol == IPPROTO_UDP) {
+			if ((skb->protocol == ETH_P_IP) &&
+			    (skb->nh.iph->protocol == IPPROTO_UDP) ) {
 				pkt_info.cmd_sts |= ETH_UDP_FRAME;
 				pkt_info.l4i_chk = skb->h.uh->check;
-			} else if (skb->nh.iph->protocol == IPPROTO_TCP)
+			} else if ((skb->protocol == ETH_P_IP) &&
+				   (skb->nh.iph->protocol == IPPROTO_TCP))
 				pkt_info.l4i_chk = skb->h.th->check;
 			else {
 				printk(KERN_ERR
-					"%s: chksum proto != TCP or UDP\n",
+					"%s: chksum proto != IPv4 TCP or UDP\n",
 					dev->name);
 				spin_unlock_irqrestore(&mp->lock, flags);
 				return 1;
@@ -1183,26 +1158,6 @@
 	} else {
 		unsigned int frag;
 
-		/* Since hardware can't handle unaligned fragments smaller
-		 * than 9 bytes, if we find any, we linearize the skb
-		 * and start again.  When I've seen it, it's always been
-		 * the first frag (probably near the end of the page),
-		 * but we check all frags to be safe.
-		 */
-		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
-			skb_frag_t *fragp;
-
-			fragp = &skb_shinfo(skb)->frags[frag];
-			if (fragp->size <= 8 && fragp->page_offset & 0x7) {
-				skb_linearize(skb, GFP_ATOMIC);
-				printk(KERN_DEBUG "%s: unaligned tiny fragment"
-						"%d of %d, fixed\n",
-						dev->name, frag,
-						skb_shinfo(skb)->nr_frags);
-				goto linear;
-			}
-		}
-
 		/* first frag which is skb header */
 		pkt_info.byte_cnt = skb_headlen(skb);
 		pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
@@ -1221,14 +1176,16 @@
 					   ETH_GEN_IP_V_4_CHECKSUM |
 					   skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
 			/* CPU already calculated pseudo header checksum. */
-			if (skb->nh.iph->protocol == IPPROTO_UDP) {
+			if ((skb->protocol == ETH_P_IP) &&
+			    (skb->nh.iph->protocol == IPPROTO_UDP)) {
 				pkt_info.cmd_sts |= ETH_UDP_FRAME;
 				pkt_info.l4i_chk = skb->h.uh->check;
-			} else if (skb->nh.iph->protocol == IPPROTO_TCP)
+			} else if ((skb->protocol == ETH_P_IP) &&
+				   (skb->nh.iph->protocol == IPPROTO_TCP))
 				pkt_info.l4i_chk = skb->h.th->check;
 			else {
 				printk(KERN_ERR
-					"%s: chksum proto != TCP or UDP\n",
+					"%s: chksum proto != IPv4 TCP or UDP\n",
 					dev->name);
 				spin_unlock_irqrestore(&mp->lock, flags);
 				return 1;
@@ -1288,6 +1245,8 @@
 		}
 	}
 #else
+	spin_lock_irqsave(&mp->lock, flags);
+
 	pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC |
 							ETH_TX_LAST_DESC;
 	pkt_info.l4i_chk = 0;
@@ -1340,39 +1299,18 @@
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-static inline void mv643xx_enable_irq(struct mv643xx_private *mp)
-{
-	int port_num = mp->port_num;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mp->lock, flags);
-	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-					INT_CAUSE_UNMASK_ALL);
-	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
-					INT_CAUSE_UNMASK_ALL_EXT);
-	spin_unlock_irqrestore(&mp->lock, flags);
-}
-
-static inline void mv643xx_disable_irq(struct mv643xx_private *mp)
-{
-	int port_num = mp->port_num;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mp->lock, flags);
-	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
-					INT_CAUSE_MASK_ALL);
-	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
-					INT_CAUSE_MASK_ALL_EXT);
-	spin_unlock_irqrestore(&mp->lock, flags);
-}
-
 static void mv643xx_netpoll(struct net_device *netdev)
 {
 	struct mv643xx_private *mp = netdev_priv(netdev);
+	int port_num = mp->port_num;
 
-	mv643xx_disable_irq(mp);
+	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+	/* wait for previous write to complete */
+	mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
 	mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
-	mv643xx_enable_irq(mp);
+
+	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
 }
 #endif
 
@@ -1441,7 +1379,7 @@
 	 * Zero copy can only work if we use Discovery II memory. Else, we will
 	 * have to map the buffers to ISA memory which is only 16 MB
 	 */
-	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_CSUM;
+	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
 #endif
 #endif
 
@@ -2054,6 +1992,196 @@
 }
 
 /*
+ * The entries in each table are indexed by a hash of a packet's MAC
+ * address.  One bit in each entry determines whether the packet is
+ * accepted.  There are 4 entries (each 8 bits wide) in each register
+ * of the table.  The bits in each entry are defined as follows:
+ *	0	Accept=1, Drop=0
+ *	3-1	Queue			(ETH_Q0=0)
+ *	7-4	Reserved = 0;
+ */
+static void eth_port_set_filter_table_entry(int table, unsigned char entry)
+{
+	unsigned int table_reg;
+	unsigned int tbl_offset;
+	unsigned int reg_offset;
+
+	tbl_offset = (entry / 4) * 4;	/* Register offset of DA table entry */
+	reg_offset = entry % 4;		/* Entry offset within the register */
+
+	/* Set "accepts frame bit" at specified table entry */
+	table_reg = mv_read(table + tbl_offset);
+	table_reg |= 0x01 << (8 * reg_offset);
+	mv_write(table + tbl_offset, table_reg);
+}
+
+/*
+ * eth_port_mc_addr - Multicast address settings.
+ *
+ * The MV device supports multicast using two tables:
+ * 1) Special Multicast Table for MAC addresses of the form
+ *    0x01-00-5E-00-00-XX (where XX is between 0x00 and 0x_FF).
+ *    The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+ *    Table entries in the DA-Filter table.
+ * 2) Other Multicast Table for multicast of another type. A CRC-8bit
+ *    is used as an index to the Other Multicast Table entries in the
+ *    DA-Filter table.  This function calculates the CRC-8bit value.
+ * In either case, eth_port_set_filter_table_entry() is then called
+ * to set to set the actual table entry.
+ */
+static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
+{
+	unsigned int mac_h;
+	unsigned int mac_l;
+	unsigned char crc_result = 0;
+	int table;
+	int mac_array[48];
+	int crc[8];
+	int i;
+
+	if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) &&
+	    (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) {
+		table = MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+					(eth_port_num);
+		eth_port_set_filter_table_entry(table, p_addr[5]);
+		return;
+	}
+
+	/* Calculate CRC-8 out of the given address */
+	mac_h = (p_addr[0] << 8) | (p_addr[1]);
+	mac_l = (p_addr[2] << 24) | (p_addr[3] << 16) |
+			(p_addr[4] << 8) | (p_addr[5] << 0);
+
+	for (i = 0; i < 32; i++)
+		mac_array[i] = (mac_l >> i) & 0x1;
+	for (i = 32; i < 48; i++)
+		mac_array[i] = (mac_h >> (i - 32)) & 0x1;
+
+	crc[0] = mac_array[45] ^ mac_array[43] ^ mac_array[40] ^ mac_array[39] ^
+		 mac_array[35] ^ mac_array[34] ^ mac_array[31] ^ mac_array[30] ^
+		 mac_array[28] ^ mac_array[23] ^ mac_array[21] ^ mac_array[19] ^
+		 mac_array[18] ^ mac_array[16] ^ mac_array[14] ^ mac_array[12] ^
+		 mac_array[8]  ^ mac_array[7]  ^ mac_array[6]  ^ mac_array[0];
+
+	crc[1] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^
+		 mac_array[41] ^ mac_array[39] ^ mac_array[36] ^ mac_array[34] ^
+		 mac_array[32] ^ mac_array[30] ^ mac_array[29] ^ mac_array[28] ^
+		 mac_array[24] ^ mac_array[23] ^ mac_array[22] ^ mac_array[21] ^
+		 mac_array[20] ^ mac_array[18] ^ mac_array[17] ^ mac_array[16] ^
+		 mac_array[15] ^ mac_array[14] ^ mac_array[13] ^ mac_array[12] ^
+		 mac_array[9]  ^ mac_array[6]  ^ mac_array[1]  ^ mac_array[0];
+
+	crc[2] = mac_array[47] ^ mac_array[46] ^ mac_array[44] ^ mac_array[43] ^
+		 mac_array[42] ^ mac_array[39] ^ mac_array[37] ^ mac_array[34] ^
+		 mac_array[33] ^ mac_array[29] ^ mac_array[28] ^ mac_array[25] ^
+		 mac_array[24] ^ mac_array[22] ^ mac_array[17] ^ mac_array[15] ^
+		 mac_array[13] ^ mac_array[12] ^ mac_array[10] ^ mac_array[8]  ^
+		 mac_array[6]  ^ mac_array[2]  ^ mac_array[1]  ^ mac_array[0];
+
+	crc[3] = mac_array[47] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^
+		 mac_array[40] ^ mac_array[38] ^ mac_array[35] ^ mac_array[34] ^
+		 mac_array[30] ^ mac_array[29] ^ mac_array[26] ^ mac_array[25] ^
+		 mac_array[23] ^ mac_array[18] ^ mac_array[16] ^ mac_array[14] ^
+		 mac_array[13] ^ mac_array[11] ^ mac_array[9]  ^ mac_array[7]  ^
+		 mac_array[3]  ^ mac_array[2]  ^ mac_array[1];
+
+	crc[4] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[41] ^
+		 mac_array[39] ^ mac_array[36] ^ mac_array[35] ^ mac_array[31] ^
+		 mac_array[30] ^ mac_array[27] ^ mac_array[26] ^ mac_array[24] ^
+		 mac_array[19] ^ mac_array[17] ^ mac_array[15] ^ mac_array[14] ^
+		 mac_array[12] ^ mac_array[10] ^ mac_array[8]  ^ mac_array[4]  ^
+		 mac_array[3]  ^ mac_array[2];
+
+	crc[5] = mac_array[47] ^ mac_array[46] ^ mac_array[45] ^ mac_array[42] ^
+		 mac_array[40] ^ mac_array[37] ^ mac_array[36] ^ mac_array[32] ^
+		 mac_array[31] ^ mac_array[28] ^ mac_array[27] ^ mac_array[25] ^
+		 mac_array[20] ^ mac_array[18] ^ mac_array[16] ^ mac_array[15] ^
+		 mac_array[13] ^ mac_array[11] ^ mac_array[9]  ^ mac_array[5]  ^
+		 mac_array[4]  ^ mac_array[3];
+
+	crc[6] = mac_array[47] ^ mac_array[46] ^ mac_array[43] ^ mac_array[41] ^
+		 mac_array[38] ^ mac_array[37] ^ mac_array[33] ^ mac_array[32] ^
+		 mac_array[29] ^ mac_array[28] ^ mac_array[26] ^ mac_array[21] ^
+		 mac_array[19] ^ mac_array[17] ^ mac_array[16] ^ mac_array[14] ^
+		 mac_array[12] ^ mac_array[10] ^ mac_array[6]  ^ mac_array[5]  ^
+		 mac_array[4];
+
+	crc[7] = mac_array[47] ^ mac_array[44] ^ mac_array[42] ^ mac_array[39] ^
+		 mac_array[38] ^ mac_array[34] ^ mac_array[33] ^ mac_array[30] ^
+		 mac_array[29] ^ mac_array[27] ^ mac_array[22] ^ mac_array[20] ^
+		 mac_array[18] ^ mac_array[17] ^ mac_array[15] ^ mac_array[13] ^
+		 mac_array[11] ^ mac_array[7]  ^ mac_array[6]  ^ mac_array[5];
+
+	for (i = 0; i < 8; i++)
+		crc_result = crc_result | (crc[i] << i);
+
+	table = MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
+	eth_port_set_filter_table_entry(table, crc_result);
+}
+
+/*
+ * Set the entire multicast list based on dev->mc_list.
+ */
+static void eth_port_set_multicast_list(struct net_device *dev)
+{
+
+	struct dev_mc_list	*mc_list;
+	int			i;
+	int			table_index;
+	struct mv643xx_private	*mp = netdev_priv(dev);
+	unsigned int		eth_port_num = mp->port_num;
+
+	/* If the device is in promiscuous mode or in all multicast mode,
+	 * we will fully populate both multicast tables with accept.
+	 * This is guaranteed to yield a match on all multicast addresses...
+	 */
+	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 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;
+	}
+
+	/* We will clear out multicast tables every time we get the list.
+	 * Then add the entire new list...
+	 */
+	for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+		/* Clear DA filter special multicast table (Ex_dFSMT) */
+		mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+				(eth_port_num) + table_index, 0);
+
+		/* Clear DA filter other multicast table (Ex_dFOMT) */
+		mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+				(eth_port_num) + table_index, 0);
+	}
+
+	/* Get pointer to net_device multicast list and add each one... */
+	for (i = 0, mc_list = dev->mc_list;
+			(i < 256) && (mc_list != NULL) && (i < dev->mc_count);
+			i++, mc_list = mc_list->next)
+		if (mc_list->dmi_addrlen == 6)
+			eth_port_mc_addr(eth_port_num, mc_list->dmi_addr);
+}
+
+/*
  * eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
  *
  * DESCRIPTION:
@@ -2080,11 +2208,11 @@
 
 	for (table_index = 0; table_index <= 0xFC; table_index += 4) {
 		/* Clear DA filter special multicast table (Ex_dFSMT) */
-		mv_write((MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
-					(eth_port_num) + table_index), 0);
+		mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+					(eth_port_num) + table_index, 0);
 		/* Clear DA filter other multicast table (Ex_dFOMT) */
-		mv_write((MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
-					(eth_port_num) + table_index), 0);
+		mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+					(eth_port_num) + table_index, 0);
 	}
 }
 
@@ -2489,6 +2617,7 @@
 	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)
@@ -2505,6 +2634,8 @@
 		return ETH_ERROR;
 	}
 
+	spin_lock_irqsave(&mp->lock, flags);
+
 	mp->tx_ring_skbs++;
 	BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
 
@@ -2554,11 +2685,15 @@
 		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
@@ -2569,11 +2704,14 @@
 	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);
 
@@ -2604,9 +2742,12 @@
 	/* 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
@@ -2629,23 +2770,27 @@
  *	Tx ring 'first' and 'used' indexes are updated.
  *
  * RETURN:
- *	ETH_ERROR in case the routine can not access Tx desc ring.
- *	ETH_RETRY in case there is transmission in process.
- *	ETH_END_OF_JOB if the routine has nothing to release.
- *	ETH_OK otherwise.
+ *	ETH_OK on success
+ *	ETH_ERROR otherwise.
  *
  */
 static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
 						struct pkt_info *p_pkt_info)
 {
 	int tx_desc_used;
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
-	int tx_busy_desc = mp->tx_first_desc_q;
-#else
-	int tx_busy_desc = mp->tx_curr_desc_q;
-#endif
+	int tx_busy_desc;
 	struct eth_tx_desc *p_tx_desc_used;
 	unsigned int command_status;
+	unsigned long flags;
+	int err = ETH_OK;
+
+	spin_lock_irqsave(&mp->lock, flags);
+
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+	tx_busy_desc = mp->tx_first_desc_q;
+#else
+	tx_busy_desc = mp->tx_curr_desc_q;
+#endif
 
 	/* Get the Tx Desc ring indexes */
 	tx_desc_used = mp->tx_used_desc_q;
@@ -2653,22 +2798,30 @@
 	p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used];
 
 	/* Sanity check */
-	if (p_tx_desc_used == NULL)
-		return ETH_ERROR;
+	if (p_tx_desc_used == NULL) {
+		err = ETH_ERROR;
+		goto out;
+	}
 
 	/* Stop release. About to overlap the current available Tx descriptor */
-	if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err)
-		return ETH_END_OF_JOB;
+	if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err) {
+		err = ETH_ERROR;
+		goto out;
+	}
 
 	command_status = p_tx_desc_used->cmd_sts;
 
 	/* Still transmitting... */
-	if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
-		return ETH_RETRY;
+	if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+		err = ETH_ERROR;
+		goto out;
+	}
 
 	/* Pass the packet information to the caller */
 	p_pkt_info->cmd_sts = command_status;
 	p_pkt_info->return_info = mp->tx_skb[tx_desc_used];
+	p_pkt_info->buf_ptr = p_tx_desc_used->buf_ptr;
+	p_pkt_info->byte_cnt = p_tx_desc_used->byte_cnt;
 	mp->tx_skb[tx_desc_used] = NULL;
 
 	/* Update the next descriptor to release. */
@@ -2680,7 +2833,10 @@
 	BUG_ON(mp->tx_ring_skbs == 0);
 	mp->tx_ring_skbs--;
 
-	return ETH_OK;
+out:
+	spin_unlock_irqrestore(&mp->lock, flags);
+
+	return err;
 }
 
 /*
@@ -2712,11 +2868,14 @@
 	int rx_next_curr_desc, rx_curr_desc, rx_used_desc;
 	volatile struct eth_rx_desc *p_rx_desc;
 	unsigned int command_status;
+	unsigned long flags;
 
 	/* Do not process Rx ring in case of Rx ring resource error */
 	if (mp->rx_resource_err)
 		return ETH_QUEUE_FULL;
 
+	spin_lock_irqsave(&mp->lock, flags);
+
 	/* Get the Rx Desc ring 'curr and 'used' indexes */
 	rx_curr_desc = mp->rx_curr_desc_q;
 	rx_used_desc = mp->rx_used_desc_q;
@@ -2728,8 +2887,10 @@
 	rmb();
 
 	/* Nothing to receive... */
-	if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
+	if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+		spin_unlock_irqrestore(&mp->lock, flags);
 		return ETH_END_OF_JOB;
+	}
 
 	p_pkt_info->byte_cnt = (p_rx_desc->byte_cnt) - RX_BUF_OFFSET;
 	p_pkt_info->cmd_sts = command_status;
@@ -2749,6 +2910,8 @@
 	if (rx_next_curr_desc == rx_used_desc)
 		mp->rx_resource_err = 1;
 
+	spin_unlock_irqrestore(&mp->lock, flags);
+
 	return ETH_OK;
 }
 
@@ -2777,6 +2940,9 @@
 {
 	int used_rx_desc;	/* Where to return Rx resource */
 	volatile struct eth_rx_desc *p_used_rx_desc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mp->lock, flags);
 
 	/* Get 'used' Rx descriptor */
 	used_rx_desc = mp->rx_used_desc_q;
@@ -2800,6 +2966,8 @@
 	/* Any Rx return cancels the Rx resource error status */
 	mp->rx_resource_err = 0;
 
+	spin_unlock_irqrestore(&mp->lock, flags);
+
 	return ETH_OK;
 }
 
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index b538e30..bf55a4c 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -3243,12 +3243,22 @@
 
 	pci_set_master(pdev);
 
-	if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)))
+	if (sizeof(dma_addr_t) > sizeof(u32) &&
+	    !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
 		using_dac = 1;
-	else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
-		printk(KERN_ERR PFX "%s no usable DMA configuration\n",
-		       pci_name(pdev));
-		goto err_out_free_regions;
+		err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+		if (err < 0) {
+			printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA "
+			       "for consistent allocations\n", pci_name(pdev));
+			goto err_out_free_regions;
+		}
+	} else {
+		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		if (err) {
+			printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+			       pci_name(pdev));
+			goto err_out_free_regions;
+		}
 	}
 
 #ifdef __BIG_ENDIAN
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index f5d697c..f8b973a 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -57,7 +57,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"0.11"
+#define DRV_VERSION		"0.13"
 #define PFX			DRV_NAME " "
 
 /*
@@ -75,6 +75,7 @@
 #define RX_LE_BYTES		(RX_LE_SIZE*sizeof(struct sky2_rx_le))
 #define RX_MAX_PENDING		(RX_LE_SIZE/2 - 2)
 #define RX_DEF_PENDING		RX_MAX_PENDING
+#define RX_SKB_ALIGN		8
 
 #define TX_RING_SIZE		512
 #define TX_DEF_PENDING		(TX_RING_SIZE - 1)
@@ -91,7 +92,7 @@
 static const u32 default_msg =
     NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
     | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
-    | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_INTR;
+    | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
 
 static int debug = -1;		/* defaults above */
 module_param(debug, int, 0);
@@ -624,13 +625,16 @@
 
 }
 
-static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, size_t len)
+/* Assign Ram Buffer allocation.
+ * start and end are in units of 4k bytes
+ * ram registers are in units of 64bit words
+ */
+static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk)
 {
-	u32 end;
+	u32 start, end;
 
-	start /= 8;
-	len /= 8;
-	end = start + len - 1;
+	start = startk * 4096/8;
+	end = (endk * 4096/8) - 1;
 
 	sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
 	sky2_write32(hw, RB_ADDR(q, RB_START), start);
@@ -639,14 +643,19 @@
 	sky2_write32(hw, RB_ADDR(q, RB_RP), start);
 
 	if (q == Q_R1 || q == Q_R2) {
-		u32 rxup, rxlo;
+		u32 space = (endk - startk) * 4096/8;
+		u32 tp = space - space/4;
 
-		rxlo = len/2;
-		rxup = rxlo + len/4;
+		/* On receive queue's set the thresholds
+		 * give receiver priority when > 3/4 full
+		 * send pause when down to 2K
+		 */
+		sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
+		sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
 
-		/* Set thresholds on receive queue's */
-		sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), rxup);
-		sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), rxlo);
+		tp = space - 2048/8;
+		sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
+		sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
 	} else {
 		/* Enable store & forward on Tx queue's because
 		 * Tx FIFO is only 1K on Yukon
@@ -695,9 +704,10 @@
  * This is a workaround code taken from SysKonnect sk98lin driver
  * to deal with chip bug on Yukon EC rev 0 in the wraparound case.
  */
-static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q,
+static void sky2_put_idx(struct sky2_hw *hw, unsigned q,
 				u16 idx, u16 *last, u16 size)
 {
+	wmb();
 	if (is_ec_a1(hw) && idx < *last) {
 		u16 hwget = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX));
 
@@ -721,6 +731,7 @@
 		sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
 	}
 	*last = idx;
+	mmiowb();
 }
 
 
@@ -734,11 +745,11 @@
 /* Return high part of DMA address (could be 32 or 64 bit) */
 static inline u32 high32(dma_addr_t a)
 {
-	return (a >> 16) >> 16;
+	return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
 }
 
 /* Build description to hardware about buffer */
-static inline void sky2_rx_add(struct sky2_port *sky2, dma_addr_t map)
+static void sky2_rx_add(struct sky2_port *sky2, dma_addr_t map)
 {
 	struct sky2_rx_le *le;
 	u32 hi = high32(map);
@@ -878,13 +889,13 @@
 	struct sky2_hw *hw = sky2->hw;
 	u16 port = sky2->port;
 
-	spin_lock(&sky2->tx_lock);
+	spin_lock_bh(&sky2->tx_lock);
 
 	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON);
 	sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON);
 	sky2->vlgrp = grp;
 
-	spin_unlock(&sky2->tx_lock);
+	spin_unlock_bh(&sky2->tx_lock);
 }
 
 static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
@@ -893,27 +904,42 @@
 	struct sky2_hw *hw = sky2->hw;
 	u16 port = sky2->port;
 
-	spin_lock(&sky2->tx_lock);
+	spin_lock_bh(&sky2->tx_lock);
 
 	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF);
 	sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF);
 	if (sky2->vlgrp)
 		sky2->vlgrp->vlan_devices[vid] = NULL;
 
-	spin_unlock(&sky2->tx_lock);
+	spin_unlock_bh(&sky2->tx_lock);
 }
 #endif
 
 /*
+ * It appears the hardware has a bug in the FIFO logic that
+ * cause it to hang if the FIFO gets overrun and the receive buffer
+ * is not aligned. ALso alloc_skb() won't align properly if slab
+ * debugging is enabled.
+ */
+static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
+	if (likely(skb)) {
+		unsigned long p	= (unsigned long) skb->data;
+		skb_reserve(skb,
+			((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p);
+	}
+
+	return skb;
+}
+
+/*
  * Allocate and setup receiver buffer pool.
  * In case of 64 bit dma, there are 2X as many list elements
  * available as ring entries
  * and need to reserve one list element so we don't wrap around.
- *
- * It appears the hardware has a bug in the FIFO logic that
- * cause it to hang if the FIFO gets overrun and the receive buffer
- * is not aligned.  This means we can't use skb_reserve to align
- * the IP header.
  */
 static int sky2_rx_start(struct sky2_port *sky2)
 {
@@ -929,7 +955,7 @@
 	for (i = 0; i < sky2->rx_pending; i++) {
 		struct ring_info *re = sky2->rx_ring + i;
 
-		re->skb = dev_alloc_skb(sky2->rx_bufsize);
+		re->skb = sky2_alloc_skb(sky2->rx_bufsize, GFP_KERNEL);
 		if (!re->skb)
 			goto nomem;
 
@@ -986,19 +1012,19 @@
 
 	sky2_mac_init(hw, port);
 
-	/* Configure RAM buffers */
-	if (hw->chip_id == CHIP_ID_YUKON_FE ||
-	    (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == 2))
-		ramsize = 4096;
-	else {
-		u8 e0 = sky2_read8(hw, B2_E_0);
-		ramsize = (e0 == 0) ? (128 * 1024) : (e0 * 4096);
-	}
+	/* Determine available ram buffer space (in 4K blocks).
+	 * Note: not sure about the FE setting below yet
+	 */
+	if (hw->chip_id == CHIP_ID_YUKON_FE)
+		ramsize = 4;
+	else
+		ramsize = sky2_read8(hw, B2_E_0);
 
-	/* 2/3 for Rx */
-	rxspace = (2 * ramsize) / 3;
+	/* Give transmitter one third (rounded up) */
+	rxspace = ramsize - (ramsize + 2) / 3;
+
 	sky2_ramset(hw, rxqaddr[port], 0, rxspace);
-	sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace);
+	sky2_ramset(hw, txqaddr[port], rxspace, ramsize);
 
 	/* Make sure SyncQ is disabled */
 	sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
@@ -1054,7 +1080,7 @@
 }
 
 /* Estimate of number of transmit list elements required */
-static inline unsigned tx_le_req(const struct sk_buff *skb)
+static unsigned tx_le_req(const struct sk_buff *skb)
 {
 	unsigned count;
 
@@ -1090,6 +1116,10 @@
 	u16 mss;
 	u8 ctrl;
 
+	/* No BH disabling for tx_lock here.  We are running in BH disabled
+	 * context and TX reclaim runs via poll inside of a software
+	 * interrupt, and no related locks in IRQ processing.
+	 */
 	if (!spin_trylock(&sky2->tx_lock))
 		return NETDEV_TX_LOCKED;
 
@@ -1099,8 +1129,9 @@
 		 */
 		if (!netif_queue_stopped(dev)) {
 			netif_stop_queue(dev);
-			printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
-			       dev->name);
+			if (net_ratelimit())
+				printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
+				       dev->name);
 		}
 		spin_unlock(&sky2->tx_lock);
 
@@ -1199,7 +1230,7 @@
 
 		mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
 				       frag->size, PCI_DMA_TODEVICE);
-		addr64 = (mapping >> 16) >> 16;
+		addr64 = high32(mapping);
 		if (addr64 != sky2->tx_addr64) {
 			le = get_tx_le(sky2);
 			le->tx.addr = cpu_to_le32(addr64);
@@ -1229,7 +1260,6 @@
 		netif_stop_queue(dev);
 
 out_unlock:
-	mmiowb();
 	spin_unlock(&sky2->tx_lock);
 
 	dev->trans_start = jiffies;
@@ -1282,17 +1312,17 @@
 		dev_kfree_skb_any(skb);
 	}
 
-	spin_lock(&sky2->tx_lock);
 	sky2->tx_cons = put;
 	if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE)
 		netif_wake_queue(dev);
-	spin_unlock(&sky2->tx_lock);
 }
 
 /* Cleanup all untransmitted buffers, assume transmitter not running */
 static void sky2_tx_clean(struct sky2_port *sky2)
 {
+	spin_lock_bh(&sky2->tx_lock);
 	sky2_tx_complete(sky2, sky2->tx_prod);
+	spin_unlock_bh(&sky2->tx_lock);
 }
 
 /* Network shutdown */
@@ -1582,28 +1612,40 @@
 	local_irq_enable();
 }
 
+
+/* Transmit timeout is only called if we are running, carries is up
+ * and tx queue is full (stopped).
+ */
 static void sky2_tx_timeout(struct net_device *dev)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 	struct sky2_hw *hw = sky2->hw;
 	unsigned txq = txqaddr[sky2->port];
+	u16 ridx;
+
+	/* Maybe we just missed an status interrupt */
+	spin_lock(&sky2->tx_lock);
+	ridx = sky2_read16(hw,
+			   sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX);
+	sky2_tx_complete(sky2, ridx);
+	spin_unlock(&sky2->tx_lock);
+
+	if (!netif_queue_stopped(dev)) {
+		if (net_ratelimit())
+			pr_info(PFX "transmit interrupt missed? recovered\n");
+		return;
+	}
 
 	if (netif_msg_timer(sky2))
 		printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
 
-	netif_stop_queue(dev);
-
 	sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP);
-	sky2_read32(hw, Q_ADDR(txq, Q_CSR));
-
 	sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
 
 	sky2_tx_clean(sky2);
 
 	sky2_qset(hw, txq);
 	sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1);
-
-	netif_wake_queue(dev);
 }
 
 
@@ -1713,7 +1755,7 @@
 	} else {
 		struct sk_buff *nskb;
 
-		nskb = dev_alloc_skb(sky2->rx_bufsize);
+		nskb = sky2_alloc_skb(sky2->rx_bufsize, GFP_ATOMIC);
 		if (!nskb)
 			goto resubmit;
 
@@ -1745,7 +1787,7 @@
 error:
 	++sky2->net_stats.rx_errors;
 
-	if (netif_msg_rx_err(sky2))
+	if (netif_msg_rx_err(sky2) && net_ratelimit())
 		printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n",
 		       sky2->netdev->name, status, length);
 
@@ -1766,13 +1808,16 @@
  */
 #define TX_NO_STATUS	0xffff
 
-static inline void sky2_tx_check(struct sky2_hw *hw, int port, u16 last)
+static void sky2_tx_check(struct sky2_hw *hw, int port, u16 last)
 {
 	if (last != TX_NO_STATUS) {
 		struct net_device *dev = hw->dev[port];
 		if (dev && netif_running(dev)) {
 			struct sky2_port *sky2 = netdev_priv(dev);
+
+			spin_lock(&sky2->tx_lock);
 			sky2_tx_complete(sky2, last);
+			spin_unlock(&sky2->tx_lock);
 		}
 	}
 }
@@ -1800,7 +1845,6 @@
 		struct sk_buff *skb;
 		u32 status;
 		u16 length;
-		u8 op;
 
 		le = hw->st_le + hw->st_idx;
 		hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
@@ -1814,10 +1858,8 @@
 		sky2 = netdev_priv(dev);
 		status = le32_to_cpu(le->status);
 		length = le16_to_cpu(le->length);
-		op = le->opcode & ~HW_OWNER;
-		le->opcode = 0;
 
-		switch (op) {
+		switch (le->opcode & ~HW_OWNER) {
 		case OP_RXSTAT:
 			skb = sky2_receive(sky2, length, status);
 			if (!skb)
@@ -1865,14 +1907,13 @@
 		default:
 			if (net_ratelimit())
 				printk(KERN_WARNING PFX
-				       "unknown status opcode 0x%x\n", op);
+				       "unknown status opcode 0x%x\n", le->opcode);
 			break;
 		}
 	}
 
 exit_loop:
 	sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-	mmiowb();
 
 	sky2_tx_check(hw, 0, tx_done[0]);
 	sky2_tx_check(hw, 1, tx_done[1]);
@@ -1887,7 +1928,6 @@
 		netif_rx_complete(dev0);
 		hw->intr_mask |= Y2_IS_STAT_BMU;
 		sky2_write32(hw, B0_IMSK, hw->intr_mask);
-		mmiowb();
 		return 0;
 	} else {
 		*budget -= work_done;
@@ -1900,35 +1940,42 @@
 {
 	struct net_device *dev = hw->dev[port];
 
-	printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n",
-	       dev->name, status);
+	if (net_ratelimit())
+		printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n",
+		       dev->name, status);
 
 	if (status & Y2_IS_PAR_RD1) {
-		printk(KERN_ERR PFX "%s: ram data read parity error\n",
-		       dev->name);
+		if (net_ratelimit())
+			printk(KERN_ERR PFX "%s: ram data read parity error\n",
+			       dev->name);
 		/* Clear IRQ */
 		sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR);
 	}
 
 	if (status & Y2_IS_PAR_WR1) {
-		printk(KERN_ERR PFX "%s: ram data write parity error\n",
-		       dev->name);
+		if (net_ratelimit())
+			printk(KERN_ERR PFX "%s: ram data write parity error\n",
+			       dev->name);
 
 		sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR);
 	}
 
 	if (status & Y2_IS_PAR_MAC1) {
-		printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name);
+		if (net_ratelimit())
+			printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name);
 		sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);
 	}
 
 	if (status & Y2_IS_PAR_RX1) {
-		printk(KERN_ERR PFX "%s: RX parity error\n", dev->name);
+		if (net_ratelimit())
+			printk(KERN_ERR PFX "%s: RX parity error\n", dev->name);
 		sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR);
 	}
 
 	if (status & Y2_IS_TCP_TXA1) {
-		printk(KERN_ERR PFX "%s: TCP segmentation error\n", dev->name);
+		if (net_ratelimit())
+			printk(KERN_ERR PFX "%s: TCP segmentation error\n",
+			       dev->name);
 		sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP);
 	}
 }
@@ -1944,8 +1991,9 @@
 		u16 pci_err;
 
 		pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err);
-		printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
-		       pci_name(hw->pdev), pci_err);
+		if (net_ratelimit())
+			printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
+			       pci_name(hw->pdev), pci_err);
 
 		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 		pci_write_config_word(hw->pdev, PCI_STATUS,
@@ -1959,8 +2007,9 @@
 
 		pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err);
 
-		printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
-		       pci_name(hw->pdev), pex_err);
+		if (net_ratelimit())
+			printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
+			       pci_name(hw->pdev), pex_err);
 
 		/* clear the interrupt */
 		sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
@@ -2250,7 +2299,7 @@
 	return 0;
 }
 
-static inline u32 sky2_supported_modes(const struct sky2_hw *hw)
+static u32 sky2_supported_modes(const struct sky2_hw *hw)
 {
 	u32 modes;
 	if (hw->copper) {
@@ -2995,7 +3044,7 @@
 	return dev;
 }
 
-static inline void sky2_show_addr(struct net_device *dev)
+static void __devinit sky2_show_addr(struct net_device *dev)
 {
 	const struct sky2_port *sky2 = netdev_priv(dev);
 
@@ -3038,13 +3087,17 @@
 		goto err_out_free_regions;
 	}
 
-	if (sizeof(dma_addr_t) > sizeof(u32)) {
-		err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
-		if (!err)
-			using_dac = 1;
-	}
+	if (sizeof(dma_addr_t) > sizeof(u32) &&
+	    !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+		using_dac = 1;
+		err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+		if (err < 0) {
+			printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA "
+			       "for consistent allocations\n", pci_name(pdev));
+			goto err_out_free_regions;
+		}
 
-	if (!using_dac) {
+	} else {
 		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (err) {
 			printk(KERN_ERR PFX "%s no usable DMA configuration\n",
@@ -3052,6 +3105,7 @@
 			goto err_out_free_regions;
 		}
 	}
+
 #ifdef __BIG_ENDIAN
 	/* byte swap descriptors in hardware */
 	{
@@ -3064,14 +3118,13 @@
 #endif
 
 	err = -ENOMEM;
-	hw = kmalloc(sizeof(*hw), GFP_KERNEL);
+	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
 	if (!hw) {
 		printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n",
 		       pci_name(pdev));
 		goto err_out_free_regions;
 	}
 
-	memset(hw, 0, sizeof(*hw));
 	hw->pdev = pdev;
 
 	hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 0d765f1..1f5975a 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -22,7 +22,6 @@
  */
 
 #include <linux/config.h>
-
 #include <linux/compiler.h>
 #include <linux/crc32.h>
 #include <linux/delay.h>
@@ -30,6 +29,7 @@
 #include <linux/ethtool.h>
 #include <linux/firmware.h>
 #include <linux/if_vlan.h>
+#include <linux/in.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/ip.h>
@@ -43,6 +43,7 @@
 #include <linux/slab.h>
 #include <linux/tcp.h>
 #include <linux/types.h>
+#include <linux/vmalloc.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <asm/bitops.h>
@@ -108,42 +109,6 @@
 	writel(value, card->regs + reg);
 }
 
-/**
- * spider_net_write_reg_sync - writes to an SMMIO register of a card
- * @card: device structure
- * @reg: register to write to
- * @value: value to write into the specified SMMIO register
- *
- * Unlike spider_net_write_reg, this will also make sure the
- * data arrives on the card by reading the reg again.
- */
-static void
-spider_net_write_reg_sync(struct spider_net_card *card, u32 reg, u32 value)
-{
-	value = cpu_to_le32(value);
-	writel(value, card->regs + reg);
-	(void)readl(card->regs + reg);
-}
-
-/**
- * spider_net_rx_irq_off - switch off rx irq on this spider card
- * @card: device structure
- *
- * switches off rx irq by masking them out in the GHIINTnMSK register
- */
-static void
-spider_net_rx_irq_off(struct spider_net_card *card)
-{
-	u32 regvalue;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->intmask_lock, flags);
-	regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
-	regvalue &= ~SPIDER_NET_RXINT;
-	spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
-	spin_unlock_irqrestore(&card->intmask_lock, flags);
-}
-
 /** spider_net_write_phy - write to phy register
  * @netdev: adapter to be written to
  * @mii_id: id of MII
@@ -199,6 +164,21 @@
 }
 
 /**
+ * spider_net_rx_irq_off - switch off rx irq on this spider card
+ * @card: device structure
+ *
+ * switches off rx irq by masking them out in the GHIINTnMSK register
+ */
+static void
+spider_net_rx_irq_off(struct spider_net_card *card)
+{
+	u32 regvalue;
+
+	regvalue = SPIDER_NET_INT0_MASK_VALUE & (~SPIDER_NET_RXINT);
+	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
+}
+
+/**
  * spider_net_rx_irq_on - switch on rx irq on this spider card
  * @card: device structure
  *
@@ -208,51 +188,9 @@
 spider_net_rx_irq_on(struct spider_net_card *card)
 {
 	u32 regvalue;
-	unsigned long flags;
 
-	spin_lock_irqsave(&card->intmask_lock, flags);
-	regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
-	regvalue |= SPIDER_NET_RXINT;
-	spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
-	spin_unlock_irqrestore(&card->intmask_lock, flags);
-}
-
-/**
- * spider_net_tx_irq_off - switch off tx irq on this spider card
- * @card: device structure
- *
- * switches off tx irq by masking them out in the GHIINTnMSK register
- */
-static void
-spider_net_tx_irq_off(struct spider_net_card *card)
-{
-	u32 regvalue;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->intmask_lock, flags);
-	regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
-	regvalue &= ~SPIDER_NET_TXINT;
-	spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
-	spin_unlock_irqrestore(&card->intmask_lock, flags);
-}
-
-/**
- * spider_net_tx_irq_on - switch on tx irq on this spider card
- * @card: device structure
- *
- * switches on tx irq by enabling them in the GHIINTnMSK register
- */
-static void
-spider_net_tx_irq_on(struct spider_net_card *card)
-{
-	u32 regvalue;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->intmask_lock, flags);
-	regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
-	regvalue |= SPIDER_NET_TXINT;
-	spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
-	spin_unlock_irqrestore(&card->intmask_lock, flags);
+	regvalue = SPIDER_NET_INT0_MASK_VALUE | SPIDER_NET_RXINT;
+	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
 }
 
 /**
@@ -326,9 +264,8 @@
 spider_net_get_descr_status(struct spider_net_descr *descr)
 {
 	u32 cmd_status;
-	rmb();
+
 	cmd_status = descr->dmac_cmd_status;
-	rmb();
 	cmd_status >>= SPIDER_NET_DESCR_IND_PROC_SHIFT;
 	/* no need to mask out any bits, as cmd_status is 32 bits wide only
 	 * (and unsigned) */
@@ -349,7 +286,6 @@
 {
 	u32 cmd_status;
 	/* read the status */
-	mb();
 	cmd_status = descr->dmac_cmd_status;
 	/* clean the upper 4 bits */
 	cmd_status &= SPIDER_NET_DESCR_IND_PROC_MASKO;
@@ -357,7 +293,6 @@
 	cmd_status |= ((u32)status)<<SPIDER_NET_DESCR_IND_PROC_SHIFT;
 	/* and write it back */
 	descr->dmac_cmd_status = cmd_status;
-	wmb();
 }
 
 /**
@@ -398,8 +333,9 @@
 {
 	int i;
 	struct spider_net_descr *descr;
+	dma_addr_t buf;
 
-	spin_lock_init(&card->chain_lock);
+	atomic_set(&card->rx_chain_refill,0);
 
 	descr = start_descr;
 	memset(descr, 0, sizeof(*descr) * no);
@@ -408,14 +344,14 @@
 	for (i=0; i<no; i++, descr++) {
 		spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
 
-		descr->bus_addr =
-			pci_map_single(card->pdev, descr,
-				       SPIDER_NET_DESCR_SIZE,
-				       PCI_DMA_BIDIRECTIONAL);
+		buf = pci_map_single(card->pdev, descr,
+				     SPIDER_NET_DESCR_SIZE,
+				     PCI_DMA_BIDIRECTIONAL);
 
-		if (descr->bus_addr == DMA_ERROR_CODE)
+		if (buf == DMA_ERROR_CODE)
 			goto iommu_error;
 
+		descr->bus_addr = buf;
 		descr->next = descr + 1;
 		descr->prev = descr - 1;
 
@@ -439,7 +375,8 @@
 	for (i=0; i < no; i++, descr++)
 		if (descr->bus_addr)
 			pci_unmap_single(card->pdev, descr->bus_addr,
-					 SPIDER_NET_DESCR_SIZE, PCI_DMA_BIDIRECTIONAL);
+					 SPIDER_NET_DESCR_SIZE,
+					 PCI_DMA_BIDIRECTIONAL);
 	return -ENOMEM;
 }
 
@@ -459,7 +396,7 @@
 		if (descr->skb) {
 			dev_kfree_skb(descr->skb);
 			pci_unmap_single(card->pdev, descr->buf_addr,
-					 SPIDER_NET_MAX_MTU,
+					 SPIDER_NET_MAX_FRAME,
 					 PCI_DMA_BIDIRECTIONAL);
 		}
 		descr = descr->next;
@@ -480,12 +417,13 @@
 spider_net_prepare_rx_descr(struct spider_net_card *card,
 			    struct spider_net_descr *descr)
 {
+	dma_addr_t buf;
 	int error = 0;
 	int offset;
 	int bufsize;
 
 	/* we need to round up the buffer size to a multiple of 128 */
-	bufsize = (SPIDER_NET_MAX_MTU + SPIDER_NET_RXBUF_ALIGN - 1) &
+	bufsize = (SPIDER_NET_MAX_FRAME + SPIDER_NET_RXBUF_ALIGN - 1) &
 		(~(SPIDER_NET_RXBUF_ALIGN - 1));
 
 	/* and we need to have it 128 byte aligned, therefore we allocate a
@@ -493,10 +431,8 @@
 	/* allocate an skb */
 	descr->skb = dev_alloc_skb(bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
 	if (!descr->skb) {
-		if (net_ratelimit())
-			if (netif_msg_rx_err(card))
-				pr_err("Not enough memory to allocate "
-					"rx buffer\n");
+		if (netif_msg_rx_err(card) && net_ratelimit())
+			pr_err("Not enough memory to allocate rx buffer\n");
 		return -ENOMEM;
 	}
 	descr->buf_size = bufsize;
@@ -510,12 +446,12 @@
 	if (offset)
 		skb_reserve(descr->skb, SPIDER_NET_RXBUF_ALIGN - offset);
 	/* io-mmu-map the skb */
-	descr->buf_addr = pci_map_single(card->pdev, descr->skb->data,
-					 SPIDER_NET_MAX_MTU,
-					 PCI_DMA_BIDIRECTIONAL);
-	if (descr->buf_addr == DMA_ERROR_CODE) {
+	buf = pci_map_single(card->pdev, descr->skb->data,
+			     SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+	descr->buf_addr = buf;
+	if (buf == DMA_ERROR_CODE) {
 		dev_kfree_skb_any(descr->skb);
-		if (netif_msg_rx_err(card))
+		if (netif_msg_rx_err(card) && net_ratelimit())
 			pr_err("Could not iommu-map rx buffer\n");
 		spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
 	} else {
@@ -526,10 +462,10 @@
 }
 
 /**
- * spider_net_enable_rxctails - sets RX dmac chain tail addresses
+ * spider_net_enable_rxchtails - sets RX dmac chain tail addresses
  * @card: card structure
  *
- * spider_net_enable_rxctails sets the RX DMAC chain tail adresses in the
+ * spider_net_enable_rxchtails sets the RX DMAC chain tail adresses in the
  * chip by writing to the appropriate register. DMA is enabled in
  * spider_net_enable_rxdmac.
  */
@@ -551,6 +487,7 @@
 static void
 spider_net_enable_rxdmac(struct spider_net_card *card)
 {
+	wmb();
 	spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
 			     SPIDER_NET_DMA_RX_VALUE);
 }
@@ -559,32 +496,28 @@
  * spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
  * @card: card structure
  *
- * refills descriptors in all chains (last used chain first): allocates skbs
- * and iommu-maps them.
+ * refills descriptors in the rx chain: allocates skbs and iommu-maps them.
  */
 static void
 spider_net_refill_rx_chain(struct spider_net_card *card)
 {
 	struct spider_net_descr_chain *chain;
-	int count = 0;
-	unsigned long flags;
 
 	chain = &card->rx_chain;
 
-	spin_lock_irqsave(&card->chain_lock, flags);
-	while (spider_net_get_descr_status(chain->head) ==
-				SPIDER_NET_DESCR_NOT_IN_USE) {
-		if (spider_net_prepare_rx_descr(card, chain->head))
-			break;
-		count++;
-		chain->head = chain->head->next;
-	}
-	spin_unlock_irqrestore(&card->chain_lock, flags);
+	/* one context doing the refill (and a second context seeing that
+	 * and omitting it) is ok. If called by NAPI, we'll be called again
+	 * as spider_net_decode_one_descr is called several times. If some
+	 * interrupt calls us, the NAPI is about to clean up anyway. */
+	if (atomic_inc_return(&card->rx_chain_refill) == 1)
+		while (spider_net_get_descr_status(chain->head) ==
+		       SPIDER_NET_DESCR_NOT_IN_USE) {
+			if (spider_net_prepare_rx_descr(card, chain->head))
+				break;
+			chain->head = chain->head->next;
+		}
 
-	/* could be optimized, only do that, if we know the DMA processing
-	 * has terminated */
-	if (count)
-		spider_net_enable_rxdmac(card);
+	atomic_dec(&card->rx_chain_refill);
 }
 
 /**
@@ -613,6 +546,7 @@
 	/* this will allocate the rest of the rx buffers; if not, it's
 	 * business as usual later on */
 	spider_net_refill_rx_chain(card);
+	spider_net_enable_rxdmac(card);
 	return 0;
 
 error:
@@ -649,24 +583,30 @@
  * @card: adapter structure
  * @brutal: if set, don't care about whether descriptor seems to be in use
  *
- * releases the tx descriptors that spider has finished with (if non-brutal)
- * or simply release tx descriptors (if brutal)
+ * returns 0 if the tx ring is empty, otherwise 1.
+ *
+ * spider_net_release_tx_chain releases the tx descriptors that spider has
+ * finished with (if non-brutal) or simply release tx descriptors (if brutal).
+ * If some other context is calling this function, we return 1 so that we're
+ * scheduled again (if we were scheduled) and will not loose initiative.
  */
-static void
+static int
 spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
 {
 	struct spider_net_descr_chain *tx_chain = &card->tx_chain;
 	enum spider_net_descr_status status;
 
-	spider_net_tx_irq_off(card);
+	if (atomic_inc_return(&card->tx_chain_release) != 1) {
+		atomic_dec(&card->tx_chain_release);
+		return 1;
+	}
 
-	/* no lock for chain needed, if this is only executed once at a time */
-again:
 	for (;;) {
 		status = spider_net_get_descr_status(tx_chain->tail);
 		switch (status) {
 		case SPIDER_NET_DESCR_CARDOWNED:
-			if (!brutal) goto out;
+			if (!brutal)
+				goto out;
 			/* fallthrough, if we release the descriptors
 			 * brutally (then we don't care about
 			 * SPIDER_NET_DESCR_CARDOWNED) */
@@ -693,25 +633,30 @@
 		tx_chain->tail = tx_chain->tail->next;
 	}
 out:
+	atomic_dec(&card->tx_chain_release);
+
 	netif_wake_queue(card->netdev);
 
-	if (!brutal) {
-		/* switch on tx irqs (while we are still in the interrupt
-		 * handler, so we don't get an interrupt), check again
-		 * for done descriptors. This results in fewer interrupts */
-		spider_net_tx_irq_on(card);
-		status = spider_net_get_descr_status(tx_chain->tail);
-		switch (status) {
-			case SPIDER_NET_DESCR_RESPONSE_ERROR:
-			case SPIDER_NET_DESCR_PROTECTION_ERROR:
-			case SPIDER_NET_DESCR_FORCE_END:
-			case SPIDER_NET_DESCR_COMPLETE:
-				goto again;
-			default:
-				break;
-		}
-	}
+	if (status == SPIDER_NET_DESCR_CARDOWNED)
+		return 1;
+	return 0;
+}
 
+/**
+ * spider_net_cleanup_tx_ring - cleans up the TX ring
+ * @card: card structure
+ *
+ * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
+ * interrupts to cleanup our TX ring) and returns sent packets to the stack
+ * by freeing them
+ */
+static void
+spider_net_cleanup_tx_ring(struct spider_net_card *card)
+{
+	if ( (spider_net_release_tx_chain(card, 0)) &&
+	      (card->netdev->flags & IFF_UP) ) {
+		mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
+	}
 }
 
 /**
@@ -726,16 +671,22 @@
 static u8
 spider_net_get_multicast_hash(struct net_device *netdev, __u8 *addr)
 {
-	/* FIXME: an addr of 01:00:5e:00:00:01 must result in 0xa9,
-	 * ff:ff:ff:ff:ff:ff must result in 0xfd */
 	u32 crc;
 	u8 hash;
+	char addr_for_crc[ETH_ALEN] = { 0, };
+	int i, bit;
 
-	crc = crc32_be(~0, addr, netdev->addr_len);
+	for (i = 0; i < ETH_ALEN * 8; i++) {
+		bit = (addr[i / 8] >> (i % 8)) & 1;
+		addr_for_crc[ETH_ALEN - 1 - i / 8] += bit << (7 - (i % 8));
+	}
+
+	crc = crc32_be(~0, addr_for_crc, netdev->addr_len);
 
 	hash = (crc >> 27);
 	hash <<= 3;
 	hash |= crc & 7;
+	hash &= 0xff;
 
 	return hash;
 }
@@ -821,9 +772,11 @@
 {
 	struct spider_net_card *card = netdev_priv(netdev);
 
+	tasklet_kill(&card->rxram_full_tl);
 	netif_poll_disable(netdev);
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
+	del_timer_sync(&card->tx_timer);
 
 	/* disable/mask all interrupts */
 	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
@@ -872,13 +825,15 @@
  * @skb: packet to consider
  *
  * fills out the command and status field of the descriptor structure,
- * depending on hardware checksum settings. This function assumes a wmb()
- * has executed before.
+ * depending on hardware checksum settings.
  */
 static void
 spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
 			       struct sk_buff *skb)
 {
+	/* make sure the other fields in the descriptor are written */
+	wmb();
+
 	if (skb->ip_summed != CHECKSUM_HW) {
 		descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
 		return;
@@ -887,14 +842,13 @@
 	/* is packet ip?
 	 * if yes: tcp? udp? */
 	if (skb->protocol == htons(ETH_P_IP)) {
-		if (skb->nh.iph->protocol == IPPROTO_TCP) {
+		if (skb->nh.iph->protocol == IPPROTO_TCP)
 			descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_TCPCS;
-		} else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+		else if (skb->nh.iph->protocol == IPPROTO_UDP)
 			descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_UDPCS;
-		} else { /* the stack should checksum non-tcp and non-udp
-			    packets on his own: NETIF_F_IP_CSUM */
+		else /* the stack should checksum non-tcp and non-udp
+			packets on his own: NETIF_F_IP_CSUM */
 			descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
-		}
 	}
 }
 
@@ -914,23 +868,22 @@
 			    struct spider_net_descr *descr,
 			    struct sk_buff *skb)
 {
-	descr->buf_addr = pci_map_single(card->pdev, skb->data,
-					 skb->len, PCI_DMA_BIDIRECTIONAL);
-	if (descr->buf_addr == DMA_ERROR_CODE) {
-		if (netif_msg_tx_err(card))
+	dma_addr_t buf;
+
+	buf = pci_map_single(card->pdev, skb->data,
+			     skb->len, PCI_DMA_BIDIRECTIONAL);
+	if (buf == DMA_ERROR_CODE) {
+		if (netif_msg_tx_err(card) && net_ratelimit())
 			pr_err("could not iommu-map packet (%p, %i). "
 				  "Dropping packet\n", skb->data, skb->len);
 		return -ENOMEM;
 	}
 
+	descr->buf_addr = buf;
 	descr->buf_size = skb->len;
 	descr->skb = skb;
 	descr->data_status = 0;
 
-	/* make sure the above values are in memory before we change the
-	 * status */
-	wmb();
-
 	spider_net_set_txdescr_cmdstat(descr,skb);
 
 	return 0;
@@ -972,17 +925,12 @@
 	struct spider_net_descr *descr;
 	int result;
 
+	spider_net_release_tx_chain(card, 0);
+
 	descr = spider_net_get_next_tx_descr(card);
 
-	if (!descr) {
-		netif_stop_queue(netdev);
-
-		descr = spider_net_get_next_tx_descr(card);
-		if (!descr)
-			goto error;
-		else
-			netif_start_queue(netdev);
-	}
+	if (!descr)
+		goto error;
 
 	result = spider_net_prepare_tx_descr(card, descr, skb);
 	if (result)
@@ -990,19 +938,25 @@
 
 	card->tx_chain.head = card->tx_chain.head->next;
 
-	/* make sure the status from spider_net_prepare_tx_descr is in
-	 * memory before we check out the previous descriptor */
-	wmb();
-
 	if (spider_net_get_descr_status(descr->prev) !=
-	    SPIDER_NET_DESCR_CARDOWNED)
-		spider_net_kick_tx_dma(card, descr);
+	    SPIDER_NET_DESCR_CARDOWNED) {
+		/* make sure the current descriptor is in memory. Then
+		 * kicking it on again makes sense, if the previous is not
+		 * card-owned anymore. Check the previous descriptor twice
+		 * to omit an mb() in heavy traffic cases */
+		mb();
+		if (spider_net_get_descr_status(descr->prev) !=
+		    SPIDER_NET_DESCR_CARDOWNED)
+			spider_net_kick_tx_dma(card, descr);
+	}
+
+	mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
 
 	return NETDEV_TX_OK;
 
 error:
 	card->netdev_stats.tx_dropped++;
-	return NETDEV_TX_LOCKED;
+	return NETDEV_TX_BUSY;
 }
 
 /**
@@ -1027,6 +981,7 @@
  * spider_net_pass_skb_up - takes an skb from a descriptor and passes it on
  * @descr: descriptor to process
  * @card: card structure
+ * @napi: whether caller is in NAPI context
  *
  * returns 1 on success, 0 if no packet was passed to the stack
  *
@@ -1035,7 +990,7 @@
  */
 static int
 spider_net_pass_skb_up(struct spider_net_descr *descr,
-		       struct spider_net_card *card)
+		       struct spider_net_card *card, int napi)
 {
 	struct sk_buff *skb;
 	struct net_device *netdev;
@@ -1046,22 +1001,20 @@
 
 	netdev = card->netdev;
 
-	/* check for errors in the data_error flag */
-	if ((data_error & SPIDER_NET_DATA_ERROR_MASK) &&
-	    netif_msg_rx_err(card))
-		pr_err("error in received descriptor found, "
-		       "data_status=x%08x, data_error=x%08x\n",
-		       data_status, data_error);
-
-	/* prepare skb, unmap descriptor */
-	skb = descr->skb;
-	pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_MTU,
+	/* unmap descriptor */
+	pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_FRAME,
 			 PCI_DMA_BIDIRECTIONAL);
 
 	/* the cases we'll throw away the packet immediately */
-	if (data_error & SPIDER_NET_DESTROY_RX_FLAGS)
+	if (data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
+		if (netif_msg_rx_err(card))
+			pr_err("error in received descriptor found, "
+			       "data_status=x%08x, data_error=x%08x\n",
+			       data_status, data_error);
 		return 0;
+	}
 
+	skb = descr->skb;
 	skb->dev = netdev;
 	skb_put(skb, descr->valid_size);
 
@@ -1073,14 +1026,14 @@
 
 	/* checksum offload */
 	if (card->options.rx_csum) {
-		if ( (data_status & SPIDER_NET_DATA_STATUS_CHK_MASK) &&
-		     (!(data_error & SPIDER_NET_DATA_ERROR_CHK_MASK)) )
+		if ( ( (data_status & SPIDER_NET_DATA_STATUS_CKSUM_MASK) ==
+		       SPIDER_NET_DATA_STATUS_CKSUM_MASK) &&
+		     !(data_error & SPIDER_NET_DATA_ERR_CKSUM_MASK))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
 			skb->ip_summed = CHECKSUM_NONE;
-	} else {
+	} else
 		skb->ip_summed = CHECKSUM_NONE;
-	}
 
 	if (data_status & SPIDER_NET_VLAN_PACKET) {
 		/* further enhancements: HW-accel VLAN
@@ -1089,7 +1042,10 @@
 	}
 
 	/* pass skb up to stack */
-	netif_receive_skb(skb);
+	if (napi)
+		netif_receive_skb(skb);
+	else
+		netif_rx_ni(skb);
 
 	/* update netdevice statistics */
 	card->netdev_stats.rx_packets++;
@@ -1099,16 +1055,18 @@
 }
 
 /**
- * spider_net_decode_descr - processes an rx descriptor
+ * spider_net_decode_one_descr - processes an rx descriptor
  * @card: card structure
+ * @napi: whether caller is in NAPI context
  *
  * returns 1 if a packet has been sent to the stack, otherwise 0
  *
  * processes an rx descriptor by iommu-unmapping the data buffer and passing
- * the packet up to the stack
+ * the packet up to the stack. This function is called in softirq
+ * context, e.g. either bottom half from interrupt or NAPI polling context
  */
 static int
-spider_net_decode_one_descr(struct spider_net_card *card)
+spider_net_decode_one_descr(struct spider_net_card *card, int napi)
 {
 	enum spider_net_descr_status status;
 	struct spider_net_descr *descr;
@@ -1122,17 +1080,19 @@
 
 	if (status == SPIDER_NET_DESCR_CARDOWNED) {
 		/* nothing in the descriptor yet */
-		return 0;
+		result=0;
+		goto out;
 	}
 
 	if (status == SPIDER_NET_DESCR_NOT_IN_USE) {
-		/* not initialized yet, I bet chain->tail == chain->head
-		 * and the ring is empty */
+		/* not initialized yet, the ring must be empty */
 		spider_net_refill_rx_chain(card);
-		return 0;
+		spider_net_enable_rxdmac(card);
+		result=0;
+		goto out;
 	}
 
-	/* descriptor definitively used -- move on head */
+	/* descriptor definitively used -- move on tail */
 	chain->tail = descr->next;
 
 	result = 0;
@@ -1143,6 +1103,9 @@
 			pr_err("%s: dropping RX descriptor with state %d\n",
 			       card->netdev->name, status);
 		card->netdev_stats.rx_dropped++;
+		pci_unmap_single(card->pdev, descr->buf_addr,
+				 SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+		dev_kfree_skb_irq(descr->skb);
 		goto refill;
 	}
 
@@ -1155,12 +1118,13 @@
 	}
 
 	/* ok, we've got a packet in descr */
-	result = spider_net_pass_skb_up(descr, card);
+	result = spider_net_pass_skb_up(descr, card, napi);
 refill:
 	spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
 	/* change the descriptor state: */
-	spider_net_refill_rx_chain(card);
-
+	if (!napi)
+		spider_net_refill_rx_chain(card);
+out:
 	return result;
 }
 
@@ -1186,7 +1150,7 @@
 	packets_to_do = min(*budget, netdev->quota);
 
 	while (packets_to_do) {
-		if (spider_net_decode_one_descr(card)) {
+		if (spider_net_decode_one_descr(card, 1)) {
 			packets_done++;
 			packets_to_do--;
 		} else {
@@ -1198,6 +1162,7 @@
 
 	netdev->quota -= packets_done;
 	*budget -= packets_done;
+	spider_net_refill_rx_chain(card);
 
 	/* if all packets are in the stack, enable interrupts and return 0 */
 	/* if not, return 1 */
@@ -1342,6 +1307,24 @@
 }
 
 /**
+ * spider_net_handle_rxram_full - cleans up RX ring upon RX RAM full interrupt
+ * @card: card structure
+ *
+ * spider_net_handle_rxram_full empties the RX ring so that spider can put
+ * more packets in it and empty its RX RAM. This is called in bottom half
+ * context
+ */
+static void
+spider_net_handle_rxram_full(struct spider_net_card *card)
+{
+	while (spider_net_decode_one_descr(card, 0))
+		;
+	spider_net_enable_rxchtails(card);
+	spider_net_enable_rxdmac(card);
+	netif_rx_schedule(card->netdev);
+}
+
+/**
  * spider_net_handle_error_irq - handles errors raised by an interrupt
  * @card: card structure
  * @status_reg: interrupt status register 0 (GHIINT0STS)
@@ -1449,17 +1432,21 @@
 				switch (i)
 	{
 	case SPIDER_NET_GTMFLLINT:
-		if (netif_msg_intr(card))
+		if (netif_msg_intr(card) && net_ratelimit())
 			pr_err("Spider TX RAM full\n");
 		show_error = 0;
 		break;
+	case SPIDER_NET_GRFDFLLINT: /* fallthrough */
+	case SPIDER_NET_GRFCFLLINT: /* fallthrough */
+	case SPIDER_NET_GRFBFLLINT: /* fallthrough */
+	case SPIDER_NET_GRFAFLLINT: /* fallthrough */
 	case SPIDER_NET_GRMFLLINT:
-		if (netif_msg_intr(card))
+		if (netif_msg_intr(card) && net_ratelimit())
 			pr_err("Spider RX RAM full, incoming packets "
-			       "might be discarded !\n");
-		netif_rx_schedule(card->netdev);
-		spider_net_enable_rxchtails(card);
-		spider_net_enable_rxdmac(card);
+			       "might be discarded!\n");
+		spider_net_rx_irq_off(card);
+		tasklet_schedule(&card->rxram_full_tl);
+		show_error = 0;
 		break;
 
 	/* case SPIDER_NET_GTMSHTINT: problem, print a message */
@@ -1467,10 +1454,6 @@
 		/* allrighty. tx from previous descr ok */
 		show_error = 0;
 		break;
-	/* case SPIDER_NET_GRFDFLLINT: print a message down there */
-	/* case SPIDER_NET_GRFCFLLINT: print a message down there */
-	/* case SPIDER_NET_GRFBFLLINT: print a message down there */
-	/* case SPIDER_NET_GRFAFLLINT: print a message down there */
 
 	/* chain end */
 	case SPIDER_NET_GDDDCEINT: /* fallthrough */
@@ -1482,6 +1465,7 @@
 			       "restarting DMAC %c.\n",
 			       'D'+i-SPIDER_NET_GDDDCEINT);
 		spider_net_refill_rx_chain(card);
+		spider_net_enable_rxdmac(card);
 		show_error = 0;
 		break;
 
@@ -1492,6 +1476,7 @@
 	case SPIDER_NET_GDAINVDINT:
 		/* could happen when rx chain is full */
 		spider_net_refill_rx_chain(card);
+		spider_net_enable_rxdmac(card);
 		show_error = 0;
 		break;
 
@@ -1580,17 +1565,13 @@
 	if (!status_reg)
 		return IRQ_NONE;
 
-	if (status_reg & SPIDER_NET_TXINT)
-		spider_net_release_tx_chain(card, 0);
-
 	if (status_reg & SPIDER_NET_RXINT ) {
 		spider_net_rx_irq_off(card);
 		netif_rx_schedule(netdev);
 	}
 
-	/* we do this after rx and tx processing, as we want the tx chain
-	 * processed to see, whether we should restart tx dma processing */
-	spider_net_handle_error_irq(card, status_reg);
+	if (status_reg & SPIDER_NET_ERRINT )
+		spider_net_handle_error_irq(card, status_reg);
 
 	/* clear interrupt sources */
 	spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg);
@@ -1831,34 +1812,40 @@
 /**
  * spider_net_download_firmware - loads firmware into the adapter
  * @card: card structure
- * @firmware: firmware pointer
+ * @firmware_ptr: pointer to firmware data
  *
- * spider_net_download_firmware loads the firmware opened by
- * spider_net_init_firmware into the adapter.
+ * spider_net_download_firmware loads the firmware data into the
+ * adapter. It assumes the length etc. to be allright.
  */
-static void
+static int
 spider_net_download_firmware(struct spider_net_card *card,
-			     const struct firmware *firmware)
+			     u8 *firmware_ptr)
 {
 	int sequencer, i;
-	u32 *fw_ptr = (u32 *)firmware->data;
+	u32 *fw_ptr = (u32 *)firmware_ptr;
 
 	/* stop sequencers */
 	spider_net_write_reg(card, SPIDER_NET_GSINIT,
 			     SPIDER_NET_STOP_SEQ_VALUE);
 
-	for (sequencer = 0; sequencer < 6; sequencer++) {
+	for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
+	     sequencer++) {
 		spider_net_write_reg(card,
 				     SPIDER_NET_GSnPRGADR + sequencer * 8, 0);
-		for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+		for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
 			spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
 					     sequencer * 8, *fw_ptr);
 			fw_ptr++;
 		}
 	}
 
+	if (spider_net_read_reg(card, SPIDER_NET_GSINIT))
+		return -EIO;
+
 	spider_net_write_reg(card, SPIDER_NET_GSINIT,
 			     SPIDER_NET_RUN_SEQ_VALUE);
+
+	return 0;
 }
 
 /**
@@ -1890,31 +1877,53 @@
 static int
 spider_net_init_firmware(struct spider_net_card *card)
 {
-	const struct firmware *firmware;
-	int err = -EIO;
+	struct firmware *firmware = NULL;
+	struct device_node *dn;
+	u8 *fw_prop = NULL;
+	int err = -ENOENT;
+	int fw_size;
 
-	if (request_firmware(&firmware,
-			     SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) < 0) {
-		if (netif_msg_probe(card))
-			pr_err("Couldn't read in sequencer data file %s.\n",
-			       SPIDER_NET_FIRMWARE_NAME);
-		firmware = NULL;
-		goto out;
+	if (request_firmware((const struct firmware **)&firmware,
+			     SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
+		if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
+		     netif_msg_probe(card) ) {
+			pr_err("Incorrect size of spidernet firmware in " \
+			       "filesystem. Looking in host firmware...\n");
+			goto try_host_fw;
+		}
+		err = spider_net_download_firmware(card, firmware->data);
+
+		release_firmware(firmware);
+		if (err)
+			goto try_host_fw;
+
+		goto done;
 	}
 
-	if (firmware->size != 6 * SPIDER_NET_FIRMWARE_LEN * sizeof(u32)) {
-		if (netif_msg_probe(card))
-			pr_err("Invalid size of sequencer data file %s.\n",
-			       SPIDER_NET_FIRMWARE_NAME);
-		goto out;
+try_host_fw:
+	dn = pci_device_to_OF_node(card->pdev);
+	if (!dn)
+		goto out_err;
+
+	fw_prop = (u8 *)get_property(dn, "firmware", &fw_size);
+	if (!fw_prop)
+		goto out_err;
+
+	if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
+	     netif_msg_probe(card) ) {
+		pr_err("Incorrect size of spidernet firmware in " \
+		       "host firmware\n");
+		goto done;
 	}
 
-	spider_net_download_firmware(card, firmware);
+	err = spider_net_download_firmware(card, fw_prop);
 
-	err = 0;
-out:
-	release_firmware(firmware);
-
+done:
+	return err;
+out_err:
+	if (netif_msg_probe(card))
+		pr_err("Couldn't find spidernet firmware in filesystem " \
+		       "or host firmware\n");
 	return err;
 }
 
@@ -1934,10 +1943,11 @@
 			     SPIDER_NET_CKRCTRL_RUN_VALUE);
 
 	/* empty sequencer data */
-	for (sequencer = 0; sequencer < 6; sequencer++) {
+	for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
+	     sequencer++) {
 		spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
 				     sequencer * 8, 0x0);
-		for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+		for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
 			spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
 					     sequencer * 8, 0x0);
 		}
@@ -2061,7 +2071,15 @@
 	SET_NETDEV_DEV(netdev, &card->pdev->dev);
 
 	pci_set_drvdata(card->pdev, netdev);
-	spin_lock_init(&card->intmask_lock);
+
+	atomic_set(&card->tx_chain_release,0);
+	card->rxram_full_tl.data = (unsigned long) card;
+	card->rxram_full_tl.func =
+		(void (*)(unsigned long)) spider_net_handle_rxram_full;
+	init_timer(&card->tx_timer);
+	card->tx_timer.function =
+		(void (*)(unsigned long)) spider_net_cleanup_tx_ring;
+	card->tx_timer.data = (unsigned long) card;
 	netdev->irq = card->pdev->irq;
 
 	card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 22b2f23..5922b52 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -33,25 +33,32 @@
 
 extern char spider_net_driver_name[];
 
-#define SPIDER_NET_MAX_MTU			2308
+#define SPIDER_NET_MAX_FRAME			2312
+#define SPIDER_NET_MAX_MTU			2294
 #define SPIDER_NET_MIN_MTU			64
 
 #define SPIDER_NET_RXBUF_ALIGN			128
 
-#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT	64
+#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT	256
 #define SPIDER_NET_RX_DESCRIPTORS_MIN		16
-#define SPIDER_NET_RX_DESCRIPTORS_MAX		256
+#define SPIDER_NET_RX_DESCRIPTORS_MAX		512
 
-#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT	64
+#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT	256
 #define SPIDER_NET_TX_DESCRIPTORS_MIN		16
-#define SPIDER_NET_TX_DESCRIPTORS_MAX		256
+#define SPIDER_NET_TX_DESCRIPTORS_MAX		512
+
+#define SPIDER_NET_TX_TIMER			20
 
 #define SPIDER_NET_RX_CSUM_DEFAULT		1
 
-#define SPIDER_NET_WATCHDOG_TIMEOUT 5*HZ
-#define SPIDER_NET_NAPI_WEIGHT 64
+#define SPIDER_NET_WATCHDOG_TIMEOUT		50*HZ
+#define SPIDER_NET_NAPI_WEIGHT			64
 
-#define SPIDER_NET_FIRMWARE_LEN		1024
+#define SPIDER_NET_FIRMWARE_SEQS	6
+#define SPIDER_NET_FIRMWARE_SEQWORDS	1024
+#define SPIDER_NET_FIRMWARE_LEN		(SPIDER_NET_FIRMWARE_SEQS * \
+					 SPIDER_NET_FIRMWARE_SEQWORDS * \
+					 sizeof(u32))
 #define SPIDER_NET_FIRMWARE_NAME	"spider_fw.bin"
 
 /** spider_net SMMIO registers */
@@ -142,14 +149,12 @@
 /** SCONFIG registers */
 #define SPIDER_NET_SCONFIG_IOACTE	0x00002810
 
-/** hardcoded register values */
-#define SPIDER_NET_INT0_MASK_VALUE	0x3f7fe3ff
-#define SPIDER_NET_INT1_MASK_VALUE	0xffffffff
+/** interrupt mask registers */
+#define SPIDER_NET_INT0_MASK_VALUE	0x3f7fe2c7
+#define SPIDER_NET_INT1_MASK_VALUE	0xffff7ff7
 /* no MAC aborts -> auto retransmission */
-#define SPIDER_NET_INT2_MASK_VALUE	0xfffffff1
+#define SPIDER_NET_INT2_MASK_VALUE	0xffef7ff1
 
-/* clear counter when interrupt sources are cleared
-#define SPIDER_NET_FRAMENUM_VALUE	0x0001f001 */
 /* we rely on flagged descriptor interrupts */
 #define SPIDER_NET_FRAMENUM_VALUE	0x00000000
 /* set this first, then the FRAMENUM_VALUE */
@@ -168,7 +173,7 @@
 #if 0
 #define SPIDER_NET_WOL_VALUE		0x00000000
 #endif
-#define SPIDER_NET_IPSECINIT_VALUE	0x00f000f8
+#define SPIDER_NET_IPSECINIT_VALUE	0x6f716f71
 
 /* pause frames: automatic, no upper retransmission count */
 /* outside loopback mode: ETOMOD signal dont matter, not connected */
@@ -318,6 +323,10 @@
 #define SPIDER_NET_RXINT	( (1 << SPIDER_NET_GDAFDCINT) | \
 				  (1 << SPIDER_NET_GRMFLLINT) )
 
+#define SPIDER_NET_ERRINT	( 0xffffffff & \
+				  (~SPIDER_NET_TXINT) & \
+				  (~SPIDER_NET_RXINT) )
+
 #define SPIDER_NET_GPREXEC		0x80000000
 #define SPIDER_NET_GPRDAT_MASK		0x0000ffff
 
@@ -358,9 +367,6 @@
 /* descr ready, descr is in middle of chain, get interrupt on completion */
 #define SPIDER_NET_DMAC_RX_CARDOWNED	0xa0800000
 
-/* multicast is no problem */
-#define SPIDER_NET_DATA_ERROR_MASK	0xffffbfff
-
 enum spider_net_descr_status {
 	SPIDER_NET_DESCR_COMPLETE		= 0x00, /* used in rx and tx */
 	SPIDER_NET_DESCR_RESPONSE_ERROR		= 0x01, /* used in rx and tx */
@@ -373,9 +379,9 @@
 
 struct spider_net_descr {
 	/* as defined by the hardware */
-	dma_addr_t buf_addr;
+	u32 buf_addr;
 	u32 buf_size;
-	dma_addr_t next_descr_addr;
+	u32 next_descr_addr;
 	u32 dmac_cmd_status;
 	u32 result_size;
 	u32 valid_size;	/* all zeroes for tx */
@@ -384,7 +390,7 @@
 
 	/* used in the driver */
 	struct sk_buff *skb;
-	dma_addr_t bus_addr;
+	u32 bus_addr;
 	struct spider_net_descr *next;
 	struct spider_net_descr *prev;
 } __attribute__((aligned(32)));
@@ -396,21 +402,21 @@
 };
 
 /* descriptor data_status bits */
-#define SPIDER_NET_RXIPCHK		29
-#define SPIDER_NET_TCPUDPIPCHK		28
-#define SPIDER_NET_DATA_STATUS_CHK_MASK	(1 << SPIDER_NET_RXIPCHK | \
-					 1 << SPIDER_NET_TCPUDPIPCHK)
-
+#define SPIDER_NET_RX_IPCHK		29
+#define SPIDER_NET_RX_TCPCHK		28
 #define SPIDER_NET_VLAN_PACKET		21
+#define SPIDER_NET_DATA_STATUS_CKSUM_MASK ( (1 << SPIDER_NET_RX_IPCHK) | \
+					  (1 << SPIDER_NET_RX_TCPCHK) )
 
 /* descriptor data_error bits */
-#define SPIDER_NET_RXIPCHKERR		27
-#define SPIDER_NET_RXTCPCHKERR		26
-#define SPIDER_NET_DATA_ERROR_CHK_MASK	(1 << SPIDER_NET_RXIPCHKERR | \
-					 1 << SPIDER_NET_RXTCPCHKERR)
+#define SPIDER_NET_RX_IPCHKERR		27
+#define SPIDER_NET_RX_RXTCPCHKERR	28
 
-/* the cases we don't pass the packet to the stack */
-#define SPIDER_NET_DESTROY_RX_FLAGS	0x70138000
+#define SPIDER_NET_DATA_ERR_CKSUM_MASK	(1 << SPIDER_NET_RX_IPCHKERR)
+
+/* the cases we don't pass the packet to the stack.
+ * 701b8000 would be correct, but every packets gets that flag */
+#define SPIDER_NET_DESTROY_RX_FLAGS	0x700b8000
 
 #define SPIDER_NET_DESCR_SIZE		32
 
@@ -445,13 +451,16 @@
 
 	struct spider_net_descr_chain tx_chain;
 	struct spider_net_descr_chain rx_chain;
-	spinlock_t chain_lock;
+	atomic_t rx_chain_refill;
+	atomic_t tx_chain_release;
 
 	struct net_device_stats netdev_stats;
 
 	struct spider_net_options options;
 
 	spinlock_t intmask_lock;
+	struct tasklet_struct rxram_full_tl;
+	struct timer_list tx_timer;
 
 	struct work_struct tx_timeout_task;
 	atomic_t tx_timeout_task_counter;
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
index d42e60b..a5bb0b76 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/spider_net_ethtool.c
@@ -113,6 +113,23 @@
 	return 0;
 }
 
+static uint32_t
+spider_net_ethtool_get_tx_csum(struct net_device *netdev)
+{
+        return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static int
+spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+        if (data)
+                netdev->features |= NETIF_F_HW_CSUM;
+        else
+                netdev->features &= ~NETIF_F_HW_CSUM;
+
+        return 0;
+}
+
 struct ethtool_ops spider_net_ethtool_ops = {
 	.get_settings		= spider_net_ethtool_get_settings,
 	.get_drvinfo		= spider_net_ethtool_get_drvinfo,
@@ -122,5 +139,7 @@
 	.nway_reset		= spider_net_ethtool_nway_reset,
 	.get_rx_csum		= spider_net_ethtool_get_rx_csum,
 	.set_rx_csum		= spider_net_ethtool_set_rx_csum,
+	.get_tx_csum		= spider_net_ethtool_get_tx_csum,
+	.set_tx_csum		= spider_net_ethtool_set_tx_csum,
 };
 
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index ee866fd..a4c7ae9 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -5668,13 +5668,13 @@
 		int channel = fwrq->m;
 		/* We should do a better check than that,
 		 * based on the card capability !!! */
-		if((channel < 1) || (channel > 16)) {
+		if((channel < 1) || (channel > 14)) {
 			printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m);
 			rc = -EINVAL;
 		} else {
 			readConfigRid(local, 1);
 			/* Yes ! We can set it !!! */
-			local->config.channelSet = (u16)(channel - 1);
+			local->config.channelSet = (u16) channel;
 			set_bit (FLAG_COMMIT, &local->flags);
 		}
 	}
@@ -5692,6 +5692,7 @@
 {
 	struct airo_info *local = dev->priv;
 	StatusRid status_rid;		/* Card status info */
+	int ch;
 
 	readConfigRid(local, 1);
 	if ((local->config.opmode & 0xFF) == MODE_STA_ESS)
@@ -5699,16 +5700,14 @@
 	else
 		readStatusRid(local, &status_rid, 1);
 
-#ifdef WEXT_USECHANNELS
-	fwrq->m = ((int)status_rid.channel) + 1;
-	fwrq->e = 0;
-#else
-	{
-		int f = (int)status_rid.channel;
-		fwrq->m = frequency_list[f] * 100000;
+	ch = (int)status_rid.channel;
+	if((ch > 0) && (ch < 15)) {
+		fwrq->m = frequency_list[ch - 1] * 100000;
 		fwrq->e = 1;
+	} else {
+		fwrq->m = ch;
+		fwrq->e = 0;
 	}
-#endif
 
 	return 0;
 }
@@ -5783,7 +5782,7 @@
 	/* If none, we may want to get the one that was set */
 
 	/* Push it out ! */
-	dwrq->length = status_rid.SSIDlen + 1;
+	dwrq->length = status_rid.SSIDlen;
 	dwrq->flags = 1; /* active */
 
 	return 0;
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index f0ccfef..98a76f1 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -1718,11 +1718,11 @@
 	if (priv->new_SSID_size != 0) {
 		memcpy(extra, priv->new_SSID, priv->new_SSID_size);
 		extra[priv->new_SSID_size] = '\0';
-		dwrq->length = priv->new_SSID_size + 1;
+		dwrq->length = priv->new_SSID_size;
 	} else {
 		memcpy(extra, priv->SSID, priv->SSID_size);
 		extra[priv->SSID_size] = '\0';
-		dwrq->length = priv->SSID_size + 1;
+		dwrq->length = priv->SSID_size;
 	}
 
 	dwrq->flags = !priv->connect_to_any_BSS; /* active */
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
index 56f41c7..c8f6286 100644
--- a/drivers/net/wireless/hostap/Kconfig
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -26,11 +26,25 @@
 	depends on HOSTAP
 	---help---
 	Configure Host AP driver to include support for firmware image
-	download. Current version supports only downloading to volatile, i.e.,
-	RAM memory. Flash upgrade is not yet supported.
+	download. This option by itself only enables downloading to the
+	volatile memory, i.e. the card RAM. This option is required to
+	support cards that don't have firmware in flash, such as D-Link
+	DWL-520 rev E and D-Link DWL-650 rev P.
 
-	Firmware image downloading needs user space tool, prism2_srec. It is
-	available from http://hostap.epitest.fi/.
+	Firmware image downloading needs a user space tool, prism2_srec.
+	It is available from http://hostap.epitest.fi/.
+
+config HOSTAP_FIRMWARE_NVRAM
+	bool "Support for non-volatile firmware download"
+	depends on HOSTAP_FIRMWARE
+	---help---
+	Allow Host AP driver to write firmware images to the non-volatile
+	card memory, i.e. flash memory that survives power cycling.
+	Enable this option if you want to be able to change card firmware
+	permanently.
+
+	Firmware image downloading needs a user space tool, prism2_srec.
+	It is available from http://hostap.epitest.fi/.
 
 config HOSTAP_PLX
 	tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors"
diff --git a/drivers/net/wireless/hostap/Makefile b/drivers/net/wireless/hostap/Makefile
index 353ccb9..b8e41a7 100644
--- a/drivers/net/wireless/hostap/Makefile
+++ b/drivers/net/wireless/hostap/Makefile
@@ -1,4 +1,5 @@
-hostap-y := hostap_main.o
+hostap-y := hostap_80211_rx.o hostap_80211_tx.o hostap_ap.o hostap_info.o \
+            hostap_ioctl.o hostap_main.o hostap_proc.o 
 obj-$(CONFIG_HOSTAP) += hostap.o
 
 obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h
index 5fac89b..5e63765 100644
--- a/drivers/net/wireless/hostap/hostap.h
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -1,6 +1,15 @@
 #ifndef HOSTAP_H
 #define HOSTAP_H
 
+#include <linux/ethtool.h>
+
+#include "hostap_wlan.h"
+#include "hostap_ap.h"
+
+static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+				  2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))
+
 /* hostap.c */
 
 extern struct proc_dir_entry *hostap_proc;
@@ -40,6 +49,26 @@
 int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype,
 			 u8 *body, size_t bodylen);
 int prism2_sta_deauth(local_info_t *local, u16 reason);
+int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+		   int rtnl_locked);
+int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+		   int rtnl_locked, int do_not_remove);
+
+
+/* hostap_ap.c */
+
+int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac);
+int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac);
+void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
+int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac);
+void ap_control_kickall(struct ap_data *ap);
+void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+			 struct ieee80211_crypt_data ***crypt);
+int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+			   struct iw_quality qual[], int buf_size,
+			   int aplist);
+int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
+int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param);
 
 
 /* hostap_proc.c */
@@ -54,4 +83,12 @@
 void hostap_info_process(local_info_t *local, struct sk_buff *skb);
 
 
+/* hostap_ioctl.c */
+
+extern const struct iw_handler_def hostap_iw_handler_def;
+extern struct ethtool_ops prism2_ethtool_ops;
+
+int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+
+
 #endif /* HOSTAP_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index bf506f5..1fc72fe 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -1,6 +1,9 @@
 #ifndef HOSTAP_80211_H
 #define HOSTAP_80211_H
 
+#include <linux/types.h>
+#include <net/ieee80211_crypt.h>
+
 struct hostap_ieee80211_mgmt {
 	u16 frame_control;
 	u16 duration;
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index 4b13b76..7e04dc9 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -1,7 +1,18 @@
 #include <linux/etherdevice.h>
+#include <net/ieee80211_crypt.h>
 
 #include "hostap_80211.h"
 #include "hostap.h"
+#include "hostap_ap.h"
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
 
 void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
 			  struct hostap_80211_rx_status *rx_stats)
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 9d24f8a..4a85e63 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -1,3 +1,18 @@
+#include "hostap_80211.h"
+#include "hostap_common.h"
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
+
 void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
 {
 	struct ieee80211_hdr_4addr *hdr;
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 9da94ab..753a1de 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -16,6 +16,14 @@
  *   (8802.11: 5.5)
  */
 
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
 static int other_ap_policy[MAX_PARM_DEVICES] = { AP_OTHER_AP_SKIP_ALL,
 						 DEF_INTS };
 module_param_array(other_ap_policy, int, NULL, 0444);
@@ -360,8 +368,7 @@
 }
 
 
-static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
-			      u8 *mac)
+int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
 {
 	struct mac_entry *entry;
 
@@ -380,8 +387,7 @@
 }
 
 
-static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
-			      u8 *mac)
+int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
 {
 	struct list_head *ptr;
 	struct mac_entry *entry;
@@ -433,7 +439,7 @@
 }
 
 
-static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
+void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
 {
 	struct list_head *ptr, *n;
 	struct mac_entry *entry;
@@ -454,8 +460,7 @@
 }
 
 
-static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
-			       u8 *mac)
+int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac)
 {
 	struct sta_info *sta;
 	u16 resp;
@@ -486,7 +491,7 @@
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
 
-static void ap_control_kickall(struct ap_data *ap)
+void ap_control_kickall(struct ap_data *ap)
 {
 	struct list_head *ptr, *n;
 	struct sta_info *sta;
@@ -2321,9 +2326,9 @@
 }
 
 
-static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
-				  struct iw_quality qual[], int buf_size,
-				  int aplist)
+int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+			   struct iw_quality qual[], int buf_size,
+			   int aplist)
 {
 	struct ap_data *ap = local->ap;
 	struct list_head *ptr;
@@ -2363,7 +2368,7 @@
 
 /* Translate our list of Access Points & Stations to a card independant
  * format that the Wireless Tools will understand - Jean II */
-static int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
+int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
 {
 	struct hostap_interface *iface;
 	local_info_t *local;
@@ -2608,8 +2613,7 @@
 }
 
 
-static int prism2_hostapd(struct ap_data *ap,
-			  struct prism2_hostapd_param *param)
+int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param)
 {
 	switch (param->cmd) {
 	case PRISM2_HOSTAPD_FLUSH:
@@ -3207,8 +3211,8 @@
 }
 
 
-static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
-				struct ieee80211_crypt_data ***crypt)
+void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+			 struct ieee80211_crypt_data ***crypt)
 {
 	struct sta_info *sta;
 
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
index 6d00df6..2fa2452 100644
--- a/drivers/net/wireless/hostap/hostap_ap.h
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -1,6 +1,8 @@
 #ifndef HOSTAP_AP_H
 #define HOSTAP_AP_H
 
+#include "hostap_80211.h"
+
 /* AP data structures for STAs */
 
 /* maximum number of frames to buffer per STA */
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
index 6f4fa9d..0162400 100644
--- a/drivers/net/wireless/hostap/hostap_common.h
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -1,6 +1,9 @@
 #ifndef HOSTAP_COMMON_H
 #define HOSTAP_COMMON_H
 
+#include <linux/types.h>
+#include <linux/if_ether.h>
+
 #define BIT(x) (1 << (x))
 
 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index 7ed3425..c090a5a 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -21,15 +21,10 @@
 #define PRISM2_DOWNLOAD_SUPPORT
 #endif
 
-#ifdef PRISM2_DOWNLOAD_SUPPORT
-/* Allow writing firmware images into flash, i.e., to non-volatile storage.
- * Before you enable this option, you should make absolutely sure that you are
- * using prism2_srec utility that comes with THIS version of the driver!
- * In addition, please note that it is possible to kill your card with
- * non-volatile download if you are using incorrect image. This feature has not
- * been fully tested, so please be careful with it. */
-/* #define PRISM2_NON_VOLATILE_DOWNLOAD */
-#endif /* PRISM2_DOWNLOAD_SUPPORT */
+/* Allow kernel configuration to enable non-volatile download support. */
+#ifdef CONFIG_HOSTAP_FIRMWARE_NVRAM
+#define PRISM2_NON_VOLATILE_DOWNLOAD
+#endif
 
 /* Save low-level I/O for debugging. This should not be enabled in normal use.
  */
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
index 5aa998f..50f72d8 100644
--- a/drivers/net/wireless/hostap/hostap_info.c
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -1,5 +1,8 @@
 /* Host AP driver Info Frame processing (part of hostap.o module) */
 
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
 
 /* Called only as a tasklet (software IRQ) */
 static void prism2_info_commtallies16(local_info_t *local, unsigned char *buf,
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 2617d70..f3e0ce1 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1,11 +1,13 @@
 /* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */
 
-#ifdef in_atomic
-/* Get kernel_locked() for in_atomic() */
+#include <linux/types.h>
 #include <linux/smp_lock.h>
-#endif
 #include <linux/ethtool.h>
+#include <net/ieee80211_crypt.h>
 
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
 
 static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
 {
@@ -3910,7 +3912,7 @@
 		 local->sta_fw_ver & 0xff);
 }
 
-static struct ethtool_ops prism2_ethtool_ops = {
+struct ethtool_ops prism2_ethtool_ops = {
 	.get_drvinfo = prism2_get_drvinfo
 };
 
@@ -3985,7 +3987,7 @@
 	(iw_handler) prism2_ioctl_priv_readmif,		/* 3 */
 };
 
-static const struct iw_handler_def hostap_iw_handler_def =
+const struct iw_handler_def hostap_iw_handler_def =
 {
 	.num_standard	= sizeof(prism2_handler) / sizeof(iw_handler),
 	.num_private	= sizeof(prism2_private_handler) / sizeof(iw_handler),
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 3d2ea61..8dd4c44 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -24,6 +24,7 @@
 #include <linux/kmod.h>
 #include <linux/rtnetlink.h>
 #include <linux/wireless.h>
+#include <linux/etherdevice.h>
 #include <net/iw_handler.h>
 #include <net/ieee80211.h>
 #include <net/ieee80211_crypt.h>
@@ -47,57 +48,6 @@
 #define PRISM2_MAX_MTU (PRISM2_MAX_FRAME_SIZE - (6 /* LLC */ + 8 /* WEP */))
 
 
-/* hostap.c */
-static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
-			  int rtnl_locked);
-static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
-			  int rtnl_locked, int do_not_remove);
-
-/* hostap_ap.c */
-static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
-				  struct iw_quality qual[], int buf_size,
-				  int aplist);
-static int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
-static int prism2_hostapd(struct ap_data *ap,
-			  struct prism2_hostapd_param *param);
-static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
-				struct ieee80211_crypt_data ***crypt);
-static void ap_control_kickall(struct ap_data *ap);
-#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
-static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
-			      u8 *mac);
-static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
-			      u8 *mac);
-static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
-static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
-			       u8 *mac);
-#endif /* !PRISM2_NO_KERNEL_IEEE80211_MGMT */
-
-
-static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
-				  2447, 2452, 2457, 2462, 2467, 2472, 2484 };
-#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))
-
-
-/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
-/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
-static unsigned char rfc1042_header[] =
-{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-static unsigned char bridge_tunnel_header[] =
-{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
-/* No encapsulation header if EtherType < 0x600 (=length) */
-
-
-/* FIX: these could be compiled separately and linked together to hostap.o */
-#include "hostap_ap.c"
-#include "hostap_info.c"
-#include "hostap_ioctl.c"
-#include "hostap_proc.c"
-#include "hostap_80211_rx.c"
-#include "hostap_80211_tx.c"
-
-
 struct net_device * hostap_add_interface(struct local_info *local,
 					 int type, int rtnl_locked,
 					 const char *prefix,
@@ -196,8 +146,8 @@
 }
 
 
-static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
-			  int rtnl_locked)
+int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+		   int rtnl_locked)
 {
 	struct net_device *dev;
 	struct list_head *ptr;
@@ -258,8 +208,8 @@
 }
 
 
-static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
-			  int rtnl_locked, int do_not_remove)
+int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+		   int rtnl_locked, int do_not_remove)
 {
 	unsigned long flags;
 	struct list_head *ptr;
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index a0a4cbd..d1d8ce0 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -1,5 +1,12 @@
 /* /proc routines for Host AP driver */
 
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <net/ieee80211_crypt.h>
+
+#include "hostap_wlan.h"
+#include "hostap.h"
+
 #define PROC_LIMIT (PAGE_SIZE - 80)
 
 
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index cfd8015..87a54aa 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -1,6 +1,10 @@
 #ifndef HOSTAP_WLAN_H
 #define HOSTAP_WLAN_H
 
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <net/iw_handler.h>
+
 #include "hostap_config.h"
 #include "hostap_common.h"
 
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 7518384..8bf0276 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -5735,70 +5735,6 @@
 	return &priv->ieee->stats;
 }
 
-#if WIRELESS_EXT < 18
-/* Support for wpa_supplicant before WE-18, deprecated. */
-
-/* following definitions must match definitions in driver_ipw.c */
-
-#define IPW2100_IOCTL_WPA_SUPPLICANT		SIOCIWFIRSTPRIV+30
-
-#define IPW2100_CMD_SET_WPA_PARAM		1
-#define	IPW2100_CMD_SET_WPA_IE			2
-#define IPW2100_CMD_SET_ENCRYPTION		3
-#define IPW2100_CMD_MLME			4
-
-#define IPW2100_PARAM_WPA_ENABLED		1
-#define IPW2100_PARAM_TKIP_COUNTERMEASURES	2
-#define IPW2100_PARAM_DROP_UNENCRYPTED		3
-#define IPW2100_PARAM_PRIVACY_INVOKED		4
-#define IPW2100_PARAM_AUTH_ALGS			5
-#define IPW2100_PARAM_IEEE_802_1X		6
-
-#define IPW2100_MLME_STA_DEAUTH			1
-#define IPW2100_MLME_STA_DISASSOC		2
-
-#define IPW2100_CRYPT_ERR_UNKNOWN_ALG		2
-#define IPW2100_CRYPT_ERR_UNKNOWN_ADDR		3
-#define IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED	4
-#define IPW2100_CRYPT_ERR_KEY_SET_FAILED	5
-#define IPW2100_CRYPT_ERR_TX_KEY_SET_FAILED	6
-#define IPW2100_CRYPT_ERR_CARD_CONF_FAILED	7
-
-#define	IPW2100_CRYPT_ALG_NAME_LEN		16
-
-struct ipw2100_param {
-	u32 cmd;
-	u8 sta_addr[ETH_ALEN];
-	union {
-		struct {
-			u8 name;
-			u32 value;
-		} wpa_param;
-		struct {
-			u32 len;
-			u8 reserved[32];
-			u8 data[0];
-		} wpa_ie;
-		struct {
-			u32 command;
-			u32 reason_code;
-		} mlme;
-		struct {
-			u8 alg[IPW2100_CRYPT_ALG_NAME_LEN];
-			u8 set_tx;
-			u32 err;
-			u8 idx;
-			u8 seq[8];	/* sequence counter (set: RX, get: TX) */
-			u16 key_len;
-			u8 key[0];
-		} crypt;
-
-	} u;
-};
-
-/* end of driver_ipw.c code */
-#endif				/* WIRELESS_EXT < 18 */
-
 static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value)
 {
 	/* This is called when wpa_supplicant loads and closes the driver
@@ -5807,11 +5743,6 @@
 	return 0;
 }
 
-#if WIRELESS_EXT < 18
-#define IW_AUTH_ALG_OPEN_SYSTEM			0x1
-#define IW_AUTH_ALG_SHARED_KEY			0x2
-#endif
-
 static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
 {
 
@@ -5855,360 +5786,6 @@
 	ipw2100_set_wpa_ie(priv, &frame, 0);
 }
 
-#if WIRELESS_EXT < 18
-static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value)
-{
-	struct ipw2100_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_crypt_data *crypt;
-	unsigned long flags;
-	int ret = 0;
-
-	switch (name) {
-	case IPW2100_PARAM_WPA_ENABLED:
-		ret = ipw2100_wpa_enable(priv, value);
-		break;
-
-	case IPW2100_PARAM_TKIP_COUNTERMEASURES:
-		crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
-		if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
-			break;
-
-		flags = crypt->ops->get_flags(crypt->priv);
-
-		if (value)
-			flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
-		else
-			flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
-
-		crypt->ops->set_flags(flags, crypt->priv);
-
-		break;
-
-	case IPW2100_PARAM_DROP_UNENCRYPTED:{
-			/* See IW_AUTH_DROP_UNENCRYPTED handling for details */
-			struct ieee80211_security sec = {
-				.flags = SEC_ENABLED,
-				.enabled = value,
-			};
-			priv->ieee->drop_unencrypted = value;
-			/* We only change SEC_LEVEL for open mode. Others
-			 * are set by ipw_wpa_set_encryption.
-			 */
-			if (!value) {
-				sec.flags |= SEC_LEVEL;
-				sec.level = SEC_LEVEL_0;
-			} else {
-				sec.flags |= SEC_LEVEL;
-				sec.level = SEC_LEVEL_1;
-			}
-			if (priv->ieee->set_security)
-				priv->ieee->set_security(priv->ieee->dev, &sec);
-			break;
-		}
-
-	case IPW2100_PARAM_PRIVACY_INVOKED:
-		priv->ieee->privacy_invoked = value;
-		break;
-
-	case IPW2100_PARAM_AUTH_ALGS:
-		ret = ipw2100_wpa_set_auth_algs(priv, value);
-		break;
-
-	case IPW2100_PARAM_IEEE_802_1X:
-		priv->ieee->ieee802_1x = value;
-		break;
-
-	default:
-		printk(KERN_ERR DRV_NAME ": %s: Unknown WPA param: %d\n",
-		       dev->name, name);
-		ret = -EOPNOTSUPP;
-	}
-
-	return ret;
-}
-
-static int ipw2100_wpa_mlme(struct net_device *dev, int command, int reason)
-{
-
-	struct ipw2100_priv *priv = ieee80211_priv(dev);
-	int ret = 0;
-
-	switch (command) {
-	case IPW2100_MLME_STA_DEAUTH:
-		// silently ignore
-		break;
-
-	case IPW2100_MLME_STA_DISASSOC:
-		ipw2100_disassociate_bssid(priv);
-		break;
-
-	default:
-		printk(KERN_ERR DRV_NAME ": %s: Unknown MLME request: %d\n",
-		       dev->name, command);
-		ret = -EOPNOTSUPP;
-	}
-
-	return ret;
-}
-
-static int ipw2100_wpa_set_wpa_ie(struct net_device *dev,
-				  struct ipw2100_param *param, int plen)
-{
-
-	struct ipw2100_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = priv->ieee;
-	u8 *buf;
-
-	if (!ieee->wpa_enabled)
-		return -EOPNOTSUPP;
-
-	if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
-	    (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
-		return -EINVAL;
-
-	if (param->u.wpa_ie.len) {
-		buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
-
-		memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
-
-		kfree(ieee->wpa_ie);
-		ieee->wpa_ie = buf;
-		ieee->wpa_ie_len = param->u.wpa_ie.len;
-
-	} else {
-		kfree(ieee->wpa_ie);
-		ieee->wpa_ie = NULL;
-		ieee->wpa_ie_len = 0;
-	}
-
-	ipw2100_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
-
-	return 0;
-}
-
-/* implementation borrowed from hostap driver */
-
-static int ipw2100_wpa_set_encryption(struct net_device *dev,
-				      struct ipw2100_param *param,
-				      int param_len)
-{
-	int ret = 0;
-	struct ipw2100_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = priv->ieee;
-	struct ieee80211_crypto_ops *ops;
-	struct ieee80211_crypt_data **crypt;
-
-	struct ieee80211_security sec = {
-		.flags = 0,
-	};
-
-	param->u.crypt.err = 0;
-	param->u.crypt.alg[IPW2100_CRYPT_ALG_NAME_LEN - 1] = '\0';
-
-	if (param_len !=
-	    (int)((char *)param->u.crypt.key - (char *)param) +
-	    param->u.crypt.key_len) {
-		IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len,
-			       param->u.crypt.key_len);
-		return -EINVAL;
-	}
-	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
-	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
-	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
-		if (param->u.crypt.idx >= WEP_KEYS)
-			return -EINVAL;
-		crypt = &ieee->crypt[param->u.crypt.idx];
-	} else {
-		return -EINVAL;
-	}
-
-	sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
-	if (strcmp(param->u.crypt.alg, "none") == 0) {
-		if (crypt) {
-			sec.enabled = 0;
-			sec.encrypt = 0;
-			sec.level = SEC_LEVEL_0;
-			sec.flags |= SEC_LEVEL;
-			ieee80211_crypt_delayed_deinit(ieee, crypt);
-		}
-		goto done;
-	}
-	sec.enabled = 1;
-	sec.encrypt = 1;
-
-	ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-	if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
-		request_module("ieee80211_crypt_wep");
-		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-	} else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
-		request_module("ieee80211_crypt_tkip");
-		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-	} else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
-		request_module("ieee80211_crypt_ccmp");
-		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-	}
-	if (ops == NULL) {
-		IPW_DEBUG_INFO("%s: unknown crypto alg '%s'\n",
-			       dev->name, param->u.crypt.alg);
-		param->u.crypt.err = IPW2100_CRYPT_ERR_UNKNOWN_ALG;
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (*crypt == NULL || (*crypt)->ops != ops) {
-		struct ieee80211_crypt_data *new_crypt;
-
-		ieee80211_crypt_delayed_deinit(ieee, crypt);
-
-		new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL);
-		if (new_crypt == NULL) {
-			ret = -ENOMEM;
-			goto done;
-		}
-		new_crypt->ops = ops;
-		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
-			new_crypt->priv =
-			    new_crypt->ops->init(param->u.crypt.idx);
-
-		if (new_crypt->priv == NULL) {
-			kfree(new_crypt);
-			param->u.crypt.err =
-			    IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED;
-			ret = -EINVAL;
-			goto done;
-		}
-
-		*crypt = new_crypt;
-	}
-
-	if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
-	    (*crypt)->ops->set_key(param->u.crypt.key,
-				   param->u.crypt.key_len, param->u.crypt.seq,
-				   (*crypt)->priv) < 0) {
-		IPW_DEBUG_INFO("%s: key setting failed\n", dev->name);
-		param->u.crypt.err = IPW2100_CRYPT_ERR_KEY_SET_FAILED;
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (param->u.crypt.set_tx) {
-		ieee->tx_keyidx = param->u.crypt.idx;
-		sec.active_key = param->u.crypt.idx;
-		sec.flags |= SEC_ACTIVE_KEY;
-	}
-
-	if (ops->name != NULL) {
-
-		if (strcmp(ops->name, "WEP") == 0) {
-			memcpy(sec.keys[param->u.crypt.idx],
-			       param->u.crypt.key, param->u.crypt.key_len);
-			sec.key_sizes[param->u.crypt.idx] =
-			    param->u.crypt.key_len;
-			sec.flags |= (1 << param->u.crypt.idx);
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_1;
-		} else if (strcmp(ops->name, "TKIP") == 0) {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_2;
-		} else if (strcmp(ops->name, "CCMP") == 0) {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_3;
-		}
-	}
-      done:
-	if (ieee->set_security)
-		ieee->set_security(ieee->dev, &sec);
-
-	/* Do not reset port if card is in Managed mode since resetting will
-	 * generate new IEEE 802.11 authentication which may end up in looping
-	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
-	 * configuration (for example... Prism2), implement the reset_port in
-	 * the callbacks structures used to initialize the 802.11 stack. */
-	if (ieee->reset_on_keychange &&
-	    ieee->iw_mode != IW_MODE_INFRA &&
-	    ieee->reset_port && ieee->reset_port(dev)) {
-		IPW_DEBUG_INFO("%s: reset_port failed\n", dev->name);
-		param->u.crypt.err = IPW2100_CRYPT_ERR_CARD_CONF_FAILED;
-		return -EINVAL;
-	}
-
-	return ret;
-}
-
-static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p)
-{
-
-	struct ipw2100_param *param;
-	int ret = 0;
-
-	IPW_DEBUG_IOCTL("wpa_supplicant: len=%d\n", p->length);
-
-	if (p->length < sizeof(struct ipw2100_param) || !p->pointer)
-		return -EINVAL;
-
-	param = (struct ipw2100_param *)kmalloc(p->length, GFP_KERNEL);
-	if (param == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(param, p->pointer, p->length)) {
-		kfree(param);
-		return -EFAULT;
-	}
-
-	switch (param->cmd) {
-
-	case IPW2100_CMD_SET_WPA_PARAM:
-		ret = ipw2100_wpa_set_param(dev, param->u.wpa_param.name,
-					    param->u.wpa_param.value);
-		break;
-
-	case IPW2100_CMD_SET_WPA_IE:
-		ret = ipw2100_wpa_set_wpa_ie(dev, param, p->length);
-		break;
-
-	case IPW2100_CMD_SET_ENCRYPTION:
-		ret = ipw2100_wpa_set_encryption(dev, param, p->length);
-		break;
-
-	case IPW2100_CMD_MLME:
-		ret = ipw2100_wpa_mlme(dev, param->u.mlme.command,
-				       param->u.mlme.reason_code);
-		break;
-
-	default:
-		printk(KERN_ERR DRV_NAME
-		       ": %s: Unknown WPA supplicant request: %d\n", dev->name,
-		       param->cmd);
-		ret = -EOPNOTSUPP;
-
-	}
-
-	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
-		ret = -EFAULT;
-
-	kfree(param);
-	return ret;
-}
-
-static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct iwreq *wrq = (struct iwreq *)rq;
-	int ret = -1;
-	switch (cmd) {
-	case IPW2100_IOCTL_WPA_SUPPLICANT:
-		ret = ipw2100_wpa_supplicant(dev, &wrq->u.data);
-		return ret;
-
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return -EOPNOTSUPP;
-}
-#endif				/* WIRELESS_EXT < 18 */
-
 static void ipw_ethtool_get_drvinfo(struct net_device *dev,
 				    struct ethtool_drvinfo *info)
 {
@@ -6337,9 +5914,6 @@
 	dev->open = ipw2100_open;
 	dev->stop = ipw2100_close;
 	dev->init = ipw2100_net_init;
-#if WIRELESS_EXT < 18
-	dev->do_ioctl = ipw2100_ioctl;
-#endif
 	dev->get_stats = ipw2100_stats;
 	dev->ethtool_ops = &ipw2100_ethtool_ops;
 	dev->tx_timeout = ipw2100_tx_timeout;
@@ -7855,7 +7429,6 @@
 	return 0;
 }
 
-#if WIRELESS_EXT > 17
 /*
  * WE-18 WPA support
  */
@@ -8117,7 +7690,6 @@
 	}
 	return 0;
 }
-#endif				/* WIRELESS_EXT > 17 */
 
 /*
  *
@@ -8350,11 +7922,7 @@
 	NULL,			/* SIOCWIWTHRSPY */
 	ipw2100_wx_set_wap,	/* SIOCSIWAP */
 	ipw2100_wx_get_wap,	/* SIOCGIWAP */
-#if WIRELESS_EXT > 17
 	ipw2100_wx_set_mlme,	/* SIOCSIWMLME */
-#else
-	NULL,			/* -- hole -- */
-#endif
 	NULL,			/* SIOCGIWAPLIST -- deprecated */
 	ipw2100_wx_set_scan,	/* SIOCSIWSCAN */
 	ipw2100_wx_get_scan,	/* SIOCGIWSCAN */
@@ -8378,7 +7946,6 @@
 	ipw2100_wx_get_encode,	/* SIOCGIWENCODE */
 	ipw2100_wx_set_power,	/* SIOCSIWPOWER */
 	ipw2100_wx_get_power,	/* SIOCGIWPOWER */
-#if WIRELESS_EXT > 17
 	NULL,			/* -- hole -- */
 	NULL,			/* -- hole -- */
 	ipw2100_wx_set_genie,	/* SIOCSIWGENIE */
@@ -8388,7 +7955,6 @@
 	ipw2100_wx_set_encodeext,	/* SIOCSIWENCODEEXT */
 	ipw2100_wx_get_encodeext,	/* SIOCGIWENCODEEXT */
 	NULL,			/* SIOCSIWPMKSA */
-#endif
 };
 
 #define IPW2100_PRIV_SET_MONITOR	SIOCIWFIRSTPRIV
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 819be2b..4c28e33 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -8936,14 +8936,12 @@
 	IPW_DEBUG_HC("starting request direct scan!\n");
 
 	if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
-		err = wait_event_interruptible(priv->wait_state,
-					       !(priv->
-						 status & (STATUS_SCANNING |
-							   STATUS_SCAN_ABORTING)));
-		if (err) {
-			IPW_DEBUG_HC("aborting direct scan");
-			goto done;
-		}
+		/* We should not sleep here; otherwise we will block most
+		 * of the system (for instance, we hold rtnl_lock when we
+		 * get here).
+		 */
+		err = -EAGAIN;
+		goto done;
 	}
 	memset(&scan, 0, sizeof(scan));
 
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 135a156..c5cd61c 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 + 1);
+		dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length);
 	} else {
 		dwrq->flags = 0;
 		dwrq->length = 0;
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index 33d64d2..a8261d8 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -177,7 +177,7 @@
 #endif
 
 			newskb->dev = skb->dev;
-			dev_kfree_skb(skb);
+			dev_kfree_skb_irq(skb);
 			skb = newskb;
 		}
 	}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 319180c..7880d8c 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -1256,7 +1256,7 @@
 	extra[IW_ESSID_MAX_SIZE] = '\0';
 
 	/* Push it out ! */
-	dwrq->length = strlen(extra) + 1;
+	dwrq->length = strlen(extra);
 	dwrq->flags = 1; /* active */
 
 	return 0;
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 7e2039f..cf37362 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -2280,7 +2280,7 @@
 	extra[IW_ESSID_MAX_SIZE] = '\0';
 
 	/* Set the length */
-	wrqu->data.length = strlen(extra) + 1;
+	wrqu->data.length = strlen(extra);
 
 	return 0;
 }
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 605f0df..dda6099 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1142,6 +1142,9 @@
 	case 0x27c4:
 		ich = 7;
 		break;
+	case 0x2828:	/* ICH8M */
+		ich = 8;
+		break;
 	default:
 		/* we do not handle this PCI device */
 		return;
@@ -1161,7 +1164,7 @@
 		else
 			return;			/* not in combined mode */
 	} else {
-		WARN_ON((ich != 6) && (ich != 7));
+		WARN_ON((ich != 6) && (ich != 7) && (ich != 8));
 		tmp &= 0x3;  /* interesting bits 1:0 */
 		if (tmp & (1 << 0))
 			comb = (1 << 2);	/* PATA port 0, SATA port 1 */
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index d113290..19bd346 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -276,6 +276,16 @@
 	  board_ahci }, /* ESB2 */
 	{ PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ICH7-M DH */
+	{ PCI_VENDOR_ID_INTEL, 0x2821, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8 */
+	{ PCI_VENDOR_ID_INTEL, 0x2822, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8 */
+	{ PCI_VENDOR_ID_INTEL, 0x2824, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8 */
+	{ PCI_VENDOR_ID_INTEL, 0x2829, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8M */
+	{ PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8M */
 	{ }	/* terminate list */
 };
 
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 557788e..fc3ca05 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -157,6 +157,9 @@
 	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 
 	{ }	/* terminate list */
 };
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 99bae83..46c4cdb 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -611,6 +611,10 @@
 	if (dev->flags & ATA_DFLAG_PIO) {
 		tf->protocol = ATA_PROT_PIO;
 		index = dev->multi_count ? 0 : 8;
+	} else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
+		/* Unable to use DMA due to host limitation */
+		tf->protocol = ATA_PROT_PIO;
+		index = dev->multi_count ? 0 : 4;
 	} else {
 		tf->protocol = ATA_PROT_DMA;
 		index = 16;
@@ -1051,18 +1055,22 @@
 {
 	u16 modes;
 
-	/* Usual case. Word 53 indicates word 88 is valid */
-	if (adev->id[ATA_ID_FIELD_VALID] & (1 << 2)) {
+	/* Usual case. Word 53 indicates word 64 is valid */
+	if (adev->id[ATA_ID_FIELD_VALID] & (1 << 1)) {
 		modes = adev->id[ATA_ID_PIO_MODES] & 0x03;
 		modes <<= 3;
 		modes |= 0x7;
 		return modes;
 	}
 
-	/* If word 88 isn't valid then Word 51 holds the PIO timing number
-	   for the maximum. Turn it into a mask and return it */
-	modes = (2 << (adev->id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+	/* If word 64 isn't valid then Word 51 high byte holds the PIO timing
+	   number for the maximum. Turn it into a mask and return it */
+	modes = (2 << ((adev->id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF)) - 1 ;
 	return modes;
+	/* But wait.. there's more. Design your standards by committee and
+	   you too can get a free iordy field to process. However its the 
+	   speeds not the modes that are supported... Note drivers using the
+	   timing API will get this right anyway */
 }
 
 struct ata_exec_internal_arg {
@@ -1165,6 +1173,39 @@
 }
 
 /**
+ *	ata_pio_need_iordy	-	check if iordy needed
+ *	@adev: ATA device
+ *
+ *	Check if the current speed of the device requires IORDY. Used
+ *	by various controllers for chip configuration.
+ */
+
+unsigned int ata_pio_need_iordy(const struct ata_device *adev)
+{
+	int pio;
+	int speed = adev->pio_mode - XFER_PIO_0;
+
+	if (speed < 2)
+		return 0;
+	if (speed > 2)
+		return 1;
+		
+	/* If we have no drive specific rule, then PIO 2 is non IORDY */
+
+	if (adev->id[ATA_ID_FIELD_VALID] & 2) {	/* EIDE */
+		pio = adev->id[ATA_ID_EIDE_PIO];
+		/* Is the speed faster than the drive allows non IORDY ? */
+		if (pio) {
+			/* This is cycle times not frequency - watch the logic! */
+			if (pio > 240)	/* PIO2 is 240nS per cycle */
+				return 1;
+			return 0;
+		}
+	}
+	return 0;
+}
+
+/**
  *	ata_dev_identify - obtain IDENTIFY x DEVICE page
  *	@ap: port on which device we wish to probe resides
  *	@device: device bus address, starting at zero
@@ -1415,7 +1456,7 @@
 		ap->udma_mask &= ATA_UDMA5;
 		ap->host->max_sectors = ATA_MAX_SECTORS;
 		ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
-		ap->device->flags |= ATA_DFLAG_LOCK_SECTORS;
+		ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS;
 	}
 
 	if (ap->ops->dev_config)
@@ -3056,10 +3097,21 @@
 static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
 			  unsigned int buflen, int do_write)
 {
-	if (ap->flags & ATA_FLAG_MMIO)
-		ata_mmio_data_xfer(ap, buf, buflen, do_write);
-	else
-		ata_pio_data_xfer(ap, buf, buflen, do_write);
+	/* Make the crap hardware pay the costs not the good stuff */
+	if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) {
+		unsigned long flags;
+		local_irq_save(flags);
+		if (ap->flags & ATA_FLAG_MMIO)
+			ata_mmio_data_xfer(ap, buf, buflen, do_write);
+		else
+			ata_pio_data_xfer(ap, buf, buflen, do_write);
+		local_irq_restore(flags);
+	} else {
+		if (ap->flags & ATA_FLAG_MMIO)
+			ata_mmio_data_xfer(ap, buf, buflen, do_write);
+		else
+			ata_pio_data_xfer(ap, buf, buflen, do_write);
+	}
 }
 
 /**
@@ -5122,6 +5174,7 @@
 EXPORT_SYMBOL_GPL(ata_dev_config);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
+EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
 EXPORT_SYMBOL_GPL(ata_timing_compute);
 EXPORT_SYMBOL_GPL(ata_timing_merge);
 
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 3d1ea09..b0b0a69 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -66,6 +66,7 @@
 	board_2037x		= 0,	/* FastTrak S150 TX2plus */
 	board_20319		= 1,	/* FastTrak S150 TX4 */
 	board_20619		= 2,	/* FastTrak TX4000 */
+	board_20771		= 3,	/* FastTrak TX2300 */
 
 	PDC_HAS_PATA		= (1 << 1), /* PDC20375 has PATA */
 
@@ -190,6 +191,16 @@
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_pata_ops,
 	},
+
+	/* board_20771 */
+	{
+		.sht		= &pdc_ata_sht,
+		.host_flags	= PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &pdc_sata_ops,
+	},
 };
 
 static const struct pci_device_id pdc_ata_pci_tbl[] = {
@@ -226,6 +237,8 @@
 	{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20619 },
 
+	{ PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_20771 },
 	{ }	/* terminate list */
 };
 
@@ -706,6 +719,9 @@
 	case board_2037x:
 		probe_ent->n_ports = 2;
 		break;
+	case board_20771:
+		probe_ent->n_ports = 2;
+		break;
 	case board_20619:
 		probe_ent->n_ports = 4;
 
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 6683735..d847256 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -470,6 +470,7 @@
 	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
 	{ 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+	{ 0x1166, 0x024b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ }
 };
 
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index d9ce8c5..bc36edf 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2595,15 +2595,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 +2608,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_pci.c b/drivers/serial/8250_pci.c
index 589fb07..2a91215 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -940,6 +940,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 +1312,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,
@@ -2272,6 +2279,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..9fd1925 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -301,7 +301,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.
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/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..8bcaebc 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;
 	};
 
 	/*
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/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..91f5524 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:
diff --git a/fs/compat.c b/fs/compat.c
index 2468ac1..18b21b4 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,10 +70,10 @@
 		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(int dfd, char __user *filename, struct compat_timeval __user *t)
 {
 	struct timeval tv[2];
 
@@ -82,14 +84,19 @@
 		    get_user(tv[1].tv_usec, &t[1].tv_usec))
 			return -EFAULT; 
 	} 
-	return do_utimes(filename, t ? tv : NULL);
+	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(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(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,224 @@
 	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_sec, 1000000/HZ);
+			timeout += tv.tv_sec * HZ;
+		}
+	}
+
+	ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+
+	if (tvp) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		tv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
+		tv.tv_sec = timeout;
+		if (copy_to_user(tvp, &tv, sizeof(tv))) {
+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;
+	long 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)) {
+		ts.tv_sec += timeout / HZ;
+		ts.tv_nsec += (timeout % HZ) * (1000000000/HZ);
+		if (ts.tv_nsec >= 1000000000) {
+			ts.tv_sec++;
+			ts.tv_nsec -= 1000000000;
+		}
+		(void)copy_to_user(tsp, &ts, sizeof(ts));
+	}
+
+	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_sec, 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) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		/* Yes, we know it's actually an s64, but it's also positive. */
+		ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
+		ts.tv_sec = timeout;
+		if (copy_to_user(tsp, &ts, sizeof(ts))) {
+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/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/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/inotify.c b/fs/inotify.c
index 2fecb7a..878ccca 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>
 
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/namei.c b/fs/namei.c
index 33fb5bd..4acdac0 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>
 
@@ -1063,7 +1065,8 @@
 }
 
 /* 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;
 
@@ -1083,9 +1086,38 @@
 		}
 		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 file *file;
+		int fput_needed;
+		struct dentry *dentry;
+
+		file = fget_light(dfd, &fput_needed);
+		if (!file) {
+			retval = -EBADF;
+			goto out_fail;
+		}
+
+		dentry = file->f_dentry;
+
+		if (!S_ISDIR(dentry->d_inode->i_mode)) {
+			retval = -ENOTDIR;
+			fput_light(file, fput_needed);
+			goto out_fail;
+		}
+
+		retval = file_permission(file, MAY_EXEC);
+		if (retval) {
+			fput_light(file, fput_needed);
+			goto out_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;
@@ -1094,11 +1126,19 @@
 	if (unlikely(current->audit_context
 		     && nd && nd->dentry && nd->dentry->d_inode))
 		audit_inode(name, nd->dentry->d_inode, flags);
+out_fail:
 	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 +1148,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);
@@ -1126,10 +1166,10 @@
  * @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);
 }
 
@@ -1141,12 +1181,12 @@
  * @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 +1196,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 +1288,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 +1564,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 +1587,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 +1597,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 +1792,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 +1806,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 +1842,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 +1869,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 +1880,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 +1900,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 +1966,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 +1977,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 +2007,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 +2048,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 +2060,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 +2095,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 +2132,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 +2148,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 +2166,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 +2218,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 +2230,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 +2256,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 +2407,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 +2416,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 +2484,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 +2497,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 +2652,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/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..a00fe86 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -192,6 +192,14 @@
 	}
 	if (status)
 		goto out;
+
+	/* Openowner is now set, so sequence id will get bumped.  Now we need
+	 * these checks before we do any creates: */
+	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;
+
 	switch (open->op_claim_type) {
 		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
 			status = nfserr_inval;
@@ -210,6 +218,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 +230,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 +594,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 +628,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 +654,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 +769,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 +795,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/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/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/select.c b/fs/select.c
index f10a103..c0f02d3 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,154 @@
 	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) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		tv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
+		tv.tv_sec = timeout;
+		if (copy_to_user(tvp, &tv, sizeof(tv))) {
+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) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
+		ts.tv_sec = timeout;
+		if (copy_to_user(tsp, &ts, sizeof(ts))) {
+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 *)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 +561,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 +581,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 +628,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 +657,7 @@
 		}
 		i -= pp->len;
 	}
+
 	fdcount = do_poll(nfds, head, &table, timeout);
 
 	/* OK, now copy the revents fields back to user space. */
@@ -547,3 +686,98 @@
 	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) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		/* Yes, we know it's actually an s64, but it's also positive. */
+		ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
+		ts.tv_sec = timeout;
+		if (copy_to_user(tsp, &ts, sizeof(ts))) {
+		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/stat.c b/fs/stat.c
index b8a0e51..24211b0 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,50 @@
 	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)
+
+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;
+}
+
+asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
 {
 	struct kstat stat;
 	int error = vfs_fstat(fd, &stat);
@@ -260,7 +293,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 +302,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 +319,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
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index d1db8c1..1206267 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -336,24 +336,47 @@
 }
 
 /*
- * Submit all of the bios for all of the ioends we have saved up,
- * covering the initial writepage page and also any probed pages.
+ * Submit all of the bios for all of the ioends we have saved up, covering the
+ * initial writepage page and also any probed pages.
+ *
+ * Because we may have multiple ioends spanning a page, we need to start
+ * writeback on all the buffers before we submit them for I/O. If we mark the
+ * buffers as we got, then we can end up with a page that only has buffers
+ * marked async write and I/O complete on can occur before we mark the other
+ * buffers async write.
+ *
+ * The end result of this is that we trip a bug in end_page_writeback() because
+ * we call it twice for the one page as the code in end_buffer_async_write()
+ * assumes that all buffers on the page are started at the same time.
+ *
+ * The fix is two passes across the ioend list - one to start writeback on the
+ * bufferheads, and then the second one submit them for I/O.
  */
 STATIC void
 xfs_submit_ioend(
 	xfs_ioend_t		*ioend)
 {
+	xfs_ioend_t		*head = ioend;
 	xfs_ioend_t		*next;
 	struct buffer_head	*bh;
 	struct bio		*bio;
 	sector_t		lastblock = 0;
 
+	/* Pass 1 - start writeback */
+	do {
+		next = ioend->io_list;
+		for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
+			xfs_start_buffer_writeback(bh);
+		}
+	} while ((ioend = next) != NULL);
+
+	/* Pass 2 - submit I/O */
+	ioend = head;
 	do {
 		next = ioend->io_list;
 		bio = NULL;
 
 		for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
-			xfs_start_buffer_writeback(bh);
 
 			if (!bio) {
  retry:
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-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-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-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/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/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/unistd.h b/include/asm-i386/unistd.h
index 481c3c0..597496e 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -300,8 +300,23 @@
 #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_newfstatat		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_syscalls 295
+#define NR_syscalls 310
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
@@ -417,6 +432,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-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index 7e09d7c..67cdaf3 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -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..a40cdff 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -298,8 +298,10 @@
 #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_syscalls		280
+#define __NR_syscalls		282
 
 #ifdef __KERNEL__
 #define __NR__exit __NR_exit
@@ -444,11 +446,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-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-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/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-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/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index e884336..e87cd83 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -300,7 +300,20 @@
 #define __NR_ia32_inotify_add_watch	292
 #define __NR_ia32_inotify_rm_watch	293
 #define __NR_ia32_migrate_pages		294
+#define __NR_ia32_opanat		295
+#define __NR_ia32_mkdirat		296
+#define __NR_ia32_mknodat		297
+#define __NR_ia32_fchownat		298
+#define __NR_ia32_futimesat		299
+#define __NR_ia32_newfstatat		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 IA32_NR_syscalls 295	/* must be > than biggest syscall! */
+#define IA32_NR_syscalls 308	/* must be > than biggest syscall! */
 
 #endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index e6f8961..436d099 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -573,8 +573,35 @@
 __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_syscall_max __NR_migrate_pages
+#define __NR_syscall_max __NR_faccessat
+
 #ifndef __NO_STUBS
 
 /* user-visible error numbers are in the range -1 - -4095 */
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..84bb449 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1340,7 +1340,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 +1480,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 +1678,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);
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/libata.h b/include/linux/libata.h
index a43c95f..9e5db29 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -126,16 +126,19 @@
 
 	ATA_FLAG_SUSPENDED	= (1 << 12), /* port is suspended */
 
+	ATA_FLAG_PIO_LBA48	= (1 << 13), /* Host DMA engine is LBA28 only */
+	ATA_FLAG_IRQ_MASK	= (1 << 14), /* Mask IRQ in PIO xfers */
+
 	ATA_QCFLAG_ACTIVE	= (1 << 1), /* cmd not yet ack'd to scsi lyer */
 	ATA_QCFLAG_SG		= (1 << 3), /* have s/g table? */
 	ATA_QCFLAG_SINGLE	= (1 << 4), /* no s/g, just a single buffer */
 	ATA_QCFLAG_DMAMAP	= ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
 
 	/* various lengths of time */
-	ATA_TMOUT_EDD		= 5 * HZ,	/* hueristic */
+	ATA_TMOUT_EDD		= 5 * HZ,	/* heuristic */
 	ATA_TMOUT_PIO		= 30 * HZ,
-	ATA_TMOUT_BOOT		= 30 * HZ,	/* hueristic */
-	ATA_TMOUT_BOOT_QUICK	= 7 * HZ,	/* hueristic */
+	ATA_TMOUT_BOOT		= 30 * HZ,	/* heuristic */
+	ATA_TMOUT_BOOT_QUICK	= 7 * HZ,	/* heuristic */
 	ATA_TMOUT_CDB		= 30 * HZ,
 	ATA_TMOUT_CDB_QUICK	= 5 * HZ,
 	ATA_TMOUT_INTERNAL	= 30 * HZ,
@@ -499,6 +502,8 @@
 /*
  * Timing helpers
  */
+
+extern unsigned int ata_pio_need_iordy(const struct ata_device *);
 extern int ata_timing_compute(struct ata_device *, unsigned short,
 			      struct ata_timing *, int, int);
 extern void ata_timing_merge(const struct ata_timing *,
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_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/mmzone.h b/include/linux/mmzone.h
index 34cbefd..93a849f 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -149,15 +149,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/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/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/pci_ids.h b/include/linux/pci_ids.h
index 5403257..ecc1fc1 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1992,6 +1992,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
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/sched.h b/include/linux/sched.h
index 2df1a1a..0cfcd1c 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;
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/swap.h b/include/linux/swap.h
index e92054d..4a99e4a 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,6 +176,17 @@
 extern int shrink_all_memory(int);
 extern int vm_swappiness;
 
+#ifdef CONFIG_NUMA
+extern int zone_reclaim_mode;
+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);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3eed473..e666d60 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -510,9 +510,24 @@
 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);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 7f47212..8352a7c 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -182,6 +182,7 @@
 	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 */
 };
 
 
diff --git a/include/linux/time.h b/include/linux/time.h
index f2aca7e..614dd84 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -74,7 +74,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/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index 03b766a..cd82c3e 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -25,6 +25,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
+#include <net/ieee80211.h>
 #include <asm/atomic.h>
 
 enum {
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index d67c839..a2c5e0b 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -327,7 +327,7 @@
 	__u16			num_private_args;
 
 	/* Array of handlers for standard ioctls
-	 * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
+	 * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT]
 	 */
 	const iw_handler *	standard;
 
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/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..1867290 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -871,3 +871,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/sched.c b/kernel/sched.c
index 788ecce..3ee2ae4 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -3850,6 +3850,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);
 }
 
diff --git a/kernel/signal.c b/kernel/signal.c
index 5dafbd3..d3efafd 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2721,6 +2721,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/sysctl.c b/kernel/sysctl.c
index f5d69b6..cb99a42 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -870,6 +870,17 @@
 		.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	= &zero,
+	},
+#endif
 	{ .ctl_name = 0 }
 };
 
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/mempolicy.c b/mm/mempolicy.c
index 3171f88..7379018 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -185,8 +185,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 +208,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 +227,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 +317,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,51 +531,15 @@
  * 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);
 	}
 }
 
@@ -1000,6 +976,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)
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..df54e2f 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);
@@ -1595,13 +1597,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--;
diff --git a/mm/rmap.c b/mm/rmap.c
index dfbb89f..d85a99d 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)
diff --git a/mm/slab.c b/mm/slab.c
index 9374293..6f8495e 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -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>
@@ -631,7 +633,7 @@
 };
 
 /* Guard access to the cache-chain. */
-static struct semaphore cache_chain_sem;
+static DEFINE_MUTEX(cache_chain_mutex);
 static struct list_head cache_chain;
 
 /*
@@ -772,6 +774,8 @@
 }
 
 #ifdef CONFIG_NUMA
+static void *__cache_alloc_node(kmem_cache_t *, gfp_t, int);
+
 static inline struct array_cache **alloc_alien_cache(int node, int limit)
 {
 	struct array_cache **ac_ptr;
@@ -857,7 +861,7 @@
 
 	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
@@ -912,7 +916,7 @@
 				l3->shared = nc;
 			}
 		}
-		up(&cache_chain_sem);
+		mutex_unlock(&cache_chain_mutex);
 		break;
 	case CPU_ONLINE:
 		start_cpu_timer(cpu);
@@ -921,7 +925,7 @@
 	case CPU_DEAD:
 		/* 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;
@@ -973,13 +977,13 @@
 			spin_unlock_irq(&cachep->spinlock);
 			kfree(nc);
 		}
-		up(&cache_chain_sem);
+		mutex_unlock(&cache_chain_mutex);
 		break;
 #endif
 	}
 	return NOTIFY_OK;
       bad:
-	up(&cache_chain_sem);
+	mutex_unlock(&cache_chain_mutex);
 	return NOTIFY_BAD;
 }
 
@@ -1047,7 +1051,6 @@
 	 */
 
 	/* 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();
@@ -1168,10 +1171,10 @@
 	/* 6) resize the head arrays to their final sizes */
 	{
 		kmem_cache_t *cachep;
-		down(&cache_chain_sem);
+		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! */
@@ -1590,7 +1593,7 @@
 		BUG();
 	}
 
-	down(&cache_chain_sem);
+	mutex_lock(&cache_chain_mutex);
 
 	list_for_each(p, &cache_chain) {
 		kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
@@ -1856,7 +1859,7 @@
 	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);
 	return cachep;
 }
 EXPORT_SYMBOL(kmem_cache_create);
@@ -2044,18 +2047,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;
 	}
@@ -2570,6 +2573,15 @@
 	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);
 	if (likely(ac->avail)) {
@@ -3314,7 +3326,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 +3334,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);
@@ -3393,7 +3405,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 +3441,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;
@@ -3451,7 +3463,7 @@
 
 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)
@@ -3603,7 +3615,7 @@
 		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);
@@ -3620,7 +3632,7 @@
 			break;
 		}
 	}
-	up(&cache_chain_sem);
+	mutex_unlock(&cache_chain_mutex);
 	if (res >= 0)
 		res = count;
 	return res;
diff --git a/mm/swap.c b/mm/swap.c
index cbb48e7..bc2442a 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -174,6 +174,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.
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 957fef4..f1e69c3 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);
 
@@ -1161,7 +1162,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 +1181,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 +1210,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 +1239,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 +1541,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 +1567,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..2e34b61 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
@@ -458,6 +461,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;
 		}
@@ -586,7 +591,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.
  */
@@ -760,46 +765,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 +823,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++;
 		}
 	}
 
@@ -1177,6 +1171,7 @@
 
 	sc.gfp_mask = gfp_mask;
 	sc.may_writepage = 0;
+	sc.may_swap = 1;
 
 	inc_page_state(allocstall);
 
@@ -1279,6 +1274,7 @@
 	total_reclaimed = 0;
 	sc.gfp_mask = GFP_KERNEL;
 	sc.may_writepage = 0;
+	sc.may_swap = 1;
 	sc.nr_mapped = read_page_state(nr_mapped);
 
 	inc_page_state(pageoutrun);
@@ -1576,3 +1572,71 @@
 }
 
 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;
+
+/*
+ * Mininum time between zone reclaim scans
+ */
+#define ZONE_RECLAIM_INTERVAL HZ/2
+/*
+ * 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 = 1 << order;
+	struct task_struct *p = current;
+	struct reclaim_state reclaim_state;
+	struct scan_control sc = {
+		.gfp_mask	= gfp_mask,
+		.may_writepage	= 0,
+		.may_swap	= 0,
+		.nr_mapped	= read_page_state(nr_mapped),
+		.nr_scanned	= 0,
+		.nr_reclaimed	= 0,
+		.priority	= 0
+	};
+
+	if (!(gfp_mask & __GFP_WAIT) ||
+		zone->zone_pgdat->node_id != numa_node_id() ||
+		zone->all_unreclaimable ||
+		atomic_read(&zone->reclaim_in_progress) > 0)
+			return 0;
+
+	if (time_before(jiffies,
+		zone->last_unsuccessful_zone_reclaim + ZONE_RECLAIM_INTERVAL))
+			return 0;
+
+	disable_swap_token();
+
+	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;
+	shrink_zone(zone, &sc);
+	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/Kconfig b/net/Kconfig
index 9296b269..bc603d9 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -150,6 +150,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 +160,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/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/ipv4/igmp.c b/net/ipv4/igmp.c
index 192092b..d8ce713 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);
 }
@@ -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 = 0;
+
+				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/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/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/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/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,}
 };